comparison liboctave/array/fCMatrix.cc @ 15271:648dabbb4c6b

build: Refactor liboctave into multiple subdirectories. Move libcruft into liboctave. * array/Array-C.cc, array/Array-b.cc, array/Array-ch.cc, array/Array-d.cc, array/Array-f.cc, array/Array-fC.cc, array/Array-i.cc, array/Array-idx-vec.cc, array/Array-s.cc, array/Array-str.cc, array/Array-util.cc, array/Array-util.h, array/Array-voidp.cc, array/Array.cc, array/Array.h, array/Array2.h, array/Array3.h, array/ArrayN.h, array/CColVector.cc, array/CColVector.h, array/CDiagMatrix.cc, array/CDiagMatrix.h, array/CMatrix.cc, array/CMatrix.h, array/CNDArray.cc, array/CNDArray.h, array/CRowVector.cc, array/CRowVector.h, array/CSparse.cc, array/CSparse.h, array/DiagArray2.cc, array/DiagArray2.h, array/MArray-C.cc, array/MArray-d.cc, array/MArray-decl.h, array/MArray-defs.h, array/MArray-f.cc, array/MArray-fC.cc, array/MArray-i.cc, array/MArray-s.cc, array/MArray.cc, array/MArray.h, array/MArray2.h, array/MArrayN.h, array/MDiagArray2.cc, array/MDiagArray2.h, array/MSparse-C.cc, array/MSparse-d.cc, array/MSparse-defs.h, array/MSparse.cc, array/MSparse.h, array/Matrix.h, array/MatrixType.cc, array/MatrixType.h, array/PermMatrix.cc, array/PermMatrix.h, array/Range.cc, array/Range.h, array/Sparse-C.cc, array/Sparse-b.cc, array/Sparse-d.cc, array/Sparse.cc, array/Sparse.h, array/boolMatrix.cc, array/boolMatrix.h, array/boolNDArray.cc, array/boolNDArray.h, array/boolSparse.cc, array/boolSparse.h, array/chMatrix.cc, array/chMatrix.h, array/chNDArray.cc, array/chNDArray.h, array/dColVector.cc, array/dColVector.h, array/dDiagMatrix.cc, array/dDiagMatrix.h, array/dMatrix.cc, array/dMatrix.h, array/dNDArray.cc, array/dNDArray.h, array/dRowVector.cc, array/dRowVector.h, array/dSparse.cc, array/dSparse.h, array/dim-vector.cc, array/dim-vector.h, array/fCColVector.cc, array/fCColVector.h, array/fCDiagMatrix.cc, array/fCDiagMatrix.h, array/fCMatrix.cc, array/fCMatrix.h, array/fCNDArray.cc, array/fCNDArray.h, array/fCRowVector.cc, array/fCRowVector.h, array/fColVector.cc, array/fColVector.h, array/fDiagMatrix.cc, array/fDiagMatrix.h, array/fMatrix.cc, array/fMatrix.h, array/fNDArray.cc, array/fNDArray.h, array/fRowVector.cc, array/fRowVector.h, array/idx-vector.cc, array/idx-vector.h, array/int16NDArray.cc, array/int16NDArray.h, array/int32NDArray.cc, array/int32NDArray.h, array/int64NDArray.cc, array/int64NDArray.h, array/int8NDArray.cc, array/int8NDArray.h, array/intNDArray.cc, array/intNDArray.h, array/module.mk, array/uint16NDArray.cc, array/uint16NDArray.h, array/uint32NDArray.cc, array/uint32NDArray.h, array/uint64NDArray.cc, array/uint64NDArray.h, array/uint8NDArray.cc, array/uint8NDArray.h: Moved from liboctave dir to array subdirectory. * cruft/Makefile.am, cruft/amos/README, cruft/amos/cacai.f, cruft/amos/cacon.f, cruft/amos/cairy.f, cruft/amos/casyi.f, cruft/amos/cbesh.f, cruft/amos/cbesi.f, cruft/amos/cbesj.f, cruft/amos/cbesk.f, cruft/amos/cbesy.f, cruft/amos/cbinu.f, cruft/amos/cbiry.f, cruft/amos/cbknu.f, cruft/amos/cbuni.f, cruft/amos/cbunk.f, cruft/amos/ckscl.f, cruft/amos/cmlri.f, cruft/amos/crati.f, cruft/amos/cs1s2.f, cruft/amos/cseri.f, cruft/amos/cshch.f, cruft/amos/cuchk.f, cruft/amos/cunhj.f, cruft/amos/cuni1.f, cruft/amos/cuni2.f, cruft/amos/cunik.f, cruft/amos/cunk1.f, cruft/amos/cunk2.f, cruft/amos/cuoik.f, cruft/amos/cwrsk.f, cruft/amos/dgamln.f, cruft/amos/gamln.f, cruft/amos/module.mk, cruft/amos/xzabs.f, cruft/amos/xzexp.f, cruft/amos/xzlog.f, cruft/amos/xzsqrt.f, cruft/amos/zacai.f, cruft/amos/zacon.f, cruft/amos/zairy.f, cruft/amos/zasyi.f, cruft/amos/zbesh.f, cruft/amos/zbesi.f, cruft/amos/zbesj.f, cruft/amos/zbesk.f, cruft/amos/zbesy.f, cruft/amos/zbinu.f, cruft/amos/zbiry.f, cruft/amos/zbknu.f, cruft/amos/zbuni.f, cruft/amos/zbunk.f, cruft/amos/zdiv.f, cruft/amos/zkscl.f, cruft/amos/zmlri.f, cruft/amos/zmlt.f, cruft/amos/zrati.f, cruft/amos/zs1s2.f, cruft/amos/zseri.f, cruft/amos/zshch.f, cruft/amos/zuchk.f, cruft/amos/zunhj.f, cruft/amos/zuni1.f, cruft/amos/zuni2.f, cruft/amos/zunik.f, cruft/amos/zunk1.f, cruft/amos/zunk2.f, cruft/amos/zuoik.f, cruft/amos/zwrsk.f, cruft/blas-xtra/cconv2.f, cruft/blas-xtra/cdotc3.f, cruft/blas-xtra/cmatm3.f, cruft/blas-xtra/csconv2.f, cruft/blas-xtra/dconv2.f, cruft/blas-xtra/ddot3.f, cruft/blas-xtra/dmatm3.f, cruft/blas-xtra/module.mk, cruft/blas-xtra/sconv2.f, cruft/blas-xtra/sdot3.f, cruft/blas-xtra/smatm3.f, cruft/blas-xtra/xcdotc.f, cruft/blas-xtra/xcdotu.f, cruft/blas-xtra/xddot.f, cruft/blas-xtra/xdnrm2.f, cruft/blas-xtra/xdznrm2.f, cruft/blas-xtra/xerbla.f, cruft/blas-xtra/xscnrm2.f, cruft/blas-xtra/xsdot.f, cruft/blas-xtra/xsnrm2.f, cruft/blas-xtra/xzdotc.f, cruft/blas-xtra/xzdotu.f, cruft/blas-xtra/zconv2.f, cruft/blas-xtra/zdconv2.f, cruft/blas-xtra/zdotc3.f, cruft/blas-xtra/zmatm3.f, cruft/daspk/datv.f, cruft/daspk/dcnst0.f, cruft/daspk/dcnstr.f, cruft/daspk/ddasic.f, cruft/daspk/ddasid.f, cruft/daspk/ddasik.f, cruft/daspk/ddaspk.f, cruft/daspk/ddstp.f, cruft/daspk/ddwnrm.f, cruft/daspk/dfnrmd.f, cruft/daspk/dfnrmk.f, cruft/daspk/dhels.f, cruft/daspk/dheqr.f, cruft/daspk/dinvwt.f, cruft/daspk/dlinsd.f, cruft/daspk/dlinsk.f, cruft/daspk/dmatd.f, cruft/daspk/dnedd.f, cruft/daspk/dnedk.f, cruft/daspk/dnsd.f, cruft/daspk/dnsid.f, cruft/daspk/dnsik.f, cruft/daspk/dnsk.f, cruft/daspk/dorth.f, cruft/daspk/dslvd.f, cruft/daspk/dslvk.f, cruft/daspk/dspigm.f, cruft/daspk/dyypnw.f, cruft/daspk/module.mk, cruft/dasrt/ddasrt.f, cruft/dasrt/drchek.f, cruft/dasrt/droots.f, cruft/dasrt/module.mk, cruft/dassl/ddaini.f, cruft/dassl/ddajac.f, cruft/dassl/ddanrm.f, cruft/dassl/ddaslv.f, cruft/dassl/ddassl.f, cruft/dassl/ddastp.f, cruft/dassl/ddatrp.f, cruft/dassl/ddawts.f, cruft/dassl/module.mk, cruft/fftpack/cfftb.f, cruft/fftpack/cfftb1.f, cruft/fftpack/cfftf.f, cruft/fftpack/cfftf1.f, cruft/fftpack/cffti.f, cruft/fftpack/cffti1.f, cruft/fftpack/fftpack.doc, cruft/fftpack/module.mk, cruft/fftpack/passb.f, cruft/fftpack/passb2.f, cruft/fftpack/passb3.f, cruft/fftpack/passb4.f, cruft/fftpack/passb5.f, cruft/fftpack/passf.f, cruft/fftpack/passf2.f, cruft/fftpack/passf3.f, cruft/fftpack/passf4.f, cruft/fftpack/passf5.f, cruft/fftpack/zfftb.f, cruft/fftpack/zfftb1.f, cruft/fftpack/zfftf.f, cruft/fftpack/zfftf1.f, cruft/fftpack/zffti.f, cruft/fftpack/zffti1.f, cruft/fftpack/zpassb.f, cruft/fftpack/zpassb2.f, cruft/fftpack/zpassb3.f, cruft/fftpack/zpassb4.f, cruft/fftpack/zpassb5.f, cruft/fftpack/zpassf.f, cruft/fftpack/zpassf2.f, cruft/fftpack/zpassf3.f, cruft/fftpack/zpassf4.f, cruft/fftpack/zpassf5.f, cruft/lapack-xtra/crsf2csf.f, cruft/lapack-xtra/module.mk, cruft/lapack-xtra/xclange.f, cruft/lapack-xtra/xdlamch.f, cruft/lapack-xtra/xdlange.f, cruft/lapack-xtra/xilaenv.f, cruft/lapack-xtra/xslamch.f, cruft/lapack-xtra/xslange.f, cruft/lapack-xtra/xzlange.f, cruft/lapack-xtra/zrsf2csf.f, cruft/link-deps.mk, cruft/misc/blaswrap.c, cruft/misc/cquit.c, cruft/misc/d1mach-tst.for, cruft/misc/d1mach.f, cruft/misc/f77-extern.cc, cruft/misc/f77-fcn.c, cruft/misc/f77-fcn.h, cruft/misc/i1mach.f, cruft/misc/lo-error.c, cruft/misc/lo-error.h, cruft/misc/module.mk, cruft/misc/quit.cc, cruft/misc/quit.h, cruft/misc/r1mach.f, cruft/mkf77def.in, cruft/odepack/cfode.f, cruft/odepack/dlsode.f, cruft/odepack/ewset.f, cruft/odepack/intdy.f, cruft/odepack/module.mk, cruft/odepack/prepj.f, cruft/odepack/scfode.f, cruft/odepack/sewset.f, cruft/odepack/sintdy.f, cruft/odepack/slsode.f, cruft/odepack/solsy.f, cruft/odepack/sprepj.f, cruft/odepack/ssolsy.f, cruft/odepack/sstode.f, cruft/odepack/stode.f, cruft/odepack/svnorm.f, cruft/odepack/vnorm.f, cruft/ordered-qz/README, cruft/ordered-qz/dsubsp.f, cruft/ordered-qz/exchqz.f, cruft/ordered-qz/module.mk, cruft/ordered-qz/sexchqz.f, cruft/ordered-qz/ssubsp.f, cruft/quadpack/dqagi.f, cruft/quadpack/dqagie.f, cruft/quadpack/dqagp.f, cruft/quadpack/dqagpe.f, cruft/quadpack/dqelg.f, cruft/quadpack/dqk15i.f, cruft/quadpack/dqk21.f, cruft/quadpack/dqpsrt.f, cruft/quadpack/module.mk, cruft/quadpack/qagi.f, cruft/quadpack/qagie.f, cruft/quadpack/qagp.f, cruft/quadpack/qagpe.f, cruft/quadpack/qelg.f, cruft/quadpack/qk15i.f, cruft/quadpack/qk21.f, cruft/quadpack/qpsrt.f, cruft/quadpack/xerror.f, cruft/ranlib/Basegen.doc, cruft/ranlib/HOWTOGET, cruft/ranlib/README, cruft/ranlib/advnst.f, cruft/ranlib/genbet.f, cruft/ranlib/genchi.f, cruft/ranlib/genexp.f, cruft/ranlib/genf.f, cruft/ranlib/gengam.f, cruft/ranlib/genmn.f, cruft/ranlib/genmul.f, cruft/ranlib/gennch.f, cruft/ranlib/gennf.f, cruft/ranlib/gennor.f, cruft/ranlib/genprm.f, cruft/ranlib/genunf.f, cruft/ranlib/getcgn.f, cruft/ranlib/getsd.f, cruft/ranlib/ignbin.f, cruft/ranlib/ignlgi.f, cruft/ranlib/ignnbn.f, cruft/ranlib/ignpoi.f, cruft/ranlib/ignuin.f, cruft/ranlib/initgn.f, cruft/ranlib/inrgcm.f, cruft/ranlib/lennob.f, cruft/ranlib/mltmod.f, cruft/ranlib/module.mk, cruft/ranlib/phrtsd.f, cruft/ranlib/qrgnin.f, cruft/ranlib/randlib.chs, cruft/ranlib/randlib.fdoc, cruft/ranlib/ranf.f, cruft/ranlib/setall.f, cruft/ranlib/setant.f, cruft/ranlib/setgmn.f, cruft/ranlib/setsd.f, cruft/ranlib/sexpo.f, cruft/ranlib/sgamma.f, cruft/ranlib/snorm.f, cruft/ranlib/tstbot.for, cruft/ranlib/tstgmn.for, cruft/ranlib/tstmid.for, cruft/ranlib/wrap.f, cruft/slatec-err/fdump.f, cruft/slatec-err/ixsav.f, cruft/slatec-err/j4save.f, cruft/slatec-err/module.mk, cruft/slatec-err/xerclr.f, cruft/slatec-err/xercnt.f, cruft/slatec-err/xerhlt.f, cruft/slatec-err/xermsg.f, cruft/slatec-err/xerprn.f, cruft/slatec-err/xerrwd.f, cruft/slatec-err/xersve.f, cruft/slatec-err/xgetf.f, cruft/slatec-err/xgetua.f, cruft/slatec-err/xsetf.f, cruft/slatec-err/xsetua.f, cruft/slatec-fn/acosh.f, cruft/slatec-fn/albeta.f, cruft/slatec-fn/algams.f, cruft/slatec-fn/alngam.f, cruft/slatec-fn/alnrel.f, cruft/slatec-fn/asinh.f, cruft/slatec-fn/atanh.f, cruft/slatec-fn/betai.f, cruft/slatec-fn/csevl.f, cruft/slatec-fn/d9gmit.f, cruft/slatec-fn/d9lgic.f, cruft/slatec-fn/d9lgit.f, cruft/slatec-fn/d9lgmc.f, cruft/slatec-fn/dacosh.f, cruft/slatec-fn/dasinh.f, cruft/slatec-fn/datanh.f, cruft/slatec-fn/dbetai.f, cruft/slatec-fn/dcsevl.f, cruft/slatec-fn/derf.f, cruft/slatec-fn/derfc.in.f, cruft/slatec-fn/dgami.f, cruft/slatec-fn/dgamit.f, cruft/slatec-fn/dgamlm.f, cruft/slatec-fn/dgamma.f, cruft/slatec-fn/dgamr.f, cruft/slatec-fn/dlbeta.f, cruft/slatec-fn/dlgams.f, cruft/slatec-fn/dlngam.f, cruft/slatec-fn/dlnrel.f, cruft/slatec-fn/dpchim.f, cruft/slatec-fn/dpchst.f, cruft/slatec-fn/erf.f, cruft/slatec-fn/erfc.in.f, cruft/slatec-fn/gami.f, cruft/slatec-fn/gamit.f, cruft/slatec-fn/gamlim.f, cruft/slatec-fn/gamma.f, cruft/slatec-fn/gamr.f, cruft/slatec-fn/initds.f, cruft/slatec-fn/inits.f, cruft/slatec-fn/module.mk, cruft/slatec-fn/pchim.f, cruft/slatec-fn/pchst.f, cruft/slatec-fn/r9gmit.f, cruft/slatec-fn/r9lgic.f, cruft/slatec-fn/r9lgit.f, cruft/slatec-fn/r9lgmc.f, cruft/slatec-fn/xacosh.f, cruft/slatec-fn/xasinh.f, cruft/slatec-fn/xatanh.f, cruft/slatec-fn/xbetai.f, cruft/slatec-fn/xdacosh.f, cruft/slatec-fn/xdasinh.f, cruft/slatec-fn/xdatanh.f, cruft/slatec-fn/xdbetai.f, cruft/slatec-fn/xderf.f, cruft/slatec-fn/xderfc.f, cruft/slatec-fn/xdgami.f, cruft/slatec-fn/xdgamit.f, cruft/slatec-fn/xdgamma.f, cruft/slatec-fn/xerf.f, cruft/slatec-fn/xerfc.f, cruft/slatec-fn/xgamma.f, cruft/slatec-fn/xgmainc.f, cruft/slatec-fn/xsgmainc.f: Moved from top-level libcruft to cruft directory below liboctave. * numeric/CmplxAEPBAL.cc, numeric/CmplxAEPBAL.h, numeric/CmplxCHOL.cc, numeric/CmplxCHOL.h, numeric/CmplxGEPBAL.cc, numeric/CmplxGEPBAL.h, numeric/CmplxHESS.cc, numeric/CmplxHESS.h, numeric/CmplxLU.cc, numeric/CmplxLU.h, numeric/CmplxQR.cc, numeric/CmplxQR.h, numeric/CmplxQRP.cc, numeric/CmplxQRP.h, numeric/CmplxSCHUR.cc, numeric/CmplxSCHUR.h, numeric/CmplxSVD.cc, numeric/CmplxSVD.h, numeric/CollocWt.cc, numeric/CollocWt.h, numeric/DAE.h, numeric/DAEFunc.h, numeric/DAERT.h, numeric/DAERTFunc.h, numeric/DASPK-opts.in, numeric/DASPK.cc, numeric/DASPK.h, numeric/DASRT-opts.in, numeric/DASRT.cc, numeric/DASRT.h, numeric/DASSL-opts.in, numeric/DASSL.cc, numeric/DASSL.h, numeric/DET.h, numeric/EIG.cc, numeric/EIG.h, numeric/LSODE-opts.in, numeric/LSODE.cc, numeric/LSODE.h, numeric/ODE.h, numeric/ODEFunc.h, numeric/ODES.cc, numeric/ODES.h, numeric/ODESFunc.h, numeric/Quad-opts.in, numeric/Quad.cc, numeric/Quad.h, numeric/SparseCmplxCHOL.cc, numeric/SparseCmplxCHOL.h, numeric/SparseCmplxLU.cc, numeric/SparseCmplxLU.h, numeric/SparseCmplxQR.cc, numeric/SparseCmplxQR.h, numeric/SparseQR.cc, numeric/SparseQR.h, numeric/SparsedbleCHOL.cc, numeric/SparsedbleCHOL.h, numeric/SparsedbleLU.cc, numeric/SparsedbleLU.h, numeric/base-aepbal.h, numeric/base-dae.h, numeric/base-de.h, numeric/base-lu.cc, numeric/base-lu.h, numeric/base-min.h, numeric/base-qr.cc, numeric/base-qr.h, numeric/bsxfun-decl.h, numeric/bsxfun-defs.cc, numeric/bsxfun.h, numeric/dbleAEPBAL.cc, numeric/dbleAEPBAL.h, numeric/dbleCHOL.cc, numeric/dbleCHOL.h, numeric/dbleGEPBAL.cc, numeric/dbleGEPBAL.h, numeric/dbleHESS.cc, numeric/dbleHESS.h, numeric/dbleLU.cc, numeric/dbleLU.h, numeric/dbleQR.cc, numeric/dbleQR.h, numeric/dbleQRP.cc, numeric/dbleQRP.h, numeric/dbleSCHUR.cc, numeric/dbleSCHUR.h, numeric/dbleSVD.cc, numeric/dbleSVD.h, numeric/eigs-base.cc, numeric/fCmplxAEPBAL.cc, numeric/fCmplxAEPBAL.h, numeric/fCmplxCHOL.cc, numeric/fCmplxCHOL.h, numeric/fCmplxGEPBAL.cc, numeric/fCmplxGEPBAL.h, numeric/fCmplxHESS.cc, numeric/fCmplxHESS.h, numeric/fCmplxLU.cc, numeric/fCmplxLU.h, numeric/fCmplxQR.cc, numeric/fCmplxQR.h, numeric/fCmplxQRP.cc, numeric/fCmplxQRP.h, numeric/fCmplxSCHUR.cc, numeric/fCmplxSCHUR.h, numeric/fCmplxSVD.cc, numeric/fCmplxSVD.h, numeric/fEIG.cc, numeric/fEIG.h, numeric/floatAEPBAL.cc, numeric/floatAEPBAL.h, numeric/floatCHOL.cc, numeric/floatCHOL.h, numeric/floatGEPBAL.cc, numeric/floatGEPBAL.h, numeric/floatHESS.cc, numeric/floatHESS.h, numeric/floatLU.cc, numeric/floatLU.h, numeric/floatQR.cc, numeric/floatQR.h, numeric/floatQRP.cc, numeric/floatQRP.h, numeric/floatSCHUR.cc, numeric/floatSCHUR.h, numeric/floatSVD.cc, numeric/floatSVD.h, numeric/lo-mappers.cc, numeric/lo-mappers.h, numeric/lo-specfun.cc, numeric/lo-specfun.h, numeric/module.mk, numeric/oct-convn.cc, numeric/oct-convn.h, numeric/oct-fftw.cc, numeric/oct-fftw.h, numeric/oct-norm.cc, numeric/oct-norm.h, numeric/oct-rand.cc, numeric/oct-rand.h, numeric/oct-spparms.cc, numeric/oct-spparms.h, numeric/randgamma.c, numeric/randgamma.h, numeric/randmtzig.c, numeric/randmtzig.h, numeric/randpoisson.c, numeric/randpoisson.h, numeric/sparse-base-chol.cc, numeric/sparse-base-chol.h, numeric/sparse-base-lu.cc, numeric/sparse-base-lu.h, numeric/sparse-dmsolve.cc: Moved from liboctave dir to numeric subdirectory. * operators/Sparse-diag-op-defs.h, operators/Sparse-op-defs.h, operators/Sparse-perm-op-defs.h, operators/config-ops.sh, operators/mk-ops.awk, operators/module.mk, operators/mx-base.h, operators/mx-defs.h, operators/mx-ext.h, operators/mx-inlines.cc, operators/mx-op-decl.h, operators/mx-op-defs.h, operators/mx-ops, operators/sparse-mk-ops.awk, operators/sparse-mx-ops, operators/vx-ops: Moved from liboctave dir to operators subdirectory. * system/dir-ops.cc, system/dir-ops.h, system/file-ops.cc, system/file-ops.h, system/file-stat.cc, system/file-stat.h, system/lo-sysdep.cc, system/lo-sysdep.h, system/mach-info.cc, system/mach-info.h, system/module.mk, system/oct-env.cc, system/oct-env.h, system/oct-group.cc, system/oct-group.h, system/oct-openmp.h, system/oct-passwd.cc, system/oct-passwd.h, system/oct-syscalls.cc, system/oct-syscalls.h, system/oct-time.cc, system/oct-time.h, system/oct-uname.cc, system/oct-uname.h, system/pathlen.h, system/sysdir.h, system/syswait.h, system/tempnam.c, system/tempname.c: Moved from liboctave dir to system subdirectory. * util/base-list.h, util/byte-swap.h, util/caseless-str.h, util/cmd-edit.cc, util/cmd-edit.h, util/cmd-hist.cc, util/cmd-hist.h, util/data-conv.cc, util/data-conv.h, util/f2c-main.c, util/functor.h, util/glob-match.cc, util/glob-match.h, util/kpse.cc, util/lo-array-gripes.cc, util/lo-array-gripes.h, util/lo-cieee.c, util/lo-cutils.c, util/lo-cutils.h, util/lo-ieee.cc, util/lo-ieee.h, util/lo-macros.h, util/lo-math.h, util/lo-traits.h, util/lo-utils.cc, util/lo-utils.h, util/module.mk, util/oct-alloc.cc, util/oct-alloc.h, util/oct-base64.cc, util/oct-base64.h, util/oct-binmap.h, util/oct-cmplx.h, util/oct-glob.cc, util/oct-glob.h, util/oct-inttypes.cc, util/oct-inttypes.h, util/oct-locbuf.cc, util/oct-locbuf.h, util/oct-md5.cc, util/oct-md5.h, util/oct-mem.h, util/oct-mutex.cc, util/oct-mutex.h, util/oct-refcount.h, util/oct-rl-edit.c, util/oct-rl-edit.h, util/oct-rl-hist.c, util/oct-rl-hist.h, util/oct-shlib.cc, util/oct-shlib.h, util/oct-sort.cc, util/oct-sort.h, util/oct-sparse.h, util/pathsearch.cc, util/pathsearch.h, util/regexp.cc, util/regexp.h, util/singleton-cleanup.cc, util/singleton-cleanup.h, util/sparse-sort.cc, util/sparse-sort.h, util/sparse-util.cc, util/sparse-util.h, util/statdefs.h, util/str-vec.cc, util/str-vec.h, util/sun-utils.h: Moved from liboctave dir to util subdirectory. * Makefile.am: Eliminate reference to top-level liboctave directory. * autogen.sh: cd to new liboctave/operators directory to run config-ops.sh. * build-aux/common.mk: Eliminate LIBCRUFT references. * configure.ac: Eliminate libcruft top-level references. Switch test programs to find files in liboctave/cruft subdirectory. * OctaveFAQ.texi, install.txi, mkoctfile.1: Eliminate references to libcruft in docs. * libgui/src/Makefile.am, libinterp/Makefile.am, src/Makefile.am: Update include file locations. Stop linking against libcruft. * libinterp/corefcn/module.mk: Update location of OPT_INC files which are now in numeric/ subdirectory. * libinterp/dldfcn/config-module.awk: Stop linking against libcruft. * libinterp/interpfcn/toplev.cc: Remove reference to LIBCRUFT. * libinterp/link-deps.mk, liboctave/link-deps.mk: Add GNULIB_LINK_DEPS to link dependencies. * libinterp/oct-conf.in.h: Remove reference to OCTAVE_CONF_LIBCRUFT. * liboctave/Makefile.am: Overhaul to use convenience libraries in subdirectories. * scripts/miscellaneous/mkoctfile.m: Eliminate reference to LIBCRUFT. * src/mkoctfile.in.cc, src/mkoctfile.in.sh: Stop linking againt libcruft. Eliminate references to LIBCRUFT.
author Rik <rik@octave.org>
date Fri, 31 Aug 2012 20:00:20 -0700
parents liboctave/fCMatrix.cc@61822c866ba1
children 2137f5638521
comparison
equal deleted inserted replaced
15270:6615a46d90ec 15271:648dabbb4c6b
1 // Matrix manipulations.
2 /*
3
4 Copyright (C) 1994-2012 John W. Eaton
5 Copyright (C) 2008-2009 Jaroslav Hajek
6 Copyright (C) 2009 VZLU Prague, a.s.
7
8 This file is part of Octave.
9
10 Octave is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
14
15 Octave is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with Octave; see the file COPYING. If not, see
22 <http://www.gnu.org/licenses/>.
23
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <cfloat>
31
32 #include <iostream>
33 #include <vector>
34
35 // FIXME
36 #include <sys/types.h>
37
38 #include "Array-util.h"
39 #include "DET.h"
40 #include "f77-fcn.h"
41 #include "fCMatrix.h"
42 #include "fCmplxCHOL.h"
43 #include "fCmplxSCHUR.h"
44 #include "fCmplxSVD.h"
45 #include "functor.h"
46 #include "lo-error.h"
47 #include "lo-ieee.h"
48 #include "lo-mappers.h"
49 #include "lo-utils.h"
50 #include "mx-base.h"
51 #include "mx-fcm-fdm.h"
52 #include "mx-fcm-fs.h"
53 #include "mx-fdm-fcm.h"
54 #include "mx-inlines.cc"
55 #include "mx-op-defs.h"
56 #include "oct-cmplx.h"
57 #include "oct-fftw.h"
58 #include "oct-locbuf.h"
59 #include "oct-norm.h"
60
61 // Fortran functions we call.
62
63 extern "C"
64 {
65 F77_RET_T
66 F77_FUNC (xilaenv, XILAENV) (const octave_idx_type&,
67 F77_CONST_CHAR_ARG_DECL,
68 F77_CONST_CHAR_ARG_DECL,
69 const octave_idx_type&, const octave_idx_type&,
70 const octave_idx_type&, const octave_idx_type&,
71 octave_idx_type&
72 F77_CHAR_ARG_LEN_DECL
73 F77_CHAR_ARG_LEN_DECL);
74
75 F77_RET_T
76 F77_FUNC (cgebal, CGEBAL) (F77_CONST_CHAR_ARG_DECL,
77 const octave_idx_type&, FloatComplex*,
78 const octave_idx_type&, octave_idx_type&,
79 octave_idx_type&, float*, octave_idx_type&
80 F77_CHAR_ARG_LEN_DECL);
81
82 F77_RET_T
83 F77_FUNC (sgebak, SGEBAK) (F77_CONST_CHAR_ARG_DECL,
84 F77_CONST_CHAR_ARG_DECL,
85 const octave_idx_type&, const octave_idx_type&,
86 const octave_idx_type&, float*,
87 const octave_idx_type&, float*,
88 const octave_idx_type&, octave_idx_type&
89 F77_CHAR_ARG_LEN_DECL
90 F77_CHAR_ARG_LEN_DECL);
91
92 F77_RET_T
93 F77_FUNC (cgemm, CGEMM) (F77_CONST_CHAR_ARG_DECL,
94 F77_CONST_CHAR_ARG_DECL,
95 const octave_idx_type&, const octave_idx_type&,
96 const octave_idx_type&, const FloatComplex&,
97 const FloatComplex*, const octave_idx_type&,
98 const FloatComplex*, const octave_idx_type&,
99 const FloatComplex&, FloatComplex*,
100 const octave_idx_type&
101 F77_CHAR_ARG_LEN_DECL
102 F77_CHAR_ARG_LEN_DECL);
103
104 F77_RET_T
105 F77_FUNC (cgemv, CGEMV) (F77_CONST_CHAR_ARG_DECL,
106 const octave_idx_type&, const octave_idx_type&,
107 const FloatComplex&, const FloatComplex*,
108 const octave_idx_type&, const FloatComplex*,
109 const octave_idx_type&, const FloatComplex&,
110 FloatComplex*, const octave_idx_type&
111 F77_CHAR_ARG_LEN_DECL);
112
113 F77_RET_T
114 F77_FUNC (xcdotu, XCDOTU) (const octave_idx_type&, const FloatComplex*,
115 const octave_idx_type&, const FloatComplex*,
116 const octave_idx_type&, FloatComplex&);
117
118 F77_RET_T
119 F77_FUNC (xcdotc, XCDOTC) (const octave_idx_type&, const FloatComplex*,
120 const octave_idx_type&, const FloatComplex*,
121 const octave_idx_type&, FloatComplex&);
122
123 F77_RET_T
124 F77_FUNC (csyrk, CSYRK) (F77_CONST_CHAR_ARG_DECL,
125 F77_CONST_CHAR_ARG_DECL,
126 const octave_idx_type&, const octave_idx_type&,
127 const FloatComplex&, const FloatComplex*,
128 const octave_idx_type&, const FloatComplex&,
129 FloatComplex*, const octave_idx_type&
130 F77_CHAR_ARG_LEN_DECL
131 F77_CHAR_ARG_LEN_DECL);
132
133 F77_RET_T
134 F77_FUNC (cherk, CHERK) (F77_CONST_CHAR_ARG_DECL,
135 F77_CONST_CHAR_ARG_DECL,
136 const octave_idx_type&, const octave_idx_type&,
137 const float&, const FloatComplex*,
138 const octave_idx_type&, const float&,
139 FloatComplex*, const octave_idx_type&
140 F77_CHAR_ARG_LEN_DECL
141 F77_CHAR_ARG_LEN_DECL);
142
143 F77_RET_T
144 F77_FUNC (cgetrf, CGETRF) (const octave_idx_type&, const octave_idx_type&,
145 FloatComplex*, const octave_idx_type&,
146 octave_idx_type*, octave_idx_type&);
147
148 F77_RET_T
149 F77_FUNC (cgetrs, CGETRS) (F77_CONST_CHAR_ARG_DECL,
150 const octave_idx_type&, const octave_idx_type&,
151 FloatComplex*, const octave_idx_type&,
152 const octave_idx_type*, FloatComplex*,
153 const octave_idx_type&, octave_idx_type&
154 F77_CHAR_ARG_LEN_DECL);
155
156 F77_RET_T
157 F77_FUNC (cgetri, CGETRI) (const octave_idx_type&, FloatComplex*,
158 const octave_idx_type&, const octave_idx_type*,
159 FloatComplex*, const octave_idx_type&,
160 octave_idx_type&);
161
162 F77_RET_T
163 F77_FUNC (cgecon, CGECON) (F77_CONST_CHAR_ARG_DECL,
164 const octave_idx_type&, FloatComplex*,
165 const octave_idx_type&, const float&, float&,
166 FloatComplex*, float*, octave_idx_type&
167 F77_CHAR_ARG_LEN_DECL);
168
169 F77_RET_T
170 F77_FUNC (cgelsy, CGELSY) (const octave_idx_type&, const octave_idx_type&,
171 const octave_idx_type&, FloatComplex*,
172 const octave_idx_type&, FloatComplex*,
173 const octave_idx_type&, octave_idx_type*,
174 float&, octave_idx_type&, FloatComplex*,
175 const octave_idx_type&, float*, octave_idx_type&);
176
177 F77_RET_T
178 F77_FUNC (cgelsd, CGELSD) (const octave_idx_type&, const octave_idx_type&,
179 const octave_idx_type&, FloatComplex*,
180 const octave_idx_type&, FloatComplex*,
181 const octave_idx_type&, float*, float&,
182 octave_idx_type&, FloatComplex*,
183 const octave_idx_type&, float*,
184 octave_idx_type*, octave_idx_type&);
185
186 F77_RET_T
187 F77_FUNC (cpotrf, CPOTRF) (F77_CONST_CHAR_ARG_DECL,
188 const octave_idx_type&, FloatComplex*,
189 const octave_idx_type&, octave_idx_type&
190 F77_CHAR_ARG_LEN_DECL);
191
192 F77_RET_T
193 F77_FUNC (cpocon, CPOCON) (F77_CONST_CHAR_ARG_DECL,
194 const octave_idx_type&, FloatComplex*,
195 const octave_idx_type&, const float&, float&,
196 FloatComplex*, float*, octave_idx_type&
197 F77_CHAR_ARG_LEN_DECL);
198
199 F77_RET_T
200 F77_FUNC (cpotrs, CPOTRS) (F77_CONST_CHAR_ARG_DECL,
201 const octave_idx_type&,
202 const octave_idx_type&, const FloatComplex*,
203 const octave_idx_type&, FloatComplex*,
204 const octave_idx_type&, octave_idx_type&
205 F77_CHAR_ARG_LEN_DECL);
206
207 F77_RET_T
208 F77_FUNC (ctrtri, CTRTRI) (F77_CONST_CHAR_ARG_DECL,
209 F77_CONST_CHAR_ARG_DECL,
210 const octave_idx_type&, const FloatComplex*,
211 const octave_idx_type&, octave_idx_type&
212 F77_CHAR_ARG_LEN_DECL
213 F77_CHAR_ARG_LEN_DECL);
214
215 F77_RET_T
216 F77_FUNC (ctrcon, CTRCON) (F77_CONST_CHAR_ARG_DECL,
217 F77_CONST_CHAR_ARG_DECL,
218 F77_CONST_CHAR_ARG_DECL,
219 const octave_idx_type&, const FloatComplex*,
220 const octave_idx_type&, float&, FloatComplex*,
221 float*, octave_idx_type&
222 F77_CHAR_ARG_LEN_DECL
223 F77_CHAR_ARG_LEN_DECL
224 F77_CHAR_ARG_LEN_DECL);
225
226 F77_RET_T
227 F77_FUNC (ctrtrs, CTRTRS) (F77_CONST_CHAR_ARG_DECL,
228 F77_CONST_CHAR_ARG_DECL,
229 F77_CONST_CHAR_ARG_DECL,
230 const octave_idx_type&, const octave_idx_type&,
231 const FloatComplex*, const octave_idx_type&,
232 FloatComplex*, const octave_idx_type&,
233 octave_idx_type&
234 F77_CHAR_ARG_LEN_DECL
235 F77_CHAR_ARG_LEN_DECL
236 F77_CHAR_ARG_LEN_DECL);
237
238 F77_RET_T
239 F77_FUNC (clartg, CLARTG) (const FloatComplex&, const FloatComplex&,
240 float&, FloatComplex&, FloatComplex&);
241
242 F77_RET_T
243 F77_FUNC (ctrsyl, CTRSYL) (F77_CONST_CHAR_ARG_DECL,
244 F77_CONST_CHAR_ARG_DECL,
245 const octave_idx_type&, const octave_idx_type&,
246 const octave_idx_type&, const FloatComplex*,
247 const octave_idx_type&, const FloatComplex*,
248 const octave_idx_type&, const FloatComplex*,
249 const octave_idx_type&, float&, octave_idx_type&
250 F77_CHAR_ARG_LEN_DECL
251 F77_CHAR_ARG_LEN_DECL);
252
253 F77_RET_T
254 F77_FUNC (xclange, XCLANGE) (F77_CONST_CHAR_ARG_DECL,
255 const octave_idx_type&, const octave_idx_type&,
256 const FloatComplex*, const octave_idx_type&,
257 float*, float&
258 F77_CHAR_ARG_LEN_DECL);
259 }
260
261 static const FloatComplex FloatComplex_NaN_result (octave_Float_NaN, octave_Float_NaN);
262
263 // FloatComplex Matrix class
264
265 FloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& a)
266 : MArray<FloatComplex> (a)
267 {
268 }
269
270 FloatComplexMatrix::FloatComplexMatrix (const FloatRowVector& rv)
271 : MArray<FloatComplex> (rv)
272 {
273 }
274
275 FloatComplexMatrix::FloatComplexMatrix (const FloatColumnVector& cv)
276 : MArray<FloatComplex> (cv)
277 {
278 }
279
280 FloatComplexMatrix::FloatComplexMatrix (const FloatDiagMatrix& a)
281 : MArray<FloatComplex> (a.dims (), 0.0)
282 {
283 for (octave_idx_type i = 0; i < a.length (); i++)
284 elem (i, i) = a.elem (i, i);
285 }
286
287 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexRowVector& rv)
288 : MArray<FloatComplex> (rv)
289 {
290 }
291
292 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexColumnVector& cv)
293 : MArray<FloatComplex> (cv)
294 {
295 }
296
297 FloatComplexMatrix::FloatComplexMatrix (const FloatComplexDiagMatrix& a)
298 : MArray<FloatComplex> (a.dims (), 0.0)
299 {
300 for (octave_idx_type i = 0; i < a.length (); i++)
301 elem (i, i) = a.elem (i, i);
302 }
303
304 // FIXME -- could we use a templated mixed-type copy function
305 // here?
306
307 FloatComplexMatrix::FloatComplexMatrix (const boolMatrix& a)
308 : MArray<FloatComplex> (a)
309 {
310 }
311
312 FloatComplexMatrix::FloatComplexMatrix (const charMatrix& a)
313 : MArray<FloatComplex> (a.dims (), 0.0)
314 {
315 for (octave_idx_type i = 0; i < a.rows (); i++)
316 for (octave_idx_type j = 0; j < a.cols (); j++)
317 elem (i, j) = static_cast<unsigned char> (a.elem (i, j));
318 }
319
320 FloatComplexMatrix::FloatComplexMatrix (const FloatMatrix& re,
321 const FloatMatrix& im)
322 : MArray<FloatComplex> (re.dims ())
323 {
324 if (im.rows () != rows () || im.cols () != cols ())
325 (*current_liboctave_error_handler) ("complex: internal error");
326
327 octave_idx_type nel = numel ();
328 for (octave_idx_type i = 0; i < nel; i++)
329 xelem (i) = FloatComplex (re(i), im(i));
330 }
331
332 bool
333 FloatComplexMatrix::operator == (const FloatComplexMatrix& a) const
334 {
335 if (rows () != a.rows () || cols () != a.cols ())
336 return false;
337
338 return mx_inline_equal (length (), data (), a.data ());
339 }
340
341 bool
342 FloatComplexMatrix::operator != (const FloatComplexMatrix& a) const
343 {
344 return !(*this == a);
345 }
346
347 bool
348 FloatComplexMatrix::is_hermitian (void) const
349 {
350 octave_idx_type nr = rows ();
351 octave_idx_type nc = cols ();
352
353 if (is_square () && nr > 0)
354 {
355 for (octave_idx_type i = 0; i < nr; i++)
356 for (octave_idx_type j = i; j < nc; j++)
357 if (elem (i, j) != conj (elem (j, i)))
358 return false;
359
360 return true;
361 }
362
363 return false;
364 }
365
366 // destructive insert/delete/reorder operations
367
368 FloatComplexMatrix&
369 FloatComplexMatrix::insert (const FloatMatrix& a, octave_idx_type r, octave_idx_type c)
370 {
371 octave_idx_type a_nr = a.rows ();
372 octave_idx_type a_nc = a.cols ();
373
374 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())
375 {
376 (*current_liboctave_error_handler) ("range error for insert");
377 return *this;
378 }
379
380 if (a_nr >0 && a_nc > 0)
381 {
382 make_unique ();
383
384 for (octave_idx_type j = 0; j < a_nc; j++)
385 for (octave_idx_type i = 0; i < a_nr; i++)
386 xelem (r+i, c+j) = a.elem (i, j);
387 }
388
389 return *this;
390 }
391
392 FloatComplexMatrix&
393 FloatComplexMatrix::insert (const FloatRowVector& a, octave_idx_type r, octave_idx_type c)
394 {
395 octave_idx_type a_len = a.length ();
396
397 if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())
398 {
399 (*current_liboctave_error_handler) ("range error for insert");
400 return *this;
401 }
402
403 if (a_len > 0)
404 {
405 make_unique ();
406
407 for (octave_idx_type i = 0; i < a_len; i++)
408 xelem (r, c+i) = a.elem (i);
409 }
410
411 return *this;
412 }
413
414 FloatComplexMatrix&
415 FloatComplexMatrix::insert (const FloatColumnVector& a, octave_idx_type r, octave_idx_type c)
416 {
417 octave_idx_type a_len = a.length ();
418
419 if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())
420 {
421 (*current_liboctave_error_handler) ("range error for insert");
422 return *this;
423 }
424
425 if (a_len > 0)
426 {
427 make_unique ();
428
429 for (octave_idx_type i = 0; i < a_len; i++)
430 xelem (r+i, c) = a.elem (i);
431 }
432
433 return *this;
434 }
435
436 FloatComplexMatrix&
437 FloatComplexMatrix::insert (const FloatDiagMatrix& a, octave_idx_type r, octave_idx_type c)
438 {
439 octave_idx_type a_nr = a.rows ();
440 octave_idx_type a_nc = a.cols ();
441
442 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())
443 {
444 (*current_liboctave_error_handler) ("range error for insert");
445 return *this;
446 }
447
448 fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);
449
450 octave_idx_type a_len = a.length ();
451
452 if (a_len > 0)
453 {
454 make_unique ();
455
456 for (octave_idx_type i = 0; i < a_len; i++)
457 xelem (r+i, c+i) = a.elem (i, i);
458 }
459
460 return *this;
461 }
462
463 FloatComplexMatrix&
464 FloatComplexMatrix::insert (const FloatComplexMatrix& a, octave_idx_type r, octave_idx_type c)
465 {
466 Array<FloatComplex>::insert (a, r, c);
467 return *this;
468 }
469
470 FloatComplexMatrix&
471 FloatComplexMatrix::insert (const FloatComplexRowVector& a, octave_idx_type r, octave_idx_type c)
472 {
473 octave_idx_type a_len = a.length ();
474 if (r < 0 || r >= rows () || c < 0 || c + a_len > cols ())
475 {
476 (*current_liboctave_error_handler) ("range error for insert");
477 return *this;
478 }
479
480 for (octave_idx_type i = 0; i < a_len; i++)
481 elem (r, c+i) = a.elem (i);
482
483 return *this;
484 }
485
486 FloatComplexMatrix&
487 FloatComplexMatrix::insert (const FloatComplexColumnVector& a, octave_idx_type r, octave_idx_type c)
488 {
489 octave_idx_type a_len = a.length ();
490
491 if (r < 0 || r + a_len > rows () || c < 0 || c >= cols ())
492 {
493 (*current_liboctave_error_handler) ("range error for insert");
494 return *this;
495 }
496
497 if (a_len > 0)
498 {
499 make_unique ();
500
501 for (octave_idx_type i = 0; i < a_len; i++)
502 xelem (r+i, c) = a.elem (i);
503 }
504
505 return *this;
506 }
507
508 FloatComplexMatrix&
509 FloatComplexMatrix::insert (const FloatComplexDiagMatrix& a, octave_idx_type r, octave_idx_type c)
510 {
511 octave_idx_type a_nr = a.rows ();
512 octave_idx_type a_nc = a.cols ();
513
514 if (r < 0 || r + a_nr > rows () || c < 0 || c + a_nc > cols ())
515 {
516 (*current_liboctave_error_handler) ("range error for insert");
517 return *this;
518 }
519
520 fill (0.0, r, c, r + a_nr - 1, c + a_nc - 1);
521
522 octave_idx_type a_len = a.length ();
523
524 if (a_len > 0)
525 {
526 make_unique ();
527
528 for (octave_idx_type i = 0; i < a_len; i++)
529 xelem (r+i, c+i) = a.elem (i, i);
530 }
531
532 return *this;
533 }
534
535 FloatComplexMatrix&
536 FloatComplexMatrix::fill (float val)
537 {
538 octave_idx_type nr = rows ();
539 octave_idx_type nc = cols ();
540
541 if (nr > 0 && nc > 0)
542 {
543 make_unique ();
544
545 for (octave_idx_type j = 0; j < nc; j++)
546 for (octave_idx_type i = 0; i < nr; i++)
547 xelem (i, j) = val;
548 }
549
550 return *this;
551 }
552
553 FloatComplexMatrix&
554 FloatComplexMatrix::fill (const FloatComplex& val)
555 {
556 octave_idx_type nr = rows ();
557 octave_idx_type nc = cols ();
558
559 if (nr > 0 && nc > 0)
560 {
561 make_unique ();
562
563 for (octave_idx_type j = 0; j < nc; j++)
564 for (octave_idx_type i = 0; i < nr; i++)
565 xelem (i, j) = val;
566 }
567
568 return *this;
569 }
570
571 FloatComplexMatrix&
572 FloatComplexMatrix::fill (float val, octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2)
573 {
574 octave_idx_type nr = rows ();
575 octave_idx_type nc = cols ();
576
577 if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0
578 || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)
579 {
580 (*current_liboctave_error_handler) ("range error for fill");
581 return *this;
582 }
583
584 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
585 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; }
586
587 if (r2 >= r1 && c2 >= c1)
588 {
589 make_unique ();
590
591 for (octave_idx_type j = c1; j <= c2; j++)
592 for (octave_idx_type i = r1; i <= r2; i++)
593 xelem (i, j) = val;
594 }
595
596 return *this;
597 }
598
599 FloatComplexMatrix&
600 FloatComplexMatrix::fill (const FloatComplex& val, octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2)
601 {
602 octave_idx_type nr = rows ();
603 octave_idx_type nc = cols ();
604
605 if (r1 < 0 || r2 < 0 || c1 < 0 || c2 < 0
606 || r1 >= nr || r2 >= nr || c1 >= nc || c2 >= nc)
607 {
608 (*current_liboctave_error_handler) ("range error for fill");
609 return *this;
610 }
611
612 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
613 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; }
614
615 if (r2 >= r1 && c2 >=c1)
616 {
617 make_unique ();
618
619 for (octave_idx_type j = c1; j <= c2; j++)
620 for (octave_idx_type i = r1; i <= r2; i++)
621 xelem (i, j) = val;
622 }
623
624 return *this;
625 }
626
627 FloatComplexMatrix
628 FloatComplexMatrix::append (const FloatMatrix& a) const
629 {
630 octave_idx_type nr = rows ();
631 octave_idx_type nc = cols ();
632 if (nr != a.rows ())
633 {
634 (*current_liboctave_error_handler) ("row dimension mismatch for append");
635 return *this;
636 }
637
638 octave_idx_type nc_insert = nc;
639 FloatComplexMatrix retval (nr, nc + a.cols ());
640 retval.insert (*this, 0, 0);
641 retval.insert (a, 0, nc_insert);
642 return retval;
643 }
644
645 FloatComplexMatrix
646 FloatComplexMatrix::append (const FloatRowVector& a) const
647 {
648 octave_idx_type nr = rows ();
649 octave_idx_type nc = cols ();
650 if (nr != 1)
651 {
652 (*current_liboctave_error_handler) ("row dimension mismatch for append");
653 return *this;
654 }
655
656 octave_idx_type nc_insert = nc;
657 FloatComplexMatrix retval (nr, nc + a.length ());
658 retval.insert (*this, 0, 0);
659 retval.insert (a, 0, nc_insert);
660 return retval;
661 }
662
663 FloatComplexMatrix
664 FloatComplexMatrix::append (const FloatColumnVector& a) const
665 {
666 octave_idx_type nr = rows ();
667 octave_idx_type nc = cols ();
668 if (nr != a.length ())
669 {
670 (*current_liboctave_error_handler) ("row dimension mismatch for append");
671 return *this;
672 }
673
674 octave_idx_type nc_insert = nc;
675 FloatComplexMatrix retval (nr, nc + 1);
676 retval.insert (*this, 0, 0);
677 retval.insert (a, 0, nc_insert);
678 return retval;
679 }
680
681 FloatComplexMatrix
682 FloatComplexMatrix::append (const FloatDiagMatrix& a) const
683 {
684 octave_idx_type nr = rows ();
685 octave_idx_type nc = cols ();
686 if (nr != a.rows ())
687 {
688 (*current_liboctave_error_handler) ("row dimension mismatch for append");
689 return *this;
690 }
691
692 octave_idx_type nc_insert = nc;
693 FloatComplexMatrix retval (nr, nc + a.cols ());
694 retval.insert (*this, 0, 0);
695 retval.insert (a, 0, nc_insert);
696 return retval;
697 }
698
699 FloatComplexMatrix
700 FloatComplexMatrix::append (const FloatComplexMatrix& a) const
701 {
702 octave_idx_type nr = rows ();
703 octave_idx_type nc = cols ();
704 if (nr != a.rows ())
705 {
706 (*current_liboctave_error_handler) ("row dimension mismatch for append");
707 return *this;
708 }
709
710 octave_idx_type nc_insert = nc;
711 FloatComplexMatrix retval (nr, nc + a.cols ());
712 retval.insert (*this, 0, 0);
713 retval.insert (a, 0, nc_insert);
714 return retval;
715 }
716
717 FloatComplexMatrix
718 FloatComplexMatrix::append (const FloatComplexRowVector& a) const
719 {
720 octave_idx_type nr = rows ();
721 octave_idx_type nc = cols ();
722 if (nr != 1)
723 {
724 (*current_liboctave_error_handler) ("row dimension mismatch for append");
725 return *this;
726 }
727
728 octave_idx_type nc_insert = nc;
729 FloatComplexMatrix retval (nr, nc + a.length ());
730 retval.insert (*this, 0, 0);
731 retval.insert (a, 0, nc_insert);
732 return retval;
733 }
734
735 FloatComplexMatrix
736 FloatComplexMatrix::append (const FloatComplexColumnVector& a) const
737 {
738 octave_idx_type nr = rows ();
739 octave_idx_type nc = cols ();
740 if (nr != a.length ())
741 {
742 (*current_liboctave_error_handler) ("row dimension mismatch for append");
743 return *this;
744 }
745
746 octave_idx_type nc_insert = nc;
747 FloatComplexMatrix retval (nr, nc + 1);
748 retval.insert (*this, 0, 0);
749 retval.insert (a, 0, nc_insert);
750 return retval;
751 }
752
753 FloatComplexMatrix
754 FloatComplexMatrix::append (const FloatComplexDiagMatrix& a) const
755 {
756 octave_idx_type nr = rows ();
757 octave_idx_type nc = cols ();
758 if (nr != a.rows ())
759 {
760 (*current_liboctave_error_handler) ("row dimension mismatch for append");
761 return *this;
762 }
763
764 octave_idx_type nc_insert = nc;
765 FloatComplexMatrix retval (nr, nc + a.cols ());
766 retval.insert (*this, 0, 0);
767 retval.insert (a, 0, nc_insert);
768 return retval;
769 }
770
771 FloatComplexMatrix
772 FloatComplexMatrix::stack (const FloatMatrix& a) const
773 {
774 octave_idx_type nr = rows ();
775 octave_idx_type nc = cols ();
776 if (nc != a.cols ())
777 {
778 (*current_liboctave_error_handler)
779 ("column dimension mismatch for stack");
780 return *this;
781 }
782
783 octave_idx_type nr_insert = nr;
784 FloatComplexMatrix retval (nr + a.rows (), nc);
785 retval.insert (*this, 0, 0);
786 retval.insert (a, nr_insert, 0);
787 return retval;
788 }
789
790 FloatComplexMatrix
791 FloatComplexMatrix::stack (const FloatRowVector& a) const
792 {
793 octave_idx_type nr = rows ();
794 octave_idx_type nc = cols ();
795 if (nc != a.length ())
796 {
797 (*current_liboctave_error_handler)
798 ("column dimension mismatch for stack");
799 return *this;
800 }
801
802 octave_idx_type nr_insert = nr;
803 FloatComplexMatrix retval (nr + 1, nc);
804 retval.insert (*this, 0, 0);
805 retval.insert (a, nr_insert, 0);
806 return retval;
807 }
808
809 FloatComplexMatrix
810 FloatComplexMatrix::stack (const FloatColumnVector& a) const
811 {
812 octave_idx_type nr = rows ();
813 octave_idx_type nc = cols ();
814 if (nc != 1)
815 {
816 (*current_liboctave_error_handler)
817 ("column dimension mismatch for stack");
818 return *this;
819 }
820
821 octave_idx_type nr_insert = nr;
822 FloatComplexMatrix retval (nr + a.length (), nc);
823 retval.insert (*this, 0, 0);
824 retval.insert (a, nr_insert, 0);
825 return retval;
826 }
827
828 FloatComplexMatrix
829 FloatComplexMatrix::stack (const FloatDiagMatrix& a) const
830 {
831 octave_idx_type nr = rows ();
832 octave_idx_type nc = cols ();
833 if (nc != a.cols ())
834 {
835 (*current_liboctave_error_handler)
836 ("column dimension mismatch for stack");
837 return *this;
838 }
839
840 octave_idx_type nr_insert = nr;
841 FloatComplexMatrix retval (nr + a.rows (), nc);
842 retval.insert (*this, 0, 0);
843 retval.insert (a, nr_insert, 0);
844 return retval;
845 }
846
847 FloatComplexMatrix
848 FloatComplexMatrix::stack (const FloatComplexMatrix& a) const
849 {
850 octave_idx_type nr = rows ();
851 octave_idx_type nc = cols ();
852 if (nc != a.cols ())
853 {
854 (*current_liboctave_error_handler)
855 ("column dimension mismatch for stack");
856 return *this;
857 }
858
859 octave_idx_type nr_insert = nr;
860 FloatComplexMatrix retval (nr + a.rows (), nc);
861 retval.insert (*this, 0, 0);
862 retval.insert (a, nr_insert, 0);
863 return retval;
864 }
865
866 FloatComplexMatrix
867 FloatComplexMatrix::stack (const FloatComplexRowVector& a) const
868 {
869 octave_idx_type nr = rows ();
870 octave_idx_type nc = cols ();
871 if (nc != a.length ())
872 {
873 (*current_liboctave_error_handler)
874 ("column dimension mismatch for stack");
875 return *this;
876 }
877
878 octave_idx_type nr_insert = nr;
879 FloatComplexMatrix retval (nr + 1, nc);
880 retval.insert (*this, 0, 0);
881 retval.insert (a, nr_insert, 0);
882 return retval;
883 }
884
885 FloatComplexMatrix
886 FloatComplexMatrix::stack (const FloatComplexColumnVector& a) const
887 {
888 octave_idx_type nr = rows ();
889 octave_idx_type nc = cols ();
890 if (nc != 1)
891 {
892 (*current_liboctave_error_handler)
893 ("column dimension mismatch for stack");
894 return *this;
895 }
896
897 octave_idx_type nr_insert = nr;
898 FloatComplexMatrix retval (nr + a.length (), nc);
899 retval.insert (*this, 0, 0);
900 retval.insert (a, nr_insert, 0);
901 return retval;
902 }
903
904 FloatComplexMatrix
905 FloatComplexMatrix::stack (const FloatComplexDiagMatrix& a) const
906 {
907 octave_idx_type nr = rows ();
908 octave_idx_type nc = cols ();
909 if (nc != a.cols ())
910 {
911 (*current_liboctave_error_handler)
912 ("column dimension mismatch for stack");
913 return *this;
914 }
915
916 octave_idx_type nr_insert = nr;
917 FloatComplexMatrix retval (nr + a.rows (), nc);
918 retval.insert (*this, 0, 0);
919 retval.insert (a, nr_insert, 0);
920 return retval;
921 }
922
923 FloatComplexMatrix
924 conj (const FloatComplexMatrix& a)
925 {
926 return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float> > (a);
927 }
928
929 // resize is the destructive equivalent for this one
930
931 FloatComplexMatrix
932 FloatComplexMatrix::extract (octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
933 {
934 if (r1 > r2) { octave_idx_type tmp = r1; r1 = r2; r2 = tmp; }
935 if (c1 > c2) { octave_idx_type tmp = c1; c1 = c2; c2 = tmp; }
936
937 return index (idx_vector (r1, r2+1), idx_vector (c1, c2+1));
938 }
939
940 FloatComplexMatrix
941 FloatComplexMatrix::extract_n (octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const
942 {
943 return index (idx_vector (r1, r1 + nr), idx_vector (c1, c1 + nc));
944 }
945
946 // extract row or column i.
947
948 FloatComplexRowVector
949 FloatComplexMatrix::row (octave_idx_type i) const
950 {
951 return index (idx_vector (i), idx_vector::colon);
952 }
953
954 FloatComplexColumnVector
955 FloatComplexMatrix::column (octave_idx_type i) const
956 {
957 return index (idx_vector::colon, idx_vector (i));
958 }
959
960 FloatComplexMatrix
961 FloatComplexMatrix::inverse (void) const
962 {
963 octave_idx_type info;
964 float rcon;
965 MatrixType mattype (*this);
966 return inverse (mattype, info, rcon, 0, 0);
967 }
968
969 FloatComplexMatrix
970 FloatComplexMatrix::inverse (octave_idx_type& info) const
971 {
972 float rcon;
973 MatrixType mattype (*this);
974 return inverse (mattype, info, rcon, 0, 0);
975 }
976
977 FloatComplexMatrix
978 FloatComplexMatrix::inverse (octave_idx_type& info, float& rcon, int force,
979 int calc_cond) const
980 {
981 MatrixType mattype (*this);
982 return inverse (mattype, info, rcon, force, calc_cond);
983 }
984
985 FloatComplexMatrix
986 FloatComplexMatrix::inverse (MatrixType &mattype) const
987 {
988 octave_idx_type info;
989 float rcon;
990 return inverse (mattype, info, rcon, 0, 0);
991 }
992
993 FloatComplexMatrix
994 FloatComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info) const
995 {
996 float rcon;
997 return inverse (mattype, info, rcon, 0, 0);
998 }
999
1000 FloatComplexMatrix
1001 FloatComplexMatrix::tinverse (MatrixType &mattype, octave_idx_type& info,
1002 float& rcon, int force, int calc_cond) const
1003 {
1004 FloatComplexMatrix retval;
1005
1006 octave_idx_type nr = rows ();
1007 octave_idx_type nc = cols ();
1008
1009 if (nr != nc || nr == 0 || nc == 0)
1010 (*current_liboctave_error_handler) ("inverse requires square matrix");
1011 else
1012 {
1013 int typ = mattype.type ();
1014 char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
1015 char udiag = 'N';
1016 retval = *this;
1017 FloatComplex *tmp_data = retval.fortran_vec ();
1018
1019 F77_XFCN (ctrtri, CTRTRI, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1020 F77_CONST_CHAR_ARG2 (&udiag, 1),
1021 nr, tmp_data, nr, info
1022 F77_CHAR_ARG_LEN (1)
1023 F77_CHAR_ARG_LEN (1)));
1024
1025 // Throw-away extra info LAPACK gives so as to not change output.
1026 rcon = 0.0;
1027 if (info != 0)
1028 info = -1;
1029 else if (calc_cond)
1030 {
1031 octave_idx_type ztrcon_info = 0;
1032 char job = '1';
1033
1034 OCTAVE_LOCAL_BUFFER (FloatComplex, cwork, 2*nr);
1035 OCTAVE_LOCAL_BUFFER (float, rwork, nr);
1036
1037 F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1038 F77_CONST_CHAR_ARG2 (&uplo, 1),
1039 F77_CONST_CHAR_ARG2 (&udiag, 1),
1040 nr, tmp_data, nr, rcon,
1041 cwork, rwork, ztrcon_info
1042 F77_CHAR_ARG_LEN (1)
1043 F77_CHAR_ARG_LEN (1)
1044 F77_CHAR_ARG_LEN (1)));
1045
1046 if (ztrcon_info != 0)
1047 info = -1;
1048 }
1049
1050 if (info == -1 && ! force)
1051 retval = *this; // Restore matrix contents.
1052 }
1053
1054 return retval;
1055 }
1056
1057 FloatComplexMatrix
1058 FloatComplexMatrix::finverse (MatrixType &mattype, octave_idx_type& info,
1059 float& rcon, int force, int calc_cond) const
1060 {
1061 FloatComplexMatrix retval;
1062
1063 octave_idx_type nr = rows ();
1064 octave_idx_type nc = cols ();
1065
1066 if (nr != nc)
1067 (*current_liboctave_error_handler) ("inverse requires square matrix");
1068 else
1069 {
1070 Array<octave_idx_type> ipvt (dim_vector (nr, 1));
1071 octave_idx_type *pipvt = ipvt.fortran_vec ();
1072
1073 retval = *this;
1074 FloatComplex *tmp_data = retval.fortran_vec ();
1075
1076 Array<FloatComplex> z (dim_vector (1, 1));
1077 octave_idx_type lwork = -1;
1078
1079 // Query the optimum work array size.
1080
1081 F77_XFCN (cgetri, CGETRI, (nc, tmp_data, nr, pipvt,
1082 z.fortran_vec (), lwork, info));
1083
1084 lwork = static_cast<octave_idx_type> (std::real (z(0)));
1085 lwork = (lwork < 2 *nc ? 2*nc : lwork);
1086 z.resize (dim_vector (lwork, 1));
1087 FloatComplex *pz = z.fortran_vec ();
1088
1089 info = 0;
1090
1091 // Calculate the norm of the matrix, for later use.
1092 float anorm;
1093 if (calc_cond)
1094 anorm = retval.abs ().sum ().row (static_cast<octave_idx_type>(0)).max ();
1095
1096 F77_XFCN (cgetrf, CGETRF, (nc, nc, tmp_data, nr, pipvt, info));
1097
1098 // Throw-away extra info LAPACK gives so as to not change output.
1099 rcon = 0.0;
1100 if (info != 0)
1101 info = -1;
1102 else if (calc_cond)
1103 {
1104 // Now calculate the condition number for non-singular matrix.
1105 octave_idx_type zgecon_info = 0;
1106 char job = '1';
1107 Array<float> rz (dim_vector (2 * nc, 1));
1108 float *prz = rz.fortran_vec ();
1109 F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1110 nc, tmp_data, nr, anorm,
1111 rcon, pz, prz, zgecon_info
1112 F77_CHAR_ARG_LEN (1)));
1113
1114 if (zgecon_info != 0)
1115 info = -1;
1116 }
1117
1118 if (info == -1 && ! force)
1119 retval = *this; // Restore contents.
1120 else
1121 {
1122 octave_idx_type zgetri_info = 0;
1123
1124 F77_XFCN (cgetri, CGETRI, (nc, tmp_data, nr, pipvt,
1125 pz, lwork, zgetri_info));
1126
1127 if (zgetri_info != 0)
1128 info = -1;
1129 }
1130
1131 if (info != 0)
1132 mattype.mark_as_rectangular ();
1133 }
1134
1135 return retval;
1136 }
1137
1138 FloatComplexMatrix
1139 FloatComplexMatrix::inverse (MatrixType &mattype, octave_idx_type& info,
1140 float& rcon, int force, int calc_cond) const
1141 {
1142 int typ = mattype.type (false);
1143 FloatComplexMatrix ret;
1144
1145 if (typ == MatrixType::Unknown)
1146 typ = mattype.type (*this);
1147
1148 if (typ == MatrixType::Upper || typ == MatrixType::Lower)
1149 ret = tinverse (mattype, info, rcon, force, calc_cond);
1150 else
1151 {
1152 if (mattype.is_hermitian ())
1153 {
1154 FloatComplexCHOL chol (*this, info, calc_cond);
1155 if (info == 0)
1156 {
1157 if (calc_cond)
1158 rcon = chol.rcond ();
1159 else
1160 rcon = 1.0;
1161 ret = chol.inverse ();
1162 }
1163 else
1164 mattype.mark_as_unsymmetric ();
1165 }
1166
1167 if (!mattype.is_hermitian ())
1168 ret = finverse (mattype, info, rcon, force, calc_cond);
1169
1170 if ((mattype.is_hermitian () || calc_cond) && rcon == 0.)
1171 ret = FloatComplexMatrix (rows (), columns (), FloatComplex (octave_Float_Inf, 0.));
1172 }
1173
1174 return ret;
1175 }
1176
1177 FloatComplexMatrix
1178 FloatComplexMatrix::pseudo_inverse (float tol) const
1179 {
1180 FloatComplexMatrix retval;
1181
1182 FloatComplexSVD result (*this, SVD::economy);
1183
1184 FloatDiagMatrix S = result.singular_values ();
1185 FloatComplexMatrix U = result.left_singular_matrix ();
1186 FloatComplexMatrix V = result.right_singular_matrix ();
1187
1188 FloatColumnVector sigma = S.diag ();
1189
1190 octave_idx_type r = sigma.length () - 1;
1191 octave_idx_type nr = rows ();
1192 octave_idx_type nc = cols ();
1193
1194 if (tol <= 0.0)
1195 {
1196 if (nr > nc)
1197 tol = nr * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
1198 else
1199 tol = nc * sigma.elem (0) * std::numeric_limits<double>::epsilon ();
1200 }
1201
1202 while (r >= 0 && sigma.elem (r) < tol)
1203 r--;
1204
1205 if (r < 0)
1206 retval = FloatComplexMatrix (nc, nr, 0.0);
1207 else
1208 {
1209 FloatComplexMatrix Ur = U.extract (0, 0, nr-1, r);
1210 FloatDiagMatrix D = FloatDiagMatrix (sigma.extract (0, r)) . inverse ();
1211 FloatComplexMatrix Vr = V.extract (0, 0, nc-1, r);
1212 retval = Vr * D * Ur.hermitian ();
1213 }
1214
1215 return retval;
1216 }
1217
1218 #if defined (HAVE_FFTW)
1219
1220 FloatComplexMatrix
1221 FloatComplexMatrix::fourier (void) const
1222 {
1223 size_t nr = rows ();
1224 size_t nc = cols ();
1225
1226 FloatComplexMatrix retval (nr, nc);
1227
1228 size_t npts, nsamples;
1229
1230 if (nr == 1 || nc == 1)
1231 {
1232 npts = nr > nc ? nr : nc;
1233 nsamples = 1;
1234 }
1235 else
1236 {
1237 npts = nr;
1238 nsamples = nc;
1239 }
1240
1241 const FloatComplex *in (data ());
1242 FloatComplex *out (retval.fortran_vec ());
1243
1244 octave_fftw::fft (in, out, npts, nsamples);
1245
1246 return retval;
1247 }
1248
1249 FloatComplexMatrix
1250 FloatComplexMatrix::ifourier (void) const
1251 {
1252 size_t nr = rows ();
1253 size_t nc = cols ();
1254
1255 FloatComplexMatrix retval (nr, nc);
1256
1257 size_t npts, nsamples;
1258
1259 if (nr == 1 || nc == 1)
1260 {
1261 npts = nr > nc ? nr : nc;
1262 nsamples = 1;
1263 }
1264 else
1265 {
1266 npts = nr;
1267 nsamples = nc;
1268 }
1269
1270 const FloatComplex *in (data ());
1271 FloatComplex *out (retval.fortran_vec ());
1272
1273 octave_fftw::ifft (in, out, npts, nsamples);
1274
1275 return retval;
1276 }
1277
1278 FloatComplexMatrix
1279 FloatComplexMatrix::fourier2d (void) const
1280 {
1281 dim_vector dv(rows (), cols ());
1282
1283 FloatComplexMatrix retval (rows (), cols ());
1284 const FloatComplex *in (data ());
1285 FloatComplex *out (retval.fortran_vec ());
1286
1287 octave_fftw::fftNd (in, out, 2, dv);
1288
1289 return retval;
1290 }
1291
1292 FloatComplexMatrix
1293 FloatComplexMatrix::ifourier2d (void) const
1294 {
1295 dim_vector dv(rows (), cols ());
1296
1297 FloatComplexMatrix retval (rows (), cols ());
1298 const FloatComplex *in (data ());
1299 FloatComplex *out (retval.fortran_vec ());
1300
1301 octave_fftw::ifftNd (in, out, 2, dv);
1302
1303 return retval;
1304 }
1305
1306 #else
1307
1308 extern "C"
1309 {
1310 F77_RET_T
1311 F77_FUNC (cffti, CFFTI) (const octave_idx_type&, FloatComplex*);
1312
1313 F77_RET_T
1314 F77_FUNC (cfftf, CFFTF) (const octave_idx_type&, FloatComplex*, FloatComplex*);
1315
1316 F77_RET_T
1317 F77_FUNC (cfftb, CFFTB) (const octave_idx_type&, FloatComplex*, FloatComplex*);
1318 }
1319
1320 FloatComplexMatrix
1321 FloatComplexMatrix::fourier (void) const
1322 {
1323 FloatComplexMatrix retval;
1324
1325 octave_idx_type nr = rows ();
1326 octave_idx_type nc = cols ();
1327
1328 octave_idx_type npts, nsamples;
1329
1330 if (nr == 1 || nc == 1)
1331 {
1332 npts = nr > nc ? nr : nc;
1333 nsamples = 1;
1334 }
1335 else
1336 {
1337 npts = nr;
1338 nsamples = nc;
1339 }
1340
1341 octave_idx_type nn = 4*npts+15;
1342
1343 Array<FloatComplex> wsave (dim_vector (nn, 1));
1344 FloatComplex *pwsave = wsave.fortran_vec ();
1345
1346 retval = *this;
1347 FloatComplex *tmp_data = retval.fortran_vec ();
1348
1349 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1350
1351 for (octave_idx_type j = 0; j < nsamples; j++)
1352 {
1353 octave_quit ();
1354
1355 F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave);
1356 }
1357
1358 return retval;
1359 }
1360
1361 FloatComplexMatrix
1362 FloatComplexMatrix::ifourier (void) const
1363 {
1364 FloatComplexMatrix retval;
1365
1366 octave_idx_type nr = rows ();
1367 octave_idx_type nc = cols ();
1368
1369 octave_idx_type npts, nsamples;
1370
1371 if (nr == 1 || nc == 1)
1372 {
1373 npts = nr > nc ? nr : nc;
1374 nsamples = 1;
1375 }
1376 else
1377 {
1378 npts = nr;
1379 nsamples = nc;
1380 }
1381
1382 octave_idx_type nn = 4*npts+15;
1383
1384 Array<FloatComplex> wsave (dim_vector (nn, 1));
1385 FloatComplex *pwsave = wsave.fortran_vec ();
1386
1387 retval = *this;
1388 FloatComplex *tmp_data = retval.fortran_vec ();
1389
1390 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1391
1392 for (octave_idx_type j = 0; j < nsamples; j++)
1393 {
1394 octave_quit ();
1395
1396 F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave);
1397 }
1398
1399 for (octave_idx_type j = 0; j < npts*nsamples; j++)
1400 tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
1401
1402 return retval;
1403 }
1404
1405 FloatComplexMatrix
1406 FloatComplexMatrix::fourier2d (void) const
1407 {
1408 FloatComplexMatrix retval;
1409
1410 octave_idx_type nr = rows ();
1411 octave_idx_type nc = cols ();
1412
1413 octave_idx_type npts, nsamples;
1414
1415 if (nr == 1 || nc == 1)
1416 {
1417 npts = nr > nc ? nr : nc;
1418 nsamples = 1;
1419 }
1420 else
1421 {
1422 npts = nr;
1423 nsamples = nc;
1424 }
1425
1426 octave_idx_type nn = 4*npts+15;
1427
1428 Array<FloatComplex> wsave (dim_vector (nn, 1));
1429 FloatComplex *pwsave = wsave.fortran_vec ();
1430
1431 retval = *this;
1432 FloatComplex *tmp_data = retval.fortran_vec ();
1433
1434 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1435
1436 for (octave_idx_type j = 0; j < nsamples; j++)
1437 {
1438 octave_quit ();
1439
1440 F77_FUNC (cfftf, CFFTF) (npts, &tmp_data[npts*j], pwsave);
1441 }
1442
1443 npts = nc;
1444 nsamples = nr;
1445 nn = 4*npts+15;
1446
1447 wsave.resize (dim_vector (nn, 1));
1448 pwsave = wsave.fortran_vec ();
1449
1450 Array<FloatComplex> tmp (dim_vector (npts, 1));
1451 FloatComplex *prow = tmp.fortran_vec ();
1452
1453 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1454
1455 for (octave_idx_type j = 0; j < nsamples; j++)
1456 {
1457 octave_quit ();
1458
1459 for (octave_idx_type i = 0; i < npts; i++)
1460 prow[i] = tmp_data[i*nr + j];
1461
1462 F77_FUNC (cfftf, CFFTF) (npts, prow, pwsave);
1463
1464 for (octave_idx_type i = 0; i < npts; i++)
1465 tmp_data[i*nr + j] = prow[i];
1466 }
1467
1468 return retval;
1469 }
1470
1471 FloatComplexMatrix
1472 FloatComplexMatrix::ifourier2d (void) const
1473 {
1474 FloatComplexMatrix retval;
1475
1476 octave_idx_type nr = rows ();
1477 octave_idx_type nc = cols ();
1478
1479 octave_idx_type npts, nsamples;
1480
1481 if (nr == 1 || nc == 1)
1482 {
1483 npts = nr > nc ? nr : nc;
1484 nsamples = 1;
1485 }
1486 else
1487 {
1488 npts = nr;
1489 nsamples = nc;
1490 }
1491
1492 octave_idx_type nn = 4*npts+15;
1493
1494 Array<FloatComplex> wsave (dim_vector (nn, 1));
1495 FloatComplex *pwsave = wsave.fortran_vec ();
1496
1497 retval = *this;
1498 FloatComplex *tmp_data = retval.fortran_vec ();
1499
1500 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1501
1502 for (octave_idx_type j = 0; j < nsamples; j++)
1503 {
1504 octave_quit ();
1505
1506 F77_FUNC (cfftb, CFFTB) (npts, &tmp_data[npts*j], pwsave);
1507 }
1508
1509 for (octave_idx_type j = 0; j < npts*nsamples; j++)
1510 tmp_data[j] = tmp_data[j] / static_cast<float> (npts);
1511
1512 npts = nc;
1513 nsamples = nr;
1514 nn = 4*npts+15;
1515
1516 wsave.resize (dim_vector (nn, 1));
1517 pwsave = wsave.fortran_vec ();
1518
1519 Array<FloatComplex> tmp (dim_vector (npts, 1));
1520 FloatComplex *prow = tmp.fortran_vec ();
1521
1522 F77_FUNC (cffti, CFFTI) (npts, pwsave);
1523
1524 for (octave_idx_type j = 0; j < nsamples; j++)
1525 {
1526 octave_quit ();
1527
1528 for (octave_idx_type i = 0; i < npts; i++)
1529 prow[i] = tmp_data[i*nr + j];
1530
1531 F77_FUNC (cfftb, CFFTB) (npts, prow, pwsave);
1532
1533 for (octave_idx_type i = 0; i < npts; i++)
1534 tmp_data[i*nr + j] = prow[i] / static_cast<float> (npts);
1535 }
1536
1537 return retval;
1538 }
1539
1540 #endif
1541
1542 FloatComplexDET
1543 FloatComplexMatrix::determinant (void) const
1544 {
1545 octave_idx_type info;
1546 float rcon;
1547 return determinant (info, rcon, 0);
1548 }
1549
1550 FloatComplexDET
1551 FloatComplexMatrix::determinant (octave_idx_type& info) const
1552 {
1553 float rcon;
1554 return determinant (info, rcon, 0);
1555 }
1556
1557 FloatComplexDET
1558 FloatComplexMatrix::determinant (octave_idx_type& info, float& rcon, int calc_cond) const
1559 {
1560 MatrixType mattype (*this);
1561 return determinant (mattype, info, rcon, calc_cond);
1562 }
1563
1564 FloatComplexDET
1565 FloatComplexMatrix::determinant (MatrixType& mattype,
1566 octave_idx_type& info, float& rcon, int calc_cond) const
1567 {
1568 FloatComplexDET retval (1.0);
1569
1570 info = 0;
1571 rcon = 0.0;
1572
1573 octave_idx_type nr = rows ();
1574 octave_idx_type nc = cols ();
1575
1576 if (nr != nc)
1577 (*current_liboctave_error_handler) ("matrix must be square");
1578 else
1579 {
1580 volatile int typ = mattype.type ();
1581
1582 // Even though the matrix is marked as singular (Rectangular), we may
1583 // still get a useful number from the LU factorization, because it always
1584 // completes.
1585
1586 if (typ == MatrixType::Unknown)
1587 typ = mattype.type (*this);
1588 else if (typ == MatrixType::Rectangular)
1589 typ = MatrixType::Full;
1590
1591 if (typ == MatrixType::Lower || typ == MatrixType::Upper)
1592 {
1593 for (octave_idx_type i = 0; i < nc; i++)
1594 retval *= elem (i,i);
1595 }
1596 else if (typ == MatrixType::Hermitian)
1597 {
1598 FloatComplexMatrix atmp = *this;
1599 FloatComplex *tmp_data = atmp.fortran_vec ();
1600
1601 float anorm = 0;
1602 if (calc_cond) anorm = xnorm (*this, 1);
1603
1604
1605 char job = 'L';
1606 F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1607 tmp_data, nr, info
1608 F77_CHAR_ARG_LEN (1)));
1609
1610 if (info != 0)
1611 {
1612 rcon = 0.0;
1613 mattype.mark_as_unsymmetric ();
1614 typ = MatrixType::Full;
1615 }
1616 else
1617 {
1618 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1619 FloatComplex *pz = z.fortran_vec ();
1620 Array<float> rz (dim_vector (nc, 1));
1621 float *prz = rz.fortran_vec ();
1622
1623 F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1624 nr, tmp_data, nr, anorm,
1625 rcon, pz, prz, info
1626 F77_CHAR_ARG_LEN (1)));
1627
1628 if (info != 0)
1629 rcon = 0.0;
1630
1631 for (octave_idx_type i = 0; i < nc; i++)
1632 retval *= atmp (i,i);
1633
1634 retval = retval.square ();
1635 }
1636 }
1637 else if (typ != MatrixType::Full)
1638 (*current_liboctave_error_handler) ("det: invalid dense matrix type");
1639
1640 if (typ == MatrixType::Full)
1641 {
1642 Array<octave_idx_type> ipvt (dim_vector (nr, 1));
1643 octave_idx_type *pipvt = ipvt.fortran_vec ();
1644
1645 FloatComplexMatrix atmp = *this;
1646 FloatComplex *tmp_data = atmp.fortran_vec ();
1647
1648 info = 0;
1649
1650 // Calculate the norm of the matrix, for later use.
1651 float anorm = 0;
1652 if (calc_cond) anorm = xnorm (*this, 1);
1653
1654 F77_XFCN (cgetrf, CGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1655
1656 // Throw-away extra info LAPACK gives so as to not change output.
1657 rcon = 0.0;
1658 if (info != 0)
1659 {
1660 info = -1;
1661 retval = FloatComplexDET ();
1662 }
1663 else
1664 {
1665 if (calc_cond)
1666 {
1667 // Now calc the condition number for non-singular matrix.
1668 char job = '1';
1669 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1670 FloatComplex *pz = z.fortran_vec ();
1671 Array<float> rz (dim_vector (2 * nc, 1));
1672 float *prz = rz.fortran_vec ();
1673
1674 F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1675 nc, tmp_data, nr, anorm,
1676 rcon, pz, prz, info
1677 F77_CHAR_ARG_LEN (1)));
1678 }
1679
1680 if (info != 0)
1681 {
1682 info = -1;
1683 retval = FloatComplexDET ();
1684 }
1685 else
1686 {
1687 for (octave_idx_type i = 0; i < nc; i++)
1688 {
1689 FloatComplex c = atmp(i,i);
1690 retval *= (ipvt(i) != (i+1)) ? -c : c;
1691 }
1692 }
1693 }
1694 }
1695 }
1696
1697 return retval;
1698 }
1699
1700 float
1701 FloatComplexMatrix::rcond (void) const
1702 {
1703 MatrixType mattype (*this);
1704 return rcond (mattype);
1705 }
1706
1707 float
1708 FloatComplexMatrix::rcond (MatrixType &mattype) const
1709 {
1710 float rcon;
1711 octave_idx_type nr = rows ();
1712 octave_idx_type nc = cols ();
1713
1714 if (nr != nc)
1715 (*current_liboctave_error_handler) ("matrix must be square");
1716 else if (nr == 0 || nc == 0)
1717 rcon = octave_Inf;
1718 else
1719 {
1720 int typ = mattype.type ();
1721
1722 if (typ == MatrixType::Unknown)
1723 typ = mattype.type (*this);
1724
1725 // Only calculate the condition number for LU/Cholesky
1726 if (typ == MatrixType::Upper)
1727 {
1728 const FloatComplex *tmp_data = fortran_vec ();
1729 octave_idx_type info = 0;
1730 char norm = '1';
1731 char uplo = 'U';
1732 char dia = 'N';
1733
1734 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1735 FloatComplex *pz = z.fortran_vec ();
1736 Array<float> rz (dim_vector (nc, 1));
1737 float *prz = rz.fortran_vec ();
1738
1739 F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1740 F77_CONST_CHAR_ARG2 (&uplo, 1),
1741 F77_CONST_CHAR_ARG2 (&dia, 1),
1742 nr, tmp_data, nr, rcon,
1743 pz, prz, info
1744 F77_CHAR_ARG_LEN (1)
1745 F77_CHAR_ARG_LEN (1)
1746 F77_CHAR_ARG_LEN (1)));
1747
1748 if (info != 0)
1749 rcon = 0;
1750 }
1751 else if (typ == MatrixType::Permuted_Upper)
1752 (*current_liboctave_error_handler)
1753 ("permuted triangular matrix not implemented");
1754 else if (typ == MatrixType::Lower)
1755 {
1756 const FloatComplex *tmp_data = fortran_vec ();
1757 octave_idx_type info = 0;
1758 char norm = '1';
1759 char uplo = 'L';
1760 char dia = 'N';
1761
1762 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1763 FloatComplex *pz = z.fortran_vec ();
1764 Array<float> rz (dim_vector (nc, 1));
1765 float *prz = rz.fortran_vec ();
1766
1767 F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1768 F77_CONST_CHAR_ARG2 (&uplo, 1),
1769 F77_CONST_CHAR_ARG2 (&dia, 1),
1770 nr, tmp_data, nr, rcon,
1771 pz, prz, info
1772 F77_CHAR_ARG_LEN (1)
1773 F77_CHAR_ARG_LEN (1)
1774 F77_CHAR_ARG_LEN (1)));
1775
1776 if (info != 0)
1777 rcon = 0.0;
1778 }
1779 else if (typ == MatrixType::Permuted_Lower)
1780 (*current_liboctave_error_handler)
1781 ("permuted triangular matrix not implemented");
1782 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
1783 {
1784 float anorm = -1.0;
1785 FloatComplexMatrix atmp = *this;
1786 FloatComplex *tmp_data = atmp.fortran_vec ();
1787
1788 if (typ == MatrixType::Hermitian)
1789 {
1790 octave_idx_type info = 0;
1791 char job = 'L';
1792 anorm = atmp.abs ().sum ().
1793 row(static_cast<octave_idx_type>(0)).max ();
1794
1795 F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
1796 tmp_data, nr, info
1797 F77_CHAR_ARG_LEN (1)));
1798
1799 if (info != 0)
1800 {
1801 rcon = 0.0;
1802
1803 mattype.mark_as_unsymmetric ();
1804 typ = MatrixType::Full;
1805 }
1806 else
1807 {
1808 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1809 FloatComplex *pz = z.fortran_vec ();
1810 Array<float> rz (dim_vector (nc, 1));
1811 float *prz = rz.fortran_vec ();
1812
1813 F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
1814 nr, tmp_data, nr, anorm,
1815 rcon, pz, prz, info
1816 F77_CHAR_ARG_LEN (1)));
1817
1818 if (info != 0)
1819 rcon = 0.0;
1820 }
1821 }
1822
1823
1824 if (typ == MatrixType::Full)
1825 {
1826 octave_idx_type info = 0;
1827
1828 Array<octave_idx_type> ipvt (dim_vector (nr, 1));
1829 octave_idx_type *pipvt = ipvt.fortran_vec ();
1830
1831 if (anorm < 0.)
1832 anorm = atmp.abs ().sum ().
1833 row(static_cast<octave_idx_type>(0)).max ();
1834
1835 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1836 FloatComplex *pz = z.fortran_vec ();
1837 Array<float> rz (dim_vector (2 * nc, 1));
1838 float *prz = rz.fortran_vec ();
1839
1840 F77_XFCN (cgetrf, CGETRF, (nr, nr, tmp_data, nr, pipvt, info));
1841
1842 if (info != 0)
1843 {
1844 rcon = 0.0;
1845 mattype.mark_as_rectangular ();
1846 }
1847 else
1848 {
1849 char job = '1';
1850 F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
1851 nc, tmp_data, nr, anorm,
1852 rcon, pz, prz, info
1853 F77_CHAR_ARG_LEN (1)));
1854
1855 if (info != 0)
1856 rcon = 0.0;
1857 }
1858 }
1859 }
1860 else
1861 rcon = 0.0;
1862 }
1863
1864 return rcon;
1865 }
1866
1867 FloatComplexMatrix
1868 FloatComplexMatrix::utsolve (MatrixType &mattype, const FloatComplexMatrix& b,
1869 octave_idx_type& info, float& rcon,
1870 solve_singularity_handler sing_handler,
1871 bool calc_cond, blas_trans_type transt) const
1872 {
1873 FloatComplexMatrix retval;
1874
1875 octave_idx_type nr = rows ();
1876 octave_idx_type nc = cols ();
1877
1878 if (nr != b.rows ())
1879 (*current_liboctave_error_handler)
1880 ("matrix dimension mismatch solution of linear equations");
1881 else if (nr == 0 || nc == 0 || b.cols () == 0)
1882 retval = FloatComplexMatrix (nc, b.cols (), FloatComplex (0.0, 0.0));
1883 else
1884 {
1885 volatile int typ = mattype.type ();
1886
1887 if (typ == MatrixType::Permuted_Upper ||
1888 typ == MatrixType::Upper)
1889 {
1890 octave_idx_type b_nc = b.cols ();
1891 rcon = 1.;
1892 info = 0;
1893
1894 if (typ == MatrixType::Permuted_Upper)
1895 {
1896 (*current_liboctave_error_handler)
1897 ("permuted triangular matrix not implemented");
1898 }
1899 else
1900 {
1901 const FloatComplex *tmp_data = fortran_vec ();
1902
1903 if (calc_cond)
1904 {
1905 char norm = '1';
1906 char uplo = 'U';
1907 char dia = 'N';
1908
1909 Array<FloatComplex> z (dim_vector (2 * nc, 1));
1910 FloatComplex *pz = z.fortran_vec ();
1911 Array<float> rz (dim_vector (nc, 1));
1912 float *prz = rz.fortran_vec ();
1913
1914 F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
1915 F77_CONST_CHAR_ARG2 (&uplo, 1),
1916 F77_CONST_CHAR_ARG2 (&dia, 1),
1917 nr, tmp_data, nr, rcon,
1918 pz, prz, info
1919 F77_CHAR_ARG_LEN (1)
1920 F77_CHAR_ARG_LEN (1)
1921 F77_CHAR_ARG_LEN (1)));
1922
1923 if (info != 0)
1924 info = -2;
1925
1926 volatile float rcond_plus_one = rcon + 1.0;
1927
1928 if (rcond_plus_one == 1.0 || xisnan (rcon))
1929 {
1930 info = -2;
1931
1932 if (sing_handler)
1933 sing_handler (rcon);
1934 else
1935 (*current_liboctave_error_handler)
1936 ("matrix singular to machine precision, rcond = %g",
1937 rcon);
1938 }
1939 }
1940
1941 if (info == 0)
1942 {
1943 retval = b;
1944 FloatComplex *result = retval.fortran_vec ();
1945
1946 char uplo = 'U';
1947 char trans = get_blas_char (transt);
1948 char dia = 'N';
1949
1950 F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
1951 F77_CONST_CHAR_ARG2 (&trans, 1),
1952 F77_CONST_CHAR_ARG2 (&dia, 1),
1953 nr, b_nc, tmp_data, nr,
1954 result, nr, info
1955 F77_CHAR_ARG_LEN (1)
1956 F77_CHAR_ARG_LEN (1)
1957 F77_CHAR_ARG_LEN (1)));
1958 }
1959 }
1960 }
1961 else
1962 (*current_liboctave_error_handler) ("incorrect matrix type");
1963 }
1964
1965 return retval;
1966 }
1967
1968 FloatComplexMatrix
1969 FloatComplexMatrix::ltsolve (MatrixType &mattype, const FloatComplexMatrix& b,
1970 octave_idx_type& info, float& rcon,
1971 solve_singularity_handler sing_handler,
1972 bool calc_cond, blas_trans_type transt) const
1973 {
1974 FloatComplexMatrix retval;
1975
1976 octave_idx_type nr = rows ();
1977 octave_idx_type nc = cols ();
1978
1979 if (nr != b.rows ())
1980 (*current_liboctave_error_handler)
1981 ("matrix dimension mismatch solution of linear equations");
1982 else if (nr == 0 || nc == 0 || b.cols () == 0)
1983 retval = FloatComplexMatrix (nc, b.cols (), FloatComplex (0.0, 0.0));
1984 else
1985 {
1986 volatile int typ = mattype.type ();
1987
1988 if (typ == MatrixType::Permuted_Lower ||
1989 typ == MatrixType::Lower)
1990 {
1991 octave_idx_type b_nc = b.cols ();
1992 rcon = 1.;
1993 info = 0;
1994
1995 if (typ == MatrixType::Permuted_Lower)
1996 {
1997 (*current_liboctave_error_handler)
1998 ("permuted triangular matrix not implemented");
1999 }
2000 else
2001 {
2002 const FloatComplex *tmp_data = fortran_vec ();
2003
2004 if (calc_cond)
2005 {
2006 char norm = '1';
2007 char uplo = 'L';
2008 char dia = 'N';
2009
2010 Array<FloatComplex> z (dim_vector (2 * nc, 1));
2011 FloatComplex *pz = z.fortran_vec ();
2012 Array<float> rz (dim_vector (nc, 1));
2013 float *prz = rz.fortran_vec ();
2014
2015 F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
2016 F77_CONST_CHAR_ARG2 (&uplo, 1),
2017 F77_CONST_CHAR_ARG2 (&dia, 1),
2018 nr, tmp_data, nr, rcon,
2019 pz, prz, info
2020 F77_CHAR_ARG_LEN (1)
2021 F77_CHAR_ARG_LEN (1)
2022 F77_CHAR_ARG_LEN (1)));
2023
2024 if (info != 0)
2025 info = -2;
2026
2027 volatile float rcond_plus_one = rcon + 1.0;
2028
2029 if (rcond_plus_one == 1.0 || xisnan (rcon))
2030 {
2031 info = -2;
2032
2033 if (sing_handler)
2034 sing_handler (rcon);
2035 else
2036 (*current_liboctave_error_handler)
2037 ("matrix singular to machine precision, rcond = %g",
2038 rcon);
2039 }
2040 }
2041
2042 if (info == 0)
2043 {
2044 retval = b;
2045 FloatComplex *result = retval.fortran_vec ();
2046
2047 char uplo = 'L';
2048 char trans = get_blas_char (transt);
2049 char dia = 'N';
2050
2051 F77_XFCN (ctrtrs, CTRTRS, (F77_CONST_CHAR_ARG2 (&uplo, 1),
2052 F77_CONST_CHAR_ARG2 (&trans, 1),
2053 F77_CONST_CHAR_ARG2 (&dia, 1),
2054 nr, b_nc, tmp_data, nr,
2055 result, nr, info
2056 F77_CHAR_ARG_LEN (1)
2057 F77_CHAR_ARG_LEN (1)
2058 F77_CHAR_ARG_LEN (1)));
2059 }
2060 }
2061 }
2062 else
2063 (*current_liboctave_error_handler) ("incorrect matrix type");
2064 }
2065
2066 return retval;
2067 }
2068
2069 FloatComplexMatrix
2070 FloatComplexMatrix::fsolve (MatrixType &mattype, const FloatComplexMatrix& b,
2071 octave_idx_type& info, float& rcon,
2072 solve_singularity_handler sing_handler,
2073 bool calc_cond) const
2074 {
2075 FloatComplexMatrix retval;
2076
2077 octave_idx_type nr = rows ();
2078 octave_idx_type nc = cols ();
2079
2080
2081 if (nr != nc || nr != b.rows ())
2082 (*current_liboctave_error_handler)
2083 ("matrix dimension mismatch solution of linear equations");
2084 else if (nr == 0 || b.cols () == 0)
2085 retval = FloatComplexMatrix (nc, b.cols (), FloatComplex (0.0, 0.0));
2086 else
2087 {
2088 volatile int typ = mattype.type ();
2089
2090 // Calculate the norm of the matrix, for later use.
2091 float anorm = -1.;
2092
2093 if (typ == MatrixType::Hermitian)
2094 {
2095 info = 0;
2096 char job = 'L';
2097 FloatComplexMatrix atmp = *this;
2098 FloatComplex *tmp_data = atmp.fortran_vec ();
2099 anorm = atmp.abs ().sum ().row (static_cast<octave_idx_type>(0)).max ();
2100
2101 F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 (&job, 1), nr,
2102 tmp_data, nr, info
2103 F77_CHAR_ARG_LEN (1)));
2104
2105 // Throw-away extra info LAPACK gives so as to not change output.
2106 rcon = 0.0;
2107 if (info != 0)
2108 {
2109 info = -2;
2110
2111 mattype.mark_as_unsymmetric ();
2112 typ = MatrixType::Full;
2113 }
2114 else
2115 {
2116 if (calc_cond)
2117 {
2118 Array<FloatComplex> z (dim_vector (2 * nc, 1));
2119 FloatComplex *pz = z.fortran_vec ();
2120 Array<float> rz (dim_vector (nc, 1));
2121 float *prz = rz.fortran_vec ();
2122
2123 F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
2124 nr, tmp_data, nr, anorm,
2125 rcon, pz, prz, info
2126 F77_CHAR_ARG_LEN (1)));
2127
2128 if (info != 0)
2129 info = -2;
2130
2131 volatile float rcond_plus_one = rcon + 1.0;
2132
2133 if (rcond_plus_one == 1.0 || xisnan (rcon))
2134 {
2135 info = -2;
2136
2137 if (sing_handler)
2138 sing_handler (rcon);
2139 else
2140 (*current_liboctave_error_handler)
2141 ("matrix singular to machine precision, rcond = %g",
2142 rcon);
2143 }
2144 }
2145
2146 if (info == 0)
2147 {
2148 retval = b;
2149 FloatComplex *result = retval.fortran_vec ();
2150
2151 octave_idx_type b_nc = b.cols ();
2152
2153 F77_XFCN (cpotrs, CPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
2154 nr, b_nc, tmp_data, nr,
2155 result, b.rows (), info
2156 F77_CHAR_ARG_LEN (1)));
2157 }
2158 else
2159 {
2160 mattype.mark_as_unsymmetric ();
2161 typ = MatrixType::Full;
2162 }
2163 }
2164 }
2165
2166 if (typ == MatrixType::Full)
2167 {
2168 info = 0;
2169
2170 Array<octave_idx_type> ipvt (dim_vector (nr, 1));
2171 octave_idx_type *pipvt = ipvt.fortran_vec ();
2172
2173 FloatComplexMatrix atmp = *this;
2174 FloatComplex *tmp_data = atmp.fortran_vec ();
2175
2176 Array<FloatComplex> z (dim_vector (2 * nc, 1));
2177 FloatComplex *pz = z.fortran_vec ();
2178 Array<float> rz (dim_vector (2 * nc, 1));
2179 float *prz = rz.fortran_vec ();
2180
2181 // Calculate the norm of the matrix, for later use.
2182 if (anorm < 0.)
2183 anorm = atmp.abs ().sum ().row (static_cast<octave_idx_type>(0)).max ();
2184
2185 F77_XFCN (cgetrf, CGETRF, (nr, nr, tmp_data, nr, pipvt, info));
2186
2187 // Throw-away extra info LAPACK gives so as to not change output.
2188 rcon = 0.0;
2189 if (info != 0)
2190 {
2191 info = -2;
2192
2193 if (sing_handler)
2194 sing_handler (rcon);
2195 else
2196 (*current_liboctave_error_handler)
2197 ("matrix singular to machine precision");
2198
2199 mattype.mark_as_rectangular ();
2200 }
2201 else
2202 {
2203 if (calc_cond)
2204 {
2205 // Now calculate the condition number for
2206 // non-singular matrix.
2207 char job = '1';
2208 F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
2209 nc, tmp_data, nr, anorm,
2210 rcon, pz, prz, info
2211 F77_CHAR_ARG_LEN (1)));
2212
2213 if (info != 0)
2214 info = -2;
2215
2216 volatile float rcond_plus_one = rcon + 1.0;
2217
2218 if (rcond_plus_one == 1.0 || xisnan (rcon))
2219 {
2220 info = -2;
2221
2222 if (sing_handler)
2223 sing_handler (rcon);
2224 else
2225 (*current_liboctave_error_handler)
2226 ("matrix singular to machine precision, rcond = %g",
2227 rcon);
2228 }
2229 }
2230
2231 if (info == 0)
2232 {
2233 retval = b;
2234 FloatComplex *result = retval.fortran_vec ();
2235
2236 octave_idx_type b_nc = b.cols ();
2237
2238 char job = 'N';
2239 F77_XFCN (cgetrs, CGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
2240 nr, b_nc, tmp_data, nr,
2241 pipvt, result, b.rows (), info
2242 F77_CHAR_ARG_LEN (1)));
2243 }
2244 else
2245 mattype.mark_as_rectangular ();
2246 }
2247 }
2248 }
2249
2250 return retval;
2251 }
2252
2253 FloatComplexMatrix
2254 FloatComplexMatrix::solve (MatrixType &typ, const FloatMatrix& b) const
2255 {
2256 octave_idx_type info;
2257 float rcon;
2258 return solve (typ, b, info, rcon, 0);
2259 }
2260
2261 FloatComplexMatrix
2262 FloatComplexMatrix::solve (MatrixType &typ, const FloatMatrix& b,
2263 octave_idx_type& info) const
2264 {
2265 float rcon;
2266 return solve (typ, b, info, rcon, 0);
2267 }
2268
2269 FloatComplexMatrix
2270 FloatComplexMatrix::solve (MatrixType &typ, const FloatMatrix& b, octave_idx_type& info,
2271 float& rcon) const
2272 {
2273 return solve (typ, b, info, rcon, 0);
2274 }
2275
2276 FloatComplexMatrix
2277 FloatComplexMatrix::solve (MatrixType &typ, const FloatMatrix& b, octave_idx_type& info,
2278 float& rcon, solve_singularity_handler sing_handler,
2279 bool singular_fallback, blas_trans_type transt) const
2280 {
2281 FloatComplexMatrix tmp (b);
2282 return solve (typ, tmp, info, rcon, sing_handler, singular_fallback, transt);
2283 }
2284
2285 FloatComplexMatrix
2286 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b) const
2287 {
2288 octave_idx_type info;
2289 float rcon;
2290 return solve (typ, b, info, rcon, 0);
2291 }
2292
2293 FloatComplexMatrix
2294 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b,
2295 octave_idx_type& info) const
2296 {
2297 float rcon;
2298 return solve (typ, b, info, rcon, 0);
2299 }
2300
2301 FloatComplexMatrix
2302 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexMatrix& b,
2303 octave_idx_type& info, float& rcon) const
2304 {
2305 return solve (typ, b, info, rcon, 0);
2306 }
2307
2308 FloatComplexMatrix
2309 FloatComplexMatrix::solve (MatrixType &mattype, const FloatComplexMatrix& b,
2310 octave_idx_type& info, float& rcon,
2311 solve_singularity_handler sing_handler,
2312 bool singular_fallback, blas_trans_type transt) const
2313 {
2314 FloatComplexMatrix retval;
2315 int typ = mattype.type ();
2316
2317 if (typ == MatrixType::Unknown)
2318 typ = mattype.type (*this);
2319
2320 // Only calculate the condition number for LU/Cholesky
2321 if (typ == MatrixType::Upper || typ == MatrixType::Permuted_Upper)
2322 retval = utsolve (mattype, b, info, rcon, sing_handler, false, transt);
2323 else if (typ == MatrixType::Lower || typ == MatrixType::Permuted_Lower)
2324 retval = ltsolve (mattype, b, info, rcon, sing_handler, false, transt);
2325 else if (transt == blas_trans)
2326 return transpose ().solve (mattype, b, info, rcon, sing_handler, singular_fallback);
2327 else if (transt == blas_conj_trans)
2328 retval = hermitian ().solve (mattype, b, info, rcon, sing_handler, singular_fallback);
2329 else if (typ == MatrixType::Full || typ == MatrixType::Hermitian)
2330 retval = fsolve (mattype, b, info, rcon, sing_handler, true);
2331 else if (typ != MatrixType::Rectangular)
2332 {
2333 (*current_liboctave_error_handler) ("unknown matrix type");
2334 return FloatComplexMatrix ();
2335 }
2336
2337 // Rectangular or one of the above solvers flags a singular matrix
2338 if (singular_fallback && mattype.type () == MatrixType::Rectangular)
2339 {
2340 octave_idx_type rank;
2341 retval = lssolve (b, info, rank, rcon);
2342 }
2343
2344 return retval;
2345 }
2346
2347 FloatComplexColumnVector
2348 FloatComplexMatrix::solve (MatrixType &typ, const FloatColumnVector& b) const
2349 {
2350 octave_idx_type info;
2351 float rcon;
2352 return solve (typ, FloatComplexColumnVector (b), info, rcon, 0);
2353 }
2354
2355 FloatComplexColumnVector
2356 FloatComplexMatrix::solve (MatrixType &typ, const FloatColumnVector& b,
2357 octave_idx_type& info) const
2358 {
2359 float rcon;
2360 return solve (typ, FloatComplexColumnVector (b), info, rcon, 0);
2361 }
2362
2363 FloatComplexColumnVector
2364 FloatComplexMatrix::solve (MatrixType &typ, const FloatColumnVector& b,
2365 octave_idx_type& info, float& rcon) const
2366 {
2367 return solve (typ, FloatComplexColumnVector (b), info, rcon, 0);
2368 }
2369
2370 FloatComplexColumnVector
2371 FloatComplexMatrix::solve (MatrixType &typ, const FloatColumnVector& b,
2372 octave_idx_type& info, float& rcon,
2373 solve_singularity_handler sing_handler, blas_trans_type transt) const
2374 {
2375 return solve (typ, FloatComplexColumnVector (b), info, rcon, sing_handler, transt);
2376 }
2377
2378 FloatComplexColumnVector
2379 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b) const
2380 {
2381 octave_idx_type info;
2382 float rcon;
2383 return solve (typ, b, info, rcon, 0);
2384 }
2385
2386 FloatComplexColumnVector
2387 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
2388 octave_idx_type& info) const
2389 {
2390 float rcon;
2391 return solve (typ, b, info, rcon, 0);
2392 }
2393
2394 FloatComplexColumnVector
2395 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
2396 octave_idx_type& info, float& rcon) const
2397 {
2398 return solve (typ, b, info, rcon, 0);
2399 }
2400
2401 FloatComplexColumnVector
2402 FloatComplexMatrix::solve (MatrixType &typ, const FloatComplexColumnVector& b,
2403 octave_idx_type& info, float& rcon,
2404 solve_singularity_handler sing_handler, blas_trans_type transt) const
2405 {
2406
2407 FloatComplexMatrix tmp (b);
2408 tmp = solve (typ, tmp, info, rcon, sing_handler, true, transt);
2409 return tmp.column (static_cast<octave_idx_type> (0));
2410 }
2411
2412 FloatComplexMatrix
2413 FloatComplexMatrix::solve (const FloatMatrix& b) const
2414 {
2415 octave_idx_type info;
2416 float rcon;
2417 return solve (b, info, rcon, 0);
2418 }
2419
2420 FloatComplexMatrix
2421 FloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info) const
2422 {
2423 float rcon;
2424 return solve (b, info, rcon, 0);
2425 }
2426
2427 FloatComplexMatrix
2428 FloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info, float& rcon) const
2429 {
2430 return solve (b, info, rcon, 0);
2431 }
2432
2433 FloatComplexMatrix
2434 FloatComplexMatrix::solve (const FloatMatrix& b, octave_idx_type& info, float& rcon,
2435 solve_singularity_handler sing_handler, blas_trans_type transt) const
2436 {
2437 FloatComplexMatrix tmp (b);
2438 return solve (tmp, info, rcon, sing_handler, transt);
2439 }
2440
2441 FloatComplexMatrix
2442 FloatComplexMatrix::solve (const FloatComplexMatrix& b) const
2443 {
2444 octave_idx_type info;
2445 float rcon;
2446 return solve (b, info, rcon, 0);
2447 }
2448
2449 FloatComplexMatrix
2450 FloatComplexMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info) const
2451 {
2452 float rcon;
2453 return solve (b, info, rcon, 0);
2454 }
2455
2456 FloatComplexMatrix
2457 FloatComplexMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info, float& rcon) const
2458 {
2459 return solve (b, info, rcon, 0);
2460 }
2461
2462 FloatComplexMatrix
2463 FloatComplexMatrix::solve (const FloatComplexMatrix& b, octave_idx_type& info, float& rcon,
2464 solve_singularity_handler sing_handler, blas_trans_type transt) const
2465 {
2466 MatrixType mattype (*this);
2467 return solve (mattype, b, info, rcon, sing_handler, true, transt);
2468 }
2469
2470 FloatComplexColumnVector
2471 FloatComplexMatrix::solve (const FloatColumnVector& b) const
2472 {
2473 octave_idx_type info;
2474 float rcon;
2475 return solve (FloatComplexColumnVector (b), info, rcon, 0);
2476 }
2477
2478 FloatComplexColumnVector
2479 FloatComplexMatrix::solve (const FloatColumnVector& b, octave_idx_type& info) const
2480 {
2481 float rcon;
2482 return solve (FloatComplexColumnVector (b), info, rcon, 0);
2483 }
2484
2485 FloatComplexColumnVector
2486 FloatComplexMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,
2487 float& rcon) const
2488 {
2489 return solve (FloatComplexColumnVector (b), info, rcon, 0);
2490 }
2491
2492 FloatComplexColumnVector
2493 FloatComplexMatrix::solve (const FloatColumnVector& b, octave_idx_type& info,
2494 float& rcon,
2495 solve_singularity_handler sing_handler, blas_trans_type transt) const
2496 {
2497 return solve (FloatComplexColumnVector (b), info, rcon, sing_handler, transt);
2498 }
2499
2500 FloatComplexColumnVector
2501 FloatComplexMatrix::solve (const FloatComplexColumnVector& b) const
2502 {
2503 octave_idx_type info;
2504 float rcon;
2505 return solve (b, info, rcon, 0);
2506 }
2507
2508 FloatComplexColumnVector
2509 FloatComplexMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info) const
2510 {
2511 float rcon;
2512 return solve (b, info, rcon, 0);
2513 }
2514
2515 FloatComplexColumnVector
2516 FloatComplexMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info,
2517 float& rcon) const
2518 {
2519 return solve (b, info, rcon, 0);
2520 }
2521
2522 FloatComplexColumnVector
2523 FloatComplexMatrix::solve (const FloatComplexColumnVector& b, octave_idx_type& info,
2524 float& rcon,
2525 solve_singularity_handler sing_handler, blas_trans_type transt) const
2526 {
2527 MatrixType mattype (*this);
2528 return solve (mattype, b, info, rcon, sing_handler, transt);
2529 }
2530
2531 FloatComplexMatrix
2532 FloatComplexMatrix::lssolve (const FloatMatrix& b) const
2533 {
2534 octave_idx_type info;
2535 octave_idx_type rank;
2536 float rcon;
2537 return lssolve (FloatComplexMatrix (b), info, rank, rcon);
2538 }
2539
2540 FloatComplexMatrix
2541 FloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info) const
2542 {
2543 octave_idx_type rank;
2544 float rcon;
2545 return lssolve (FloatComplexMatrix (b), info, rank, rcon);
2546 }
2547
2548 FloatComplexMatrix
2549 FloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,
2550 octave_idx_type& rank) const
2551 {
2552 float rcon;
2553 return lssolve (FloatComplexMatrix (b), info, rank, rcon);
2554 }
2555
2556 FloatComplexMatrix
2557 FloatComplexMatrix::lssolve (const FloatMatrix& b, octave_idx_type& info,
2558 octave_idx_type& rank, float& rcon) const
2559 {
2560 return lssolve (FloatComplexMatrix (b), info, rank, rcon);
2561 }
2562
2563 FloatComplexMatrix
2564 FloatComplexMatrix::lssolve (const FloatComplexMatrix& b) const
2565 {
2566 octave_idx_type info;
2567 octave_idx_type rank;
2568 float rcon;
2569 return lssolve (b, info, rank, rcon);
2570 }
2571
2572 FloatComplexMatrix
2573 FloatComplexMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info) const
2574 {
2575 octave_idx_type rank;
2576 float rcon;
2577 return lssolve (b, info, rank, rcon);
2578 }
2579
2580 FloatComplexMatrix
2581 FloatComplexMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,
2582 octave_idx_type& rank) const
2583 {
2584 float rcon;
2585 return lssolve (b, info, rank, rcon);
2586 }
2587
2588 FloatComplexMatrix
2589 FloatComplexMatrix::lssolve (const FloatComplexMatrix& b, octave_idx_type& info,
2590 octave_idx_type& rank, float& rcon) const
2591 {
2592 FloatComplexMatrix retval;
2593
2594 octave_idx_type nrhs = b.cols ();
2595
2596 octave_idx_type m = rows ();
2597 octave_idx_type n = cols ();
2598
2599 if (m != b.rows ())
2600 (*current_liboctave_error_handler)
2601 ("matrix dimension mismatch solution of linear equations");
2602 else if (m== 0 || n == 0 || b.cols () == 0)
2603 retval = FloatComplexMatrix (n, b.cols (), FloatComplex (0.0, 0.0));
2604 else
2605 {
2606 volatile octave_idx_type minmn = (m < n ? m : n);
2607 octave_idx_type maxmn = m > n ? m : n;
2608 rcon = -1.0;
2609
2610 if (m != n)
2611 {
2612 retval = FloatComplexMatrix (maxmn, nrhs);
2613
2614 for (octave_idx_type j = 0; j < nrhs; j++)
2615 for (octave_idx_type i = 0; i < m; i++)
2616 retval.elem (i, j) = b.elem (i, j);
2617 }
2618 else
2619 retval = b;
2620
2621 FloatComplexMatrix atmp = *this;
2622 FloatComplex *tmp_data = atmp.fortran_vec ();
2623
2624 FloatComplex *pretval = retval.fortran_vec ();
2625 Array<float> s (dim_vector (minmn, 1));
2626 float *ps = s.fortran_vec ();
2627
2628 // Ask ZGELSD what the dimension of WORK should be.
2629 octave_idx_type lwork = -1;
2630
2631 Array<FloatComplex> work (dim_vector (1, 1));
2632
2633 octave_idx_type smlsiz;
2634 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("CGELSD", 6),
2635 F77_CONST_CHAR_ARG2 (" ", 1),
2636 0, 0, 0, 0, smlsiz
2637 F77_CHAR_ARG_LEN (6)
2638 F77_CHAR_ARG_LEN (1));
2639
2640 octave_idx_type mnthr;
2641 F77_FUNC (xilaenv, XILAENV) (6, F77_CONST_CHAR_ARG2 ("CGELSD", 6),
2642 F77_CONST_CHAR_ARG2 (" ", 1),
2643 m, n, nrhs, -1, mnthr
2644 F77_CHAR_ARG_LEN (6)
2645 F77_CHAR_ARG_LEN (1));
2646
2647 // We compute the size of rwork and iwork because ZGELSD in
2648 // older versions of LAPACK does not return them on a query
2649 // call.
2650 float dminmn = static_cast<float> (minmn);
2651 float dsmlsizp1 = static_cast<float> (smlsiz+1);
2652 #if defined (HAVE_LOG2)
2653 float tmp = log2 (dminmn / dsmlsizp1);
2654 #else
2655 float tmp = log (dminmn / dsmlsizp1) / log (2.0);
2656 #endif
2657 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
2658 if (nlvl < 0)
2659 nlvl = 0;
2660
2661 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)
2662 + 3*smlsiz*nrhs + std::max ((smlsiz+1)*(smlsiz+1),
2663 n*(1+nrhs) + 2*nrhs);
2664 if (lrwork < 1)
2665 lrwork = 1;
2666 Array<float> rwork (dim_vector (lrwork, 1));
2667 float *prwork = rwork.fortran_vec ();
2668
2669 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn;
2670 if (liwork < 1)
2671 liwork = 1;
2672 Array<octave_idx_type> iwork (dim_vector (liwork, 1));
2673 octave_idx_type* piwork = iwork.fortran_vec ();
2674
2675 F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
2676 ps, rcon, rank, work.fortran_vec (),
2677 lwork, prwork, piwork, info));
2678
2679 // The workspace query is broken in at least LAPACK 3.0.0
2680 // through 3.1.1 when n >= mnthr. The obtuse formula below
2681 // should provide sufficient workspace for ZGELSD to operate
2682 // efficiently.
2683 if (n > m && n >= mnthr)
2684 {
2685 octave_idx_type addend = m;
2686
2687 if (2*m-4 > addend)
2688 addend = 2*m-4;
2689
2690 if (nrhs > addend)
2691 addend = nrhs;
2692
2693 if (n-3*m > addend)
2694 addend = n-3*m;
2695
2696 const octave_idx_type lworkaround = 4*m + m*m + addend;
2697
2698 if (std::real (work(0)) < lworkaround)
2699 work(0) = lworkaround;
2700 }
2701 else if (m >= n)
2702 {
2703 octave_idx_type lworkaround = 2*m + m*nrhs;
2704
2705 if (std::real (work(0)) < lworkaround)
2706 work(0) = lworkaround;
2707 }
2708
2709 lwork = static_cast<octave_idx_type> (std::real (work(0)));
2710 work.resize (dim_vector (lwork, 1));
2711
2712 F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, tmp_data, m, pretval,
2713 maxmn, ps, rcon, rank,
2714 work.fortran_vec (), lwork,
2715 prwork, piwork, info));
2716
2717 if (s.elem (0) == 0.0)
2718 rcon = 0.0;
2719 else
2720 rcon = s.elem (minmn - 1) / s.elem (0);
2721
2722 retval.resize (n, nrhs);
2723 }
2724
2725 return retval;
2726 }
2727
2728 FloatComplexColumnVector
2729 FloatComplexMatrix::lssolve (const FloatColumnVector& b) const
2730 {
2731 octave_idx_type info;
2732 octave_idx_type rank;
2733 float rcon;
2734 return lssolve (FloatComplexColumnVector (b), info, rank, rcon);
2735 }
2736
2737 FloatComplexColumnVector
2738 FloatComplexMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info) const
2739 {
2740 octave_idx_type rank;
2741 float rcon;
2742 return lssolve (FloatComplexColumnVector (b), info, rank, rcon);
2743 }
2744
2745 FloatComplexColumnVector
2746 FloatComplexMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,
2747 octave_idx_type& rank) const
2748 {
2749 float rcon;
2750 return lssolve (FloatComplexColumnVector (b), info, rank, rcon);
2751 }
2752
2753 FloatComplexColumnVector
2754 FloatComplexMatrix::lssolve (const FloatColumnVector& b, octave_idx_type& info,
2755 octave_idx_type& rank, float& rcon) const
2756 {
2757 return lssolve (FloatComplexColumnVector (b), info, rank, rcon);
2758 }
2759
2760 FloatComplexColumnVector
2761 FloatComplexMatrix::lssolve (const FloatComplexColumnVector& b) const
2762 {
2763 octave_idx_type info;
2764 octave_idx_type rank;
2765 float rcon;
2766 return lssolve (b, info, rank, rcon);
2767 }
2768
2769 FloatComplexColumnVector
2770 FloatComplexMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info) const
2771 {
2772 octave_idx_type rank;
2773 float rcon;
2774 return lssolve (b, info, rank, rcon);
2775 }
2776
2777 FloatComplexColumnVector
2778 FloatComplexMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,
2779 octave_idx_type& rank) const
2780 {
2781 float rcon;
2782 return lssolve (b, info, rank, rcon);
2783
2784 }
2785
2786 FloatComplexColumnVector
2787 FloatComplexMatrix::lssolve (const FloatComplexColumnVector& b, octave_idx_type& info,
2788 octave_idx_type& rank, float& rcon) const
2789 {
2790 FloatComplexColumnVector retval;
2791
2792 octave_idx_type nrhs = 1;
2793
2794 octave_idx_type m = rows ();
2795 octave_idx_type n = cols ();
2796
2797 if (m != b.length ())
2798 (*current_liboctave_error_handler)
2799 ("matrix dimension mismatch solution of linear equations");
2800 else if (m == 0 || n == 0 || b.cols () == 0)
2801 retval = FloatComplexColumnVector (n, FloatComplex (0.0, 0.0));
2802 else
2803 {
2804 volatile octave_idx_type minmn = (m < n ? m : n);
2805 octave_idx_type maxmn = m > n ? m : n;
2806 rcon = -1.0;
2807
2808 if (m != n)
2809 {
2810 retval = FloatComplexColumnVector (maxmn);
2811
2812 for (octave_idx_type i = 0; i < m; i++)
2813 retval.elem (i) = b.elem (i);
2814 }
2815 else
2816 retval = b;
2817
2818 FloatComplexMatrix atmp = *this;
2819 FloatComplex *tmp_data = atmp.fortran_vec ();
2820
2821 FloatComplex *pretval = retval.fortran_vec ();
2822 Array<float> s (dim_vector (minmn, 1));
2823 float *ps = s.fortran_vec ();
2824
2825 // Ask ZGELSD what the dimension of WORK should be.
2826 octave_idx_type lwork = -1;
2827
2828 Array<FloatComplex> work (dim_vector (1, 1));
2829
2830 octave_idx_type smlsiz;
2831 F77_FUNC (xilaenv, XILAENV) (9, F77_CONST_CHAR_ARG2 ("CGELSD", 6),
2832 F77_CONST_CHAR_ARG2 (" ", 1),
2833 0, 0, 0, 0, smlsiz
2834 F77_CHAR_ARG_LEN (6)
2835 F77_CHAR_ARG_LEN (1));
2836
2837 // We compute the size of rwork and iwork because ZGELSD in
2838 // older versions of LAPACK does not return them on a query
2839 // call.
2840 float dminmn = static_cast<float> (minmn);
2841 float dsmlsizp1 = static_cast<float> (smlsiz+1);
2842 #if defined (HAVE_LOG2)
2843 float tmp = log2 (dminmn / dsmlsizp1);
2844 #else
2845 float tmp = log (dminmn / dsmlsizp1) / log (2.0);
2846 #endif
2847 octave_idx_type nlvl = static_cast<octave_idx_type> (tmp) + 1;
2848 if (nlvl < 0)
2849 nlvl = 0;
2850
2851 octave_idx_type lrwork = minmn*(10 + 2*smlsiz + 8*nlvl)
2852 + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);
2853 if (lrwork < 1)
2854 lrwork = 1;
2855 Array<float> rwork (dim_vector (lrwork, 1));
2856 float *prwork = rwork.fortran_vec ();
2857
2858 octave_idx_type liwork = 3 * minmn * nlvl + 11 * minmn;
2859 if (liwork < 1)
2860 liwork = 1;
2861 Array<octave_idx_type> iwork (dim_vector (liwork, 1));
2862 octave_idx_type* piwork = iwork.fortran_vec ();
2863
2864 F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
2865 ps, rcon, rank, work.fortran_vec (),
2866 lwork, prwork, piwork, info));
2867
2868 lwork = static_cast<octave_idx_type> (std::real (work(0)));
2869 work.resize (dim_vector (lwork, 1));
2870 rwork.resize (dim_vector (static_cast<octave_idx_type> (rwork(0)), 1));
2871 iwork.resize (dim_vector (iwork(0), 1));
2872
2873 F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, tmp_data, m, pretval,
2874 maxmn, ps, rcon, rank,
2875 work.fortran_vec (), lwork,
2876 prwork, piwork, info));
2877
2878 if (rank < minmn)
2879 {
2880 if (s.elem (0) == 0.0)
2881 rcon = 0.0;
2882 else
2883 rcon = s.elem (minmn - 1) / s.elem (0);
2884
2885 retval.resize (n, nrhs);
2886 }
2887 }
2888
2889 return retval;
2890 }
2891
2892 // column vector by row vector -> matrix operations
2893
2894 FloatComplexMatrix
2895 operator * (const FloatColumnVector& v, const FloatComplexRowVector& a)
2896 {
2897 FloatComplexColumnVector tmp (v);
2898 return tmp * a;
2899 }
2900
2901 FloatComplexMatrix
2902 operator * (const FloatComplexColumnVector& a, const FloatRowVector& b)
2903 {
2904 FloatComplexRowVector tmp (b);
2905 return a * tmp;
2906 }
2907
2908 FloatComplexMatrix
2909 operator * (const FloatComplexColumnVector& v, const FloatComplexRowVector& a)
2910 {
2911 FloatComplexMatrix retval;
2912
2913 octave_idx_type len = v.length ();
2914
2915 if (len != 0)
2916 {
2917 octave_idx_type a_len = a.length ();
2918
2919 retval = FloatComplexMatrix (len, a_len);
2920 FloatComplex *c = retval.fortran_vec ();
2921
2922 F77_XFCN (cgemm, CGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
2923 F77_CONST_CHAR_ARG2 ("N", 1),
2924 len, a_len, 1, 1.0, v.data (), len,
2925 a.data (), 1, 0.0, c, len
2926 F77_CHAR_ARG_LEN (1)
2927 F77_CHAR_ARG_LEN (1)));
2928 }
2929
2930 return retval;
2931 }
2932
2933 // matrix by diagonal matrix -> matrix operations
2934
2935 FloatComplexMatrix&
2936 FloatComplexMatrix::operator += (const FloatDiagMatrix& a)
2937 {
2938 octave_idx_type nr = rows ();
2939 octave_idx_type nc = cols ();
2940
2941 octave_idx_type a_nr = rows ();
2942 octave_idx_type a_nc = cols ();
2943
2944 if (nr != a_nr || nc != a_nc)
2945 {
2946 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc);
2947 return *this;
2948 }
2949
2950 for (octave_idx_type i = 0; i < a.length (); i++)
2951 elem (i, i) += a.elem (i, i);
2952
2953 return *this;
2954 }
2955
2956 FloatComplexMatrix&
2957 FloatComplexMatrix::operator -= (const FloatDiagMatrix& a)
2958 {
2959 octave_idx_type nr = rows ();
2960 octave_idx_type nc = cols ();
2961
2962 octave_idx_type a_nr = rows ();
2963 octave_idx_type a_nc = cols ();
2964
2965 if (nr != a_nr || nc != a_nc)
2966 {
2967 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc);
2968 return *this;
2969 }
2970
2971 for (octave_idx_type i = 0; i < a.length (); i++)
2972 elem (i, i) -= a.elem (i, i);
2973
2974 return *this;
2975 }
2976
2977 FloatComplexMatrix&
2978 FloatComplexMatrix::operator += (const FloatComplexDiagMatrix& a)
2979 {
2980 octave_idx_type nr = rows ();
2981 octave_idx_type nc = cols ();
2982
2983 octave_idx_type a_nr = rows ();
2984 octave_idx_type a_nc = cols ();
2985
2986 if (nr != a_nr || nc != a_nc)
2987 {
2988 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc);
2989 return *this;
2990 }
2991
2992 for (octave_idx_type i = 0; i < a.length (); i++)
2993 elem (i, i) += a.elem (i, i);
2994
2995 return *this;
2996 }
2997
2998 FloatComplexMatrix&
2999 FloatComplexMatrix::operator -= (const FloatComplexDiagMatrix& a)
3000 {
3001 octave_idx_type nr = rows ();
3002 octave_idx_type nc = cols ();
3003
3004 octave_idx_type a_nr = rows ();
3005 octave_idx_type a_nc = cols ();
3006
3007 if (nr != a_nr || nc != a_nc)
3008 {
3009 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc);
3010 return *this;
3011 }
3012
3013 for (octave_idx_type i = 0; i < a.length (); i++)
3014 elem (i, i) -= a.elem (i, i);
3015
3016 return *this;
3017 }
3018
3019 // matrix by matrix -> matrix operations
3020
3021 FloatComplexMatrix&
3022 FloatComplexMatrix::operator += (const FloatMatrix& a)
3023 {
3024 octave_idx_type nr = rows ();
3025 octave_idx_type nc = cols ();
3026
3027 octave_idx_type a_nr = a.rows ();
3028 octave_idx_type a_nc = a.cols ();
3029
3030 if (nr != a_nr || nc != a_nc)
3031 {
3032 gripe_nonconformant ("operator +=", nr, nc, a_nr, a_nc);
3033 return *this;
3034 }
3035
3036 if (nr == 0 || nc == 0)
3037 return *this;
3038
3039 FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
3040
3041 mx_inline_add2 (length (), d, a.data ());
3042 return *this;
3043 }
3044
3045 FloatComplexMatrix&
3046 FloatComplexMatrix::operator -= (const FloatMatrix& a)
3047 {
3048 octave_idx_type nr = rows ();
3049 octave_idx_type nc = cols ();
3050
3051 octave_idx_type a_nr = a.rows ();
3052 octave_idx_type a_nc = a.cols ();
3053
3054 if (nr != a_nr || nc != a_nc)
3055 {
3056 gripe_nonconformant ("operator -=", nr, nc, a_nr, a_nc);
3057 return *this;
3058 }
3059
3060 if (nr == 0 || nc == 0)
3061 return *this;
3062
3063 FloatComplex *d = fortran_vec (); // Ensures only one reference to my privates!
3064
3065 mx_inline_sub2 (length (), d, a.data ());
3066 return *this;
3067 }
3068
3069 // unary operations
3070
3071 boolMatrix
3072 FloatComplexMatrix::operator ! (void) const
3073 {
3074 if (any_element_is_nan ())
3075 gripe_nan_to_logical_conversion ();
3076
3077 return do_mx_unary_op<bool, FloatComplex> (*this, mx_inline_not);
3078 }
3079
3080 // other operations
3081
3082 bool
3083 FloatComplexMatrix::any_element_is_nan (void) const
3084 {
3085 return do_mx_check<FloatComplex> (*this, mx_inline_any_nan);
3086 }
3087
3088 bool
3089 FloatComplexMatrix::any_element_is_inf_or_nan (void) const
3090 {
3091 return ! do_mx_check<FloatComplex> (*this, mx_inline_all_finite);
3092 }
3093
3094 // Return true if no elements have imaginary components.
3095
3096 bool
3097 FloatComplexMatrix::all_elements_are_real (void) const
3098 {
3099 return do_mx_check<FloatComplex> (*this, mx_inline_all_real);
3100 }
3101
3102 // Return nonzero if any element of CM has a non-integer real or
3103 // imaginary part. Also extract the largest and smallest (real or
3104 // imaginary) values and return them in MAX_VAL and MIN_VAL.
3105
3106 bool
3107 FloatComplexMatrix::all_integers (float& max_val, float& min_val) const
3108 {
3109 octave_idx_type nr = rows ();
3110 octave_idx_type nc = cols ();
3111
3112 if (nr > 0 && nc > 0)
3113 {
3114 FloatComplex val = elem (0, 0);
3115
3116 float r_val = std::real (val);
3117 float i_val = std::imag (val);
3118
3119 max_val = r_val;
3120 min_val = r_val;
3121
3122 if (i_val > max_val)
3123 max_val = i_val;
3124
3125 if (i_val < max_val)
3126 min_val = i_val;
3127 }
3128 else
3129 return false;
3130
3131 for (octave_idx_type j = 0; j < nc; j++)
3132 for (octave_idx_type i = 0; i < nr; i++)
3133 {
3134 FloatComplex val = elem (i, j);
3135
3136 float r_val = std::real (val);
3137 float i_val = std::imag (val);
3138
3139 if (r_val > max_val)
3140 max_val = r_val;
3141
3142 if (i_val > max_val)
3143 max_val = i_val;
3144
3145 if (r_val < min_val)
3146 min_val = r_val;
3147
3148 if (i_val < min_val)
3149 min_val = i_val;
3150
3151 if (D_NINT (r_val) != r_val || D_NINT (i_val) != i_val)
3152 return false;
3153 }
3154
3155 return true;
3156 }
3157
3158 bool
3159 FloatComplexMatrix::too_large_for_float (void) const
3160 {
3161 return false;
3162 }
3163
3164 // FIXME Do these really belong here? Maybe they should be
3165 // in a base class?
3166
3167 boolMatrix
3168 FloatComplexMatrix::all (int dim) const
3169 {
3170 return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_all);
3171 }
3172
3173 boolMatrix
3174 FloatComplexMatrix::any (int dim) const
3175 {
3176 return do_mx_red_op<bool, FloatComplex> (*this, dim, mx_inline_any);
3177 }
3178
3179 FloatComplexMatrix
3180 FloatComplexMatrix::cumprod (int dim) const
3181 {
3182 return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_cumprod);
3183 }
3184
3185 FloatComplexMatrix
3186 FloatComplexMatrix::cumsum (int dim) const
3187 {
3188 return do_mx_cum_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_cumsum);
3189 }
3190
3191 FloatComplexMatrix
3192 FloatComplexMatrix::prod (int dim) const
3193 {
3194 return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_prod);
3195 }
3196
3197 FloatComplexMatrix
3198 FloatComplexMatrix::sum (int dim) const
3199 {
3200 return do_mx_red_op<FloatComplex, FloatComplex> (*this, dim, mx_inline_sum);
3201 }
3202
3203 FloatComplexMatrix
3204 FloatComplexMatrix::sumsq (int dim) const
3205 {
3206 return do_mx_red_op<float, FloatComplex> (*this, dim, mx_inline_sumsq);
3207 }
3208
3209 FloatMatrix FloatComplexMatrix::abs (void) const
3210 {
3211 return do_mx_unary_map<float, FloatComplex, std::abs> (*this);
3212 }
3213
3214 FloatComplexMatrix
3215 FloatComplexMatrix::diag (octave_idx_type k) const
3216 {
3217 return MArray<FloatComplex>::diag (k);
3218 }
3219
3220 FloatComplexDiagMatrix
3221 FloatComplexMatrix::diag (octave_idx_type m, octave_idx_type n) const
3222 {
3223 FloatComplexDiagMatrix retval;
3224
3225 octave_idx_type nr = rows ();
3226 octave_idx_type nc = cols ();
3227
3228 if (nr == 1 || nc == 1)
3229 retval = FloatComplexDiagMatrix (*this, m, n);
3230 else
3231 (*current_liboctave_error_handler)
3232 ("diag: expecting vector argument");
3233
3234 return retval;
3235 }
3236
3237 bool
3238 FloatComplexMatrix::row_is_real_only (octave_idx_type i) const
3239 {
3240 bool retval = true;
3241
3242 octave_idx_type nc = columns ();
3243
3244 for (octave_idx_type j = 0; j < nc; j++)
3245 {
3246 if (std::imag (elem (i, j)) != 0.0)
3247 {
3248 retval = false;
3249 break;
3250 }
3251 }
3252
3253 return retval;
3254 }
3255
3256 bool
3257 FloatComplexMatrix::column_is_real_only (octave_idx_type j) const
3258 {
3259 bool retval = true;
3260
3261 octave_idx_type nr = rows ();
3262
3263 for (octave_idx_type i = 0; i < nr; i++)
3264 {
3265 if (std::imag (elem (i, j)) != 0.0)
3266 {
3267 retval = false;
3268 break;
3269 }
3270 }
3271
3272 return retval;
3273 }
3274
3275 FloatComplexColumnVector
3276 FloatComplexMatrix::row_min (void) const
3277 {
3278 Array<octave_idx_type> dummy_idx;
3279 return row_min (dummy_idx);
3280 }
3281
3282 FloatComplexColumnVector
3283 FloatComplexMatrix::row_min (Array<octave_idx_type>& idx_arg) const
3284 {
3285 FloatComplexColumnVector result;
3286
3287 octave_idx_type nr = rows ();
3288 octave_idx_type nc = cols ();
3289
3290 if (nr > 0 && nc > 0)
3291 {
3292 result.resize (nr);
3293 idx_arg.resize (dim_vector (nr, 1));
3294
3295 for (octave_idx_type i = 0; i < nr; i++)
3296 {
3297 bool real_only = row_is_real_only (i);
3298
3299 octave_idx_type idx_j;
3300
3301 FloatComplex tmp_min;
3302
3303 float abs_min = octave_Float_NaN;
3304
3305 for (idx_j = 0; idx_j < nc; idx_j++)
3306 {
3307 tmp_min = elem (i, idx_j);
3308
3309 if (! xisnan (tmp_min))
3310 {
3311 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min);
3312 break;
3313 }
3314 }
3315
3316 for (octave_idx_type j = idx_j+1; j < nc; j++)
3317 {
3318 FloatComplex tmp = elem (i, j);
3319
3320 if (xisnan (tmp))
3321 continue;
3322
3323 float abs_tmp = real_only ? std::real (tmp) : std::abs (tmp);
3324
3325 if (abs_tmp < abs_min)
3326 {
3327 idx_j = j;
3328 tmp_min = tmp;
3329 abs_min = abs_tmp;
3330 }
3331 }
3332
3333 if (xisnan (tmp_min))
3334 {
3335 result.elem (i) = FloatComplex_NaN_result;
3336 idx_arg.elem (i) = 0;
3337 }
3338 else
3339 {
3340 result.elem (i) = tmp_min;
3341 idx_arg.elem (i) = idx_j;
3342 }
3343 }
3344 }
3345
3346 return result;
3347 }
3348
3349 FloatComplexColumnVector
3350 FloatComplexMatrix::row_max (void) const
3351 {
3352 Array<octave_idx_type> dummy_idx;
3353 return row_max (dummy_idx);
3354 }
3355
3356 FloatComplexColumnVector
3357 FloatComplexMatrix::row_max (Array<octave_idx_type>& idx_arg) const
3358 {
3359 FloatComplexColumnVector result;
3360
3361 octave_idx_type nr = rows ();
3362 octave_idx_type nc = cols ();
3363
3364 if (nr > 0 && nc > 0)
3365 {
3366 result.resize (nr);
3367 idx_arg.resize (dim_vector (nr, 1));
3368
3369 for (octave_idx_type i = 0; i < nr; i++)
3370 {
3371 bool real_only = row_is_real_only (i);
3372
3373 octave_idx_type idx_j;
3374
3375 FloatComplex tmp_max;
3376
3377 float abs_max = octave_Float_NaN;
3378
3379 for (idx_j = 0; idx_j < nc; idx_j++)
3380 {
3381 tmp_max = elem (i, idx_j);
3382
3383 if (! xisnan (tmp_max))
3384 {
3385 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max);
3386 break;
3387 }
3388 }
3389
3390 for (octave_idx_type j = idx_j+1; j < nc; j++)
3391 {
3392 FloatComplex tmp = elem (i, j);
3393
3394 if (xisnan (tmp))
3395 continue;
3396
3397 float abs_tmp = real_only ? std::real (tmp) : std::abs (tmp);
3398
3399 if (abs_tmp > abs_max)
3400 {
3401 idx_j = j;
3402 tmp_max = tmp;
3403 abs_max = abs_tmp;
3404 }
3405 }
3406
3407 if (xisnan (tmp_max))
3408 {
3409 result.elem (i) = FloatComplex_NaN_result;
3410 idx_arg.elem (i) = 0;
3411 }
3412 else
3413 {
3414 result.elem (i) = tmp_max;
3415 idx_arg.elem (i) = idx_j;
3416 }
3417 }
3418 }
3419
3420 return result;
3421 }
3422
3423 FloatComplexRowVector
3424 FloatComplexMatrix::column_min (void) const
3425 {
3426 Array<octave_idx_type> dummy_idx;
3427 return column_min (dummy_idx);
3428 }
3429
3430 FloatComplexRowVector
3431 FloatComplexMatrix::column_min (Array<octave_idx_type>& idx_arg) const
3432 {
3433 FloatComplexRowVector result;
3434
3435 octave_idx_type nr = rows ();
3436 octave_idx_type nc = cols ();
3437
3438 if (nr > 0 && nc > 0)
3439 {
3440 result.resize (nc);
3441 idx_arg.resize (dim_vector (1, nc));
3442
3443 for (octave_idx_type j = 0; j < nc; j++)
3444 {
3445 bool real_only = column_is_real_only (j);
3446
3447 octave_idx_type idx_i;
3448
3449 FloatComplex tmp_min;
3450
3451 float abs_min = octave_Float_NaN;
3452
3453 for (idx_i = 0; idx_i < nr; idx_i++)
3454 {
3455 tmp_min = elem (idx_i, j);
3456
3457 if (! xisnan (tmp_min))
3458 {
3459 abs_min = real_only ? std::real (tmp_min) : std::abs (tmp_min);
3460 break;
3461 }
3462 }
3463
3464 for (octave_idx_type i = idx_i+1; i < nr; i++)
3465 {
3466 FloatComplex tmp = elem (i, j);
3467
3468 if (xisnan (tmp))
3469 continue;
3470
3471 float abs_tmp = real_only ? std::real (tmp) : std::abs (tmp);
3472
3473 if (abs_tmp < abs_min)
3474 {
3475 idx_i = i;
3476 tmp_min = tmp;
3477 abs_min = abs_tmp;
3478 }
3479 }
3480
3481 if (xisnan (tmp_min))
3482 {
3483 result.elem (j) = FloatComplex_NaN_result;
3484 idx_arg.elem (j) = 0;
3485 }
3486 else
3487 {
3488 result.elem (j) = tmp_min;
3489 idx_arg.elem (j) = idx_i;
3490 }
3491 }
3492 }
3493
3494 return result;
3495 }
3496
3497 FloatComplexRowVector
3498 FloatComplexMatrix::column_max (void) const
3499 {
3500 Array<octave_idx_type> dummy_idx;
3501 return column_max (dummy_idx);
3502 }
3503
3504 FloatComplexRowVector
3505 FloatComplexMatrix::column_max (Array<octave_idx_type>& idx_arg) const
3506 {
3507 FloatComplexRowVector result;
3508
3509 octave_idx_type nr = rows ();
3510 octave_idx_type nc = cols ();
3511
3512 if (nr > 0 && nc > 0)
3513 {
3514 result.resize (nc);
3515 idx_arg.resize (dim_vector (1, nc));
3516
3517 for (octave_idx_type j = 0; j < nc; j++)
3518 {
3519 bool real_only = column_is_real_only (j);
3520
3521 octave_idx_type idx_i;
3522
3523 FloatComplex tmp_max;
3524
3525 float abs_max = octave_Float_NaN;
3526
3527 for (idx_i = 0; idx_i < nr; idx_i++)
3528 {
3529 tmp_max = elem (idx_i, j);
3530
3531 if (! xisnan (tmp_max))
3532 {
3533 abs_max = real_only ? std::real (tmp_max) : std::abs (tmp_max);
3534 break;
3535 }
3536 }
3537
3538 for (octave_idx_type i = idx_i+1; i < nr; i++)
3539 {
3540 FloatComplex tmp = elem (i, j);
3541
3542 if (xisnan (tmp))
3543 continue;
3544
3545 float abs_tmp = real_only ? std::real (tmp) : std::abs (tmp);
3546
3547 if (abs_tmp > abs_max)
3548 {
3549 idx_i = i;
3550 tmp_max = tmp;
3551 abs_max = abs_tmp;
3552 }
3553 }
3554
3555 if (xisnan (tmp_max))
3556 {
3557 result.elem (j) = FloatComplex_NaN_result;
3558 idx_arg.elem (j) = 0;
3559 }
3560 else
3561 {
3562 result.elem (j) = tmp_max;
3563 idx_arg.elem (j) = idx_i;
3564 }
3565 }
3566 }
3567
3568 return result;
3569 }
3570
3571 // i/o
3572
3573 std::ostream&
3574 operator << (std::ostream& os, const FloatComplexMatrix& a)
3575 {
3576 for (octave_idx_type i = 0; i < a.rows (); i++)
3577 {
3578 for (octave_idx_type j = 0; j < a.cols (); j++)
3579 {
3580 os << " ";
3581 octave_write_complex (os, a.elem (i, j));
3582 }
3583 os << "\n";
3584 }
3585 return os;
3586 }
3587
3588 std::istream&
3589 operator >> (std::istream& is, FloatComplexMatrix& a)
3590 {
3591 octave_idx_type nr = a.rows ();
3592 octave_idx_type nc = a.cols ();
3593
3594 if (nr > 0 && nc > 0)
3595 {
3596 FloatComplex tmp;
3597 for (octave_idx_type i = 0; i < nr; i++)
3598 for (octave_idx_type j = 0; j < nc; j++)
3599 {
3600 tmp = octave_read_value<FloatComplex> (is);
3601 if (is)
3602 a.elem (i, j) = tmp;
3603 else
3604 goto done;
3605 }
3606 }
3607
3608 done:
3609
3610 return is;
3611 }
3612
3613 FloatComplexMatrix
3614 Givens (const FloatComplex& x, const FloatComplex& y)
3615 {
3616 float cc;
3617 FloatComplex cs, temp_r;
3618
3619 F77_FUNC (clartg, CLARTG) (x, y, cc, cs, temp_r);
3620
3621 FloatComplexMatrix g (2, 2);
3622
3623 g.elem (0, 0) = cc;
3624 g.elem (1, 1) = cc;
3625 g.elem (0, 1) = cs;
3626 g.elem (1, 0) = -conj (cs);
3627
3628 return g;
3629 }
3630
3631 FloatComplexMatrix
3632 Sylvester (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
3633 const FloatComplexMatrix& c)
3634 {
3635 FloatComplexMatrix retval;
3636
3637 // FIXME -- need to check that a, b, and c are all the same
3638 // size.
3639
3640 // Compute Schur decompositions
3641
3642 FloatComplexSCHUR as (a, "U");
3643 FloatComplexSCHUR bs (b, "U");
3644
3645 // Transform c to new coordinates.
3646
3647 FloatComplexMatrix ua = as.unitary_matrix ();
3648 FloatComplexMatrix sch_a = as.schur_matrix ();
3649
3650 FloatComplexMatrix ub = bs.unitary_matrix ();
3651 FloatComplexMatrix sch_b = bs.schur_matrix ();
3652
3653 FloatComplexMatrix cx = ua.hermitian () * c * ub;
3654
3655 // Solve the sylvester equation, back-transform, and return the
3656 // solution.
3657
3658 octave_idx_type a_nr = a.rows ();
3659 octave_idx_type b_nr = b.rows ();
3660
3661 float scale;
3662 octave_idx_type info;
3663
3664 FloatComplex *pa = sch_a.fortran_vec ();
3665 FloatComplex *pb = sch_b.fortran_vec ();
3666 FloatComplex *px = cx.fortran_vec ();
3667
3668 F77_XFCN (ctrsyl, CTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
3669 F77_CONST_CHAR_ARG2 ("N", 1),
3670 1, a_nr, b_nr, pa, a_nr, pb,
3671 b_nr, px, a_nr, scale, info
3672 F77_CHAR_ARG_LEN (1)
3673 F77_CHAR_ARG_LEN (1)));
3674
3675 // FIXME -- check info?
3676
3677 retval = -ua * cx * ub.hermitian ();
3678
3679 return retval;
3680 }
3681
3682 FloatComplexMatrix
3683 operator * (const FloatComplexMatrix& m, const FloatMatrix& a)
3684 {
3685 if (m.columns () > std::min (m.rows (), a.columns ()) / 10)
3686 return FloatComplexMatrix (real (m) * a, imag (m) * a);
3687 else
3688 return m * FloatComplexMatrix (a);
3689 }
3690
3691 FloatComplexMatrix
3692 operator * (const FloatMatrix& m, const FloatComplexMatrix& a)
3693 {
3694 if (a.rows () > std::min (m.rows (), a.columns ()) / 10)
3695 return FloatComplexMatrix (m * real (a), m * imag (a));
3696 else
3697 return m * FloatComplexMatrix (a);
3698 }
3699
3700 /*
3701
3702 ## Simple Dot Product, Matrix-Vector, and Matrix-Matrix Unit tests
3703 %!assert (single ([1+i 2+i 3+i]) * single ([ 4+i ; 5+i ; 6+i]), single (29+21i), 5e-7)
3704 %!assert (single ([1+i 2+i ; 3+i 4+i]) * single ([5+i ; 6+i]), single ([15 + 14i ; 37 + 18i]), 5e-7)
3705 %!assert (single ([1+i 2+i ; 3+i 4+i ]) * single ([5+i 6+i ; 7+i 8+i]), single ([17 + 15i 20 + 17i; 41 + 19i 48 + 21i]), 5e-7)
3706 %!assert (single ([1 i])*single ([i 0])', single (-i))
3707
3708 ## Test some simple identities
3709 %!shared M, cv, rv
3710 %! M = single (randn (10,10))+ i*single (rand (10,10));
3711 %! cv = single (randn (10,1))+ i*single (rand (10,1));
3712 %! rv = single (randn (1,10))+ i*single (rand (1,10));
3713 %!assert ([M*cv,M*cv], M*[cv,cv], 5e-6)
3714 %!assert ([M.'*cv,M.'*cv], M.'*[cv,cv], 5e-6)
3715 %!assert ([M'*cv,M'*cv], M'*[cv,cv], 5e-6)
3716 %!assert ([rv*M;rv*M], [rv;rv]*M, 5e-6)
3717 %!assert ([rv*M.';rv*M.'], [rv;rv]*M.', 5e-6)
3718 %!assert ([rv*M';rv*M'], [rv;rv]*M', 5e-6)
3719 %!assert (2*rv*cv, [rv,rv]*[cv;cv], 5e-6)
3720
3721 */
3722
3723 static char
3724 get_blas_trans_arg (bool trans, bool conj)
3725 {
3726 return trans ? (conj ? 'C' : 'T') : 'N';
3727 }
3728
3729 // the general GEMM operation
3730
3731 FloatComplexMatrix
3732 xgemm (const FloatComplexMatrix& a, const FloatComplexMatrix& b,
3733 blas_trans_type transa, blas_trans_type transb)
3734 {
3735 FloatComplexMatrix retval;
3736
3737 bool tra = transa != blas_no_trans, trb = transb != blas_no_trans;
3738 bool cja = transa == blas_conj_trans, cjb = transb == blas_conj_trans;
3739
3740 octave_idx_type a_nr = tra ? a.cols () : a.rows ();
3741 octave_idx_type a_nc = tra ? a.rows () : a.cols ();
3742
3743 octave_idx_type b_nr = trb ? b.cols () : b.rows ();
3744 octave_idx_type b_nc = trb ? b.rows () : b.cols ();
3745
3746 if (a_nc != b_nr)
3747 gripe_nonconformant ("operator *", a_nr, a_nc, b_nr, b_nc);
3748 else
3749 {
3750 if (a_nr == 0 || a_nc == 0 || b_nc == 0)
3751 retval = FloatComplexMatrix (a_nr, b_nc, 0.0);
3752 else if (a.data () == b.data () && a_nr == b_nc && tra != trb)
3753 {
3754 octave_idx_type lda = a.rows ();
3755
3756 // FIXME -- looking at the reference BLAS, it appears that it
3757 // should not be necessary to initialize the output matrix if
3758 // BETA is 0 in the call to CHERK, but ATLAS appears to
3759 // use the result matrix before zeroing the elements.
3760
3761 retval = FloatComplexMatrix (a_nr, b_nc, 0.0);
3762 FloatComplex *c = retval.fortran_vec ();
3763
3764 const char ctra = get_blas_trans_arg (tra, cja);
3765 if (cja || cjb)
3766 {
3767 F77_XFCN (cherk, CHERK, (F77_CONST_CHAR_ARG2 ("U", 1),
3768 F77_CONST_CHAR_ARG2 (&ctra, 1),
3769 a_nr, a_nc, 1.0,
3770 a.data (), lda, 0.0, c, a_nr
3771 F77_CHAR_ARG_LEN (1)
3772 F77_CHAR_ARG_LEN (1)));
3773 for (octave_idx_type j = 0; j < a_nr; j++)
3774 for (octave_idx_type i = 0; i < j; i++)
3775 retval.xelem (j,i) = std::conj (retval.xelem (i,j));
3776 }
3777 else
3778 {
3779 F77_XFCN (csyrk, CSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
3780 F77_CONST_CHAR_ARG2 (&ctra, 1),
3781 a_nr, a_nc, 1.0,
3782 a.data (), lda, 0.0, c, a_nr
3783 F77_CHAR_ARG_LEN (1)
3784 F77_CHAR_ARG_LEN (1)));
3785 for (octave_idx_type j = 0; j < a_nr; j++)
3786 for (octave_idx_type i = 0; i < j; i++)
3787 retval.xelem (j,i) = retval.xelem (i,j);
3788
3789 }
3790
3791 }
3792 else
3793 {
3794 octave_idx_type lda = a.rows (), tda = a.cols ();
3795 octave_idx_type ldb = b.rows (), tdb = b.cols ();
3796
3797 retval = FloatComplexMatrix (a_nr, b_nc, 0.0);
3798 FloatComplex *c = retval.fortran_vec ();
3799
3800 if (b_nc == 1 && a_nr == 1)
3801 {
3802 if (cja == cjb)
3803 {
3804 F77_FUNC (xcdotu, XCDOTU) (a_nc, a.data (), 1, b.data (), 1, *c);
3805 if (cja) *c = std::conj (*c);
3806 }
3807 else if (cja)
3808 F77_FUNC (xcdotc, XCDOTC) (a_nc, a.data (), 1, b.data (), 1, *c);
3809 else
3810 F77_FUNC (xcdotc, XCDOTC) (a_nc, b.data (), 1, a.data (), 1, *c);
3811 }
3812 else if (b_nc == 1 && ! cjb)
3813 {
3814 const char ctra = get_blas_trans_arg (tra, cja);
3815 F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (&ctra, 1),
3816 lda, tda, 1.0, a.data (), lda,
3817 b.data (), 1, 0.0, c, 1
3818 F77_CHAR_ARG_LEN (1)));
3819 }
3820 else if (a_nr == 1 && ! cja && ! cjb)
3821 {
3822 const char crevtrb = get_blas_trans_arg (! trb, cjb);
3823 F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 (&crevtrb, 1),
3824 ldb, tdb, 1.0, b.data (), ldb,
3825 a.data (), 1, 0.0, c, 1
3826 F77_CHAR_ARG_LEN (1)));
3827 }
3828 else
3829 {
3830 const char ctra = get_blas_trans_arg (tra, cja);
3831 const char ctrb = get_blas_trans_arg (trb, cjb);
3832 F77_XFCN (cgemm, CGEMM, (F77_CONST_CHAR_ARG2 (&ctra, 1),
3833 F77_CONST_CHAR_ARG2 (&ctrb, 1),
3834 a_nr, b_nc, a_nc, 1.0, a.data (),
3835 lda, b.data (), ldb, 0.0, c, a_nr
3836 F77_CHAR_ARG_LEN (1)
3837 F77_CHAR_ARG_LEN (1)));
3838 }
3839 }
3840 }
3841
3842 return retval;
3843 }
3844
3845 FloatComplexMatrix
3846 operator * (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
3847 {
3848 return xgemm (a, b);
3849 }
3850
3851 // FIXME -- it would be nice to share code among the min/max
3852 // functions below.
3853
3854 #define EMPTY_RETURN_CHECK(T) \
3855 if (nr == 0 || nc == 0) \
3856 return T (nr, nc);
3857
3858 FloatComplexMatrix
3859 min (const FloatComplex& c, const FloatComplexMatrix& m)
3860 {
3861 octave_idx_type nr = m.rows ();
3862 octave_idx_type nc = m.columns ();
3863
3864 EMPTY_RETURN_CHECK (FloatComplexMatrix);
3865
3866 FloatComplexMatrix result (nr, nc);
3867
3868 for (octave_idx_type j = 0; j < nc; j++)
3869 for (octave_idx_type i = 0; i < nr; i++)
3870 {
3871 octave_quit ();
3872 result (i, j) = xmin (c, m (i, j));
3873 }
3874
3875 return result;
3876 }
3877
3878 FloatComplexMatrix
3879 min (const FloatComplexMatrix& m, const FloatComplex& c)
3880 {
3881 octave_idx_type nr = m.rows ();
3882 octave_idx_type nc = m.columns ();
3883
3884 EMPTY_RETURN_CHECK (FloatComplexMatrix);
3885
3886 FloatComplexMatrix result (nr, nc);
3887
3888 for (octave_idx_type j = 0; j < nc; j++)
3889 for (octave_idx_type i = 0; i < nr; i++)
3890 {
3891 octave_quit ();
3892 result (i, j) = xmin (m (i, j), c);
3893 }
3894
3895 return result;
3896 }
3897
3898 FloatComplexMatrix
3899 min (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
3900 {
3901 octave_idx_type nr = a.rows ();
3902 octave_idx_type nc = a.columns ();
3903
3904 if (nr != b.rows () || nc != b.columns ())
3905 {
3906 (*current_liboctave_error_handler)
3907 ("two-arg min expecting args of same size");
3908 return FloatComplexMatrix ();
3909 }
3910
3911 EMPTY_RETURN_CHECK (FloatComplexMatrix);
3912
3913 FloatComplexMatrix result (nr, nc);
3914
3915 for (octave_idx_type j = 0; j < nc; j++)
3916 {
3917 int columns_are_real_only = 1;
3918 for (octave_idx_type i = 0; i < nr; i++)
3919 {
3920 octave_quit ();
3921 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0)
3922 {
3923 columns_are_real_only = 0;
3924 break;
3925 }
3926 }
3927
3928 if (columns_are_real_only)
3929 {
3930 for (octave_idx_type i = 0; i < nr; i++)
3931 result (i, j) = xmin (std::real (a (i, j)), std::real (b (i, j)));
3932 }
3933 else
3934 {
3935 for (octave_idx_type i = 0; i < nr; i++)
3936 {
3937 octave_quit ();
3938 result (i, j) = xmin (a (i, j), b (i, j));
3939 }
3940 }
3941 }
3942
3943 return result;
3944 }
3945
3946 FloatComplexMatrix
3947 max (const FloatComplex& c, const FloatComplexMatrix& m)
3948 {
3949 octave_idx_type nr = m.rows ();
3950 octave_idx_type nc = m.columns ();
3951
3952 EMPTY_RETURN_CHECK (FloatComplexMatrix);
3953
3954 FloatComplexMatrix result (nr, nc);
3955
3956 for (octave_idx_type j = 0; j < nc; j++)
3957 for (octave_idx_type i = 0; i < nr; i++)
3958 {
3959 octave_quit ();
3960 result (i, j) = xmax (c, m (i, j));
3961 }
3962
3963 return result;
3964 }
3965
3966 FloatComplexMatrix
3967 max (const FloatComplexMatrix& m, const FloatComplex& c)
3968 {
3969 octave_idx_type nr = m.rows ();
3970 octave_idx_type nc = m.columns ();
3971
3972 EMPTY_RETURN_CHECK (FloatComplexMatrix);
3973
3974 FloatComplexMatrix result (nr, nc);
3975
3976 for (octave_idx_type j = 0; j < nc; j++)
3977 for (octave_idx_type i = 0; i < nr; i++)
3978 {
3979 octave_quit ();
3980 result (i, j) = xmax (m (i, j), c);
3981 }
3982
3983 return result;
3984 }
3985
3986 FloatComplexMatrix
3987 max (const FloatComplexMatrix& a, const FloatComplexMatrix& b)
3988 {
3989 octave_idx_type nr = a.rows ();
3990 octave_idx_type nc = a.columns ();
3991
3992 if (nr != b.rows () || nc != b.columns ())
3993 {
3994 (*current_liboctave_error_handler)
3995 ("two-arg max expecting args of same size");
3996 return FloatComplexMatrix ();
3997 }
3998
3999 EMPTY_RETURN_CHECK (FloatComplexMatrix);
4000
4001 FloatComplexMatrix result (nr, nc);
4002
4003 for (octave_idx_type j = 0; j < nc; j++)
4004 {
4005 int columns_are_real_only = 1;
4006 for (octave_idx_type i = 0; i < nr; i++)
4007 {
4008 octave_quit ();
4009 if (std::imag (a (i, j)) != 0.0 || std::imag (b (i, j)) != 0.0)
4010 {
4011 columns_are_real_only = 0;
4012 break;
4013 }
4014 }
4015
4016 if (columns_are_real_only)
4017 {
4018 for (octave_idx_type i = 0; i < nr; i++)
4019 {
4020 octave_quit ();
4021 result (i, j) = xmax (std::real (a (i, j)), std::real (b (i, j)));
4022 }
4023 }
4024 else
4025 {
4026 for (octave_idx_type i = 0; i < nr; i++)
4027 {
4028 octave_quit ();
4029 result (i, j) = xmax (a (i, j), b (i, j));
4030 }
4031 }
4032 }
4033
4034 return result;
4035 }
4036
4037 FloatComplexMatrix linspace (const FloatComplexColumnVector& x1,
4038 const FloatComplexColumnVector& x2,
4039 octave_idx_type n)
4040
4041 {
4042 if (n < 1) n = 1;
4043
4044 octave_idx_type m = x1.length ();
4045
4046 if (x2.length () != m)
4047 (*current_liboctave_error_handler) ("linspace: vectors must be of equal length");
4048
4049 NoAlias<FloatComplexMatrix> retval;
4050
4051 retval.clear (m, n);
4052 for (octave_idx_type i = 0; i < m; i++)
4053 retval(i, 0) = x1(i);
4054
4055 // The last column is not needed while using delta.
4056 FloatComplex *delta = &retval(0, n-1);
4057 for (octave_idx_type i = 0; i < m; i++)
4058 delta[i] = (x2(i) - x1(i)) / (n - 1.0f);
4059
4060 for (octave_idx_type j = 1; j < n-1; j++)
4061 for (octave_idx_type i = 0; i < m; i++)
4062 retval(i, j) = x1(i) + static_cast<float> (j)*delta[i];
4063
4064 for (octave_idx_type i = 0; i < m; i++)
4065 retval(i, n-1) = x2(i);
4066
4067 return retval;
4068 }
4069
4070 MS_CMP_OPS (FloatComplexMatrix, FloatComplex)
4071 MS_BOOL_OPS (FloatComplexMatrix, FloatComplex)
4072
4073 SM_CMP_OPS (FloatComplex, FloatComplexMatrix)
4074 SM_BOOL_OPS (FloatComplex, FloatComplexMatrix)
4075
4076 MM_CMP_OPS (FloatComplexMatrix, FloatComplexMatrix)
4077 MM_BOOL_OPS (FloatComplexMatrix, FloatComplexMatrix)