Mercurial > octave-libtiff
view libinterp/corefcn/oct-map.cc @ 21301:40de9f8f23a6
Use '#include "config.h"' rather than <config.h>.
* mk-octave-config-h.sh, mk-opts.pl, Backend.cc, BaseControl.cc,
ButtonControl.cc, Canvas.cc, CheckBoxControl.cc, Container.cc, ContextMenu.cc,
EditControl.cc, Figure.cc, FigureWindow.cc, GLCanvas.cc, KeyMap.cc,
ListBoxControl.cc, Logger.cc, Menu.cc, MouseModeActionGroup.cc, Object.cc,
ObjectFactory.cc, ObjectProxy.cc, Panel.cc, PopupMenuControl.cc,
PushButtonControl.cc, PushTool.cc, QtHandlesUtils.cc, RadioButtonControl.cc,
SliderControl.cc, TextControl.cc, TextEdit.cc, ToggleButtonControl.cc,
ToggleTool.cc, ToolBar.cc, ToolBarButton.cc, __init_qt__.cc,
annotation-dialog.cc, gl-select.cc, module.mk, kpty.cpp, color-picker.cc,
dialog.cc, documentation-dock-widget.cc, files-dock-widget.cc,
find-files-dialog.cc, find-files-model.cc, history-dock-widget.cc,
file-editor-tab.cc, file-editor-tab.h, file-editor.cc, find-dialog.cc,
marker.cc, octave-qscintilla.cc, octave-txt-lexer.cc, main-window.cc,
octave-cmd.cc, octave-dock-widget.cc, octave-gui.cc, octave-interpreter.cc,
octave-qt-link.cc, parser.cc, webinfo.cc, resource-manager.cc,
settings-dialog.cc, shortcut-manager.cc, terminal-dock-widget.cc,
thread-manager.cc, welcome-wizard.cc, workspace-model.cc, workspace-view.cc,
build-env-features.sh, build-env.in.cc, Cell.cc, __contourc__.cc,
__dispatch__.cc, __dsearchn__.cc, __ichol__.cc, __ilu__.cc, __lin_interpn__.cc,
__pchip_deriv__.cc, __qp__.cc, balance.cc, besselj.cc, betainc.cc, bitfcns.cc,
bsxfun.cc, c-file-ptr-stream.cc, cdisplay.c, cellfun.cc, coct-hdf5-types.c,
colloc.cc, comment-list.cc, conv2.cc, daspk.cc, dasrt.cc, dassl.cc, data.cc,
debug.cc, defaults.cc, defun.cc, det.cc, dirfns.cc, display.cc, dlmread.cc,
dot.cc, dynamic-ld.cc, eig.cc, ellipj.cc, error.cc, errwarn.cc, event-queue.cc,
fft.cc, fft2.cc, fftn.cc, file-io.cc, filter.cc, find.cc, ft-text-renderer.cc,
gammainc.cc, gcd.cc, getgrent.cc, getpwent.cc, getrusage.cc, givens.cc,
gl-render.cc, gl2ps-print.cc, graphics.cc, gripes.cc, hash.cc, help.cc,
hess.cc, hex2num.cc, hook-fcn.cc, input.cc, inv.cc, jit-ir.cc, jit-typeinfo.cc,
jit-util.cc, kron.cc, load-path.cc, load-save.cc, lookup.cc,
ls-ascii-helper.cc, ls-hdf5.cc, ls-mat-ascii.cc, ls-mat4.cc, ls-mat5.cc,
ls-oct-binary.cc, ls-oct-text.cc, ls-utils.cc, lsode.cc, lu.cc, luinc.cc,
mappers.cc, matrix_type.cc, max.cc, mex.cc, mgorth.cc, nproc.cc,
oct-errno.in.cc, oct-fstrm.cc, oct-hdf5-types.cc, oct-hist.cc, oct-iostrm.cc,
oct-lvalue.cc, oct-map.cc, oct-prcstrm.cc, oct-procbuf.cc, oct-stream.cc,
oct-strstrm.cc, oct-tex-lexer.in.ll, oct-tex-parser.in.yy, octave-link.cc,
ordschur.cc, pager.cc, pinv.cc, pr-output.cc, procstream.cc, profiler.cc,
psi.cc, pt-jit.cc, quad.cc, quadcc.cc, qz.cc, rand.cc, rcond.cc, regexp.cc,
schur.cc, sighandlers.cc, siglist.c, sparse-xdiv.cc, sparse-xpow.cc, sparse.cc,
spparms.cc, sqrtm.cc, str2double.cc, strfind.cc, strfns.cc, sub2ind.cc, svd.cc,
sylvester.cc, symtab.cc, syscalls.cc, sysdep.cc, text-renderer.cc, time.cc,
toplev.cc, tril.cc, tsearch.cc, txt-eng.cc, typecast.cc, urlwrite.cc, utils.cc,
variables.cc, xdiv.cc, xgl2ps.c, xnorm.cc, xpow.cc, zfstream.cc,
__delaunayn__.cc, __eigs__.cc, __fltk_uigetfile__.cc, __glpk__.cc,
__init_fltk__.cc, __init_gnuplot__.cc, __magick_read__.cc, __osmesa_print__.cc,
__voronoi__.cc, amd.cc, audiodevinfo.cc, audioread.cc, ccolamd.cc, chol.cc,
colamd.cc, convhulln.cc, dmperm.cc, fftw.cc, qr.cc, symbfact.cc, symrcm.cc,
mkbuiltins, mkops, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc,
ov-base-scalar.cc, ov-base-sparse.cc, ov-base.cc, ov-bool-mat.cc,
ov-bool-sparse.cc, ov-bool.cc, ov-builtin.cc, ov-cell.cc, ov-ch-mat.cc,
ov-class.cc, ov-classdef.cc, ov-colon.cc, ov-complex.cc, ov-cs-list.cc,
ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc, ov-fcn-handle.cc,
ov-fcn-inline.cc, ov-fcn.cc, ov-float.cc, ov-flt-complex.cc, ov-flt-cx-diag.cc,
ov-flt-cx-mat.cc, ov-flt-re-diag.cc, ov-flt-re-mat.cc, ov-int16.cc,
ov-int32.cc, ov-int64.cc, ov-int8.cc, ov-java.cc, ov-lazy-idx.cc,
ov-mex-fcn.cc, ov-null-mat.cc, ov-oncleanup.cc, ov-perm.cc, ov-range.cc,
ov-re-diag.cc, ov-re-mat.cc, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc,
ov-struct.cc, ov-typeinfo.cc, ov-uint16.cc, ov-uint32.cc, ov-uint64.cc,
ov-uint8.cc, ov-usr-fcn.cc, ov.cc, ovl.cc, octave.cc, op-b-b.cc, op-b-bm.cc,
op-b-sbm.cc, op-bm-b.cc, op-bm-bm.cc, op-bm-sbm.cc, op-cdm-cdm.cc, op-cell.cc,
op-chm.cc, op-class.cc, op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc,
op-cm-scm.cc, op-cm-sm.cc, op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc, op-cs-s.cc,
op-cs-scm.cc, op-cs-sm.cc, op-dm-dm.cc, op-dm-scm.cc, op-dm-sm.cc,
op-dm-template.cc, op-dms-template.cc, op-double-conv.cc, op-fcdm-fcdm.cc,
op-fcdm-fdm.cc, op-fcm-fcm.cc, op-fcm-fcs.cc, op-fcm-fm.cc, op-fcm-fs.cc,
op-fcn.cc, op-fcs-fcm.cc, op-fcs-fcs.cc, op-fcs-fm.cc, op-fcs-fs.cc,
op-fdm-fdm.cc, op-float-conv.cc, op-fm-fcm.cc, op-fm-fcs.cc, op-fm-fm.cc,
op-fm-fs.cc, op-fs-fcm.cc, op-fs-fcs.cc, op-fs-fm.cc, op-fs-fs.cc,
op-i16-i16.cc, op-i32-i32.cc, op-i64-i64.cc, op-i8-i8.cc, op-int-concat.cc,
op-int-conv.cc, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc, op-m-scm.cc,
op-m-sm.cc, op-pm-pm.cc, op-pm-scm.cc, op-pm-sm.cc, op-pm-template.cc,
op-range.cc, op-s-cm.cc, op-s-cs.cc, op-s-m.cc, op-s-s.cc, op-s-scm.cc,
op-s-sm.cc, op-sbm-b.cc, op-sbm-bm.cc, op-sbm-sbm.cc, op-scm-cm.cc,
op-scm-cs.cc, op-scm-m.cc, op-scm-s.cc, op-scm-scm.cc, op-scm-sm.cc,
op-sm-cm.cc, op-sm-cs.cc, op-sm-m.cc, op-sm-s.cc, op-sm-scm.cc, op-sm-sm.cc,
op-str-m.cc, op-str-s.cc, op-str-str.cc, op-struct.cc, op-ui16-ui16.cc,
op-ui32-ui32.cc, op-ui64-ui64.cc, op-ui8-ui8.cc, lex.ll, oct-parse.in.yy,
pt-arg-list.cc, pt-array-list.cc, pt-assign.cc, pt-binop.cc, pt-bp.cc,
pt-cbinop.cc, pt-cell.cc, pt-check.cc, pt-classdef.cc, pt-cmd.cc, pt-colon.cc,
pt-const.cc, pt-decl.cc, pt-eval.cc, pt-except.cc, pt-exp.cc, pt-fcn-handle.cc,
pt-funcall.cc, pt-id.cc, pt-idx.cc, pt-jump.cc, pt-loop.cc, pt-mat.cc,
pt-misc.cc, pt-pr-code.cc, pt-select.cc, pt-stmt.cc, pt-unop.cc, pt.cc,
token.cc, Array-jit.cc, Array-os.cc, Array-sym.cc, Array-tc.cc, version.cc,
Array-C.cc, Array-b.cc, Array-ch.cc, Array-d.cc, Array-f.cc, Array-fC.cc,
Array-i.cc, Array-idx-vec.cc, Array-s.cc, Array-str.cc, Array-util.cc,
Array-voidp.cc, Array.cc, CColVector.cc, CDiagMatrix.cc, CMatrix.cc,
CNDArray.cc, CRowVector.cc, CSparse.cc, DiagArray2.cc, MArray-C.cc,
MArray-d.cc, MArray-f.cc, MArray-fC.cc, MArray-i.cc, MArray-s.cc, MArray.cc,
MDiagArray2.cc, MSparse-C.cc, MSparse-d.cc, MatrixType.cc, PermMatrix.cc,
Range.cc, Sparse-C.cc, Sparse-b.cc, Sparse-d.cc, Sparse.cc, boolMatrix.cc,
boolNDArray.cc, boolSparse.cc, chMatrix.cc, chNDArray.cc, dColVector.cc,
dDiagMatrix.cc, dMatrix.cc, dNDArray.cc, dRowVector.cc, dSparse.cc,
dim-vector.cc, fCColVector.cc, fCDiagMatrix.cc, fCMatrix.cc, fCNDArray.cc,
fCRowVector.cc, fColVector.cc, fDiagMatrix.cc, fMatrix.cc, fNDArray.cc,
fRowVector.cc, idx-vector.cc, int16NDArray.cc, int32NDArray.cc,
int64NDArray.cc, int8NDArray.cc, intNDArray.cc, uint16NDArray.cc,
uint32NDArray.cc, uint64NDArray.cc, uint8NDArray.cc, blaswrap.c, cquit.c,
f77-extern.cc, f77-fcn.c, lo-error.c, quit.cc, CollocWt.cc, DASPK.cc, DASRT.cc,
DASSL.cc, EIG.cc, LSODE.cc, ODES.cc, Quad.cc, aepbalance.cc, chol.cc,
eigs-base.cc, fEIG.cc, gepbalance.cc, hess.cc, lo-mappers.cc, lo-specfun.cc,
lu.cc, oct-convn.cc, oct-fftw.cc, oct-norm.cc, oct-rand.cc, oct-spparms.cc,
qr.cc, qrp.cc, randgamma.c, randmtzig.c, randpoisson.c, schur.cc,
sparse-chol.cc, sparse-dmsolve.cc, sparse-lu.cc, sparse-qr.cc, svd.cc,
mk-ops.awk, dir-ops.cc, file-ops.cc, file-stat.cc, lo-sysdep.cc, mach-info.cc,
oct-env.cc, oct-group.cc, oct-passwd.cc, oct-syscalls.cc, oct-time.cc,
oct-uname.cc, cmd-edit.cc, cmd-hist.cc, data-conv.cc, f2c-main.c,
glob-match.cc, kpse.cc, lo-array-errwarn.cc, lo-array-gripes.cc, lo-cutils.c,
lo-ieee.cc, lo-regexp.cc, lo-utils.cc, oct-base64.cc, oct-glob.cc,
oct-inttypes.cc, oct-locbuf.cc, oct-mutex.cc, oct-rl-edit.c, oct-rl-hist.c,
oct-shlib.cc, oct-sort.cc, pathsearch.cc, singleton-cleanup.cc, sparse-sort.cc,
sparse-util.cc, str-vec.cc, unwind-prot.cc, url-transfer.cc,
display-available.c, main-cli.cc, main-gui.cc, main.in.cc, mkoctfile.in.cc,
octave-config.in.cc:
Use '#include "config.h"' rather than <config.h>.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 18 Feb 2016 13:34:50 -0800 |
parents | fcac5dbbf9ed |
children | ae4d7dfea337 |
line wrap: on
line source
/* Copyright (C) 1995-2015 John W. Eaton Copyright (C) 2010 VZLU Prague This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "Array-util.h" #include "error.h" #include "oct-locbuf.h" #include "str-vec.h" #include "oct-map.h" #include "utils.h" octave_fields::octave_fields (const string_vector& fields) : rep (new fields_rep) { octave_idx_type n = fields.numel (); for (octave_idx_type i = 0; i < n; i++) (*rep)[fields(i)] = i; } octave_fields::octave_fields (const char * const *fields) : rep (new fields_rep) { octave_idx_type n = 0; while (*fields) (*rep)[std::string (*fields++)] = n++; } bool octave_fields::isfield (const std::string& field) const { return rep->find (field) != rep->end (); } octave_idx_type octave_fields::getfield (const std::string& field) const { fields_rep::iterator p = rep->find (field); return (p != rep->end ()) ? p->second : -1; } octave_idx_type octave_fields::getfield (const std::string& field) { fields_rep::iterator p = rep->find (field); if (p != rep->end ()) return p->second; else { make_unique (); octave_idx_type n = rep->size (); return (*rep)[field] = n; } } octave_idx_type octave_fields::rmfield (const std::string& field) { fields_rep::iterator p = rep->find (field); if (p == rep->end ()) return -1; else { octave_idx_type n = p->second; make_unique (); rep->erase (field); for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++) { if (q->second >= n) q->second--; } return n; } } void octave_fields::orderfields (Array<octave_idx_type>& perm) { octave_idx_type n = rep->size (); perm.clear (n, 1); make_unique (); octave_idx_type i = 0; for (fields_rep::iterator q = rep->begin (); q != rep->end (); q++) { octave_idx_type j = q->second; q->second = i; perm(i++) = j; } } bool octave_fields::equal_up_to_order (const octave_fields& other, octave_idx_type* perm) const { bool retval = true; iterator p = begin (); iterator q = other.begin (); for (; p != end () && q != other.end (); p++, q++) { if (p->first == q->first) perm[p->second] = q->second; else { retval = false; break; } } retval = (p == end () && q == other.end ()); return retval; } bool octave_fields::equal_up_to_order (const octave_fields& other, Array<octave_idx_type>& perm) const { octave_idx_type n = nfields (); if (perm.numel () != n) perm.clear (1, n); return equal_up_to_order (other, perm.fortran_vec ()); } string_vector octave_fields::fieldnames (void) const { octave_idx_type n = nfields (); string_vector retval(n); for (iterator p = begin (); p != end (); p++) retval.xelem (p->second) = p->first; return retval; } octave_value octave_scalar_map::getfield (const std::string& k) const { octave_idx_type idx = xkeys.getfield (k); return (idx >= 0) ? xvals[idx] : octave_value (); } void octave_scalar_map::setfield (const std::string& k, const octave_value& val) { octave_idx_type idx = xkeys.getfield (k); if (idx < static_cast<octave_idx_type> (xvals.size ())) xvals[idx] = val; else xvals.push_back (val); } void octave_scalar_map::rmfield (const std::string& k) { octave_idx_type idx = xkeys.rmfield (k); if (idx >= 0) xvals.erase (xvals.begin () + idx); } octave_scalar_map octave_scalar_map::orderfields (void) const { Array<octave_idx_type> perm; return orderfields (perm); } octave_scalar_map octave_scalar_map::orderfields (Array<octave_idx_type>& perm) const { octave_scalar_map retval (xkeys); retval.xkeys.orderfields (perm); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[perm.xelem (i)]; return retval; } octave_scalar_map octave_scalar_map::orderfields (const octave_scalar_map& other, Array<octave_idx_type>& perm) const { if (xkeys.is_same (other.xkeys)) return *this; else { octave_scalar_map retval (other.xkeys); if (! other.xkeys.equal_up_to_order (xkeys, perm)) error ("orderfields: structs must have same fields up to order"); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[perm.xelem (i)]; return retval; } } octave_value octave_scalar_map::contents (const std::string& k) const { return getfield (k); } octave_value& octave_scalar_map::contents (const std::string& k) { octave_idx_type idx = xkeys.getfield (k); if (idx >= static_cast<octave_idx_type> (xvals.size ())) xvals.resize (idx+1); return xvals[idx]; } octave_map::octave_map (const octave_scalar_map& m) : xkeys (m.xkeys), xvals (), dimensions (1, 1) { octave_idx_type nf = m.nfields (); xvals.reserve (nf); for (octave_idx_type i = 0; i < nf; i++) { xvals.push_back (Cell (dimensions)); xvals[i].xelem (0) = m.xvals[i]; } } Cell octave_map::getfield (const std::string& k) const { octave_idx_type idx = xkeys.getfield (k); return (idx >= 0) ? xvals[idx] : Cell (); } void octave_map::setfield (const std::string& k, const Cell& val) { if (nfields () == 0) dimensions = val.dims (); if (val.dims () != dimensions) error ("octave_map::setfield: internal error"); octave_idx_type idx = xkeys.getfield (k); if (idx < static_cast<octave_idx_type> (xvals.size ())) xvals[idx] = val; else xvals.push_back (val); } void octave_map::rmfield (const std::string& k) { octave_idx_type idx = xkeys.rmfield (k); if (idx >= 0) xvals.erase (xvals.begin () + idx); } octave_map octave_map::orderfields (void) const { Array<octave_idx_type> perm; return orderfields (perm); } octave_map octave_map::orderfields (Array<octave_idx_type>& perm) const { octave_map retval (xkeys); retval.xkeys.orderfields (perm); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[perm.xelem (i)]; return retval; } octave_map octave_map::orderfields (const octave_map& other, Array<octave_idx_type>& perm) const { if (xkeys.is_same (other.xkeys)) return *this; else { octave_map retval (other.xkeys); if (! other.xkeys.equal_up_to_order (xkeys, perm)) error ("orderfields: structs must have same fields up to order"); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[perm.xelem (i)]; return retval; } } Cell octave_map::contents (const std::string& k) const { return getfield (k); } Cell& octave_map::contents (const std::string& k) { octave_idx_type idx = xkeys.getfield (k); if (idx >= static_cast<octave_idx_type> (xvals.size ())) xvals.push_back (Cell (dimensions)); // auto-set correct dims. return xvals[idx]; } void octave_map::extract_scalar (octave_scalar_map& dest, octave_idx_type idx) const { octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) dest.xvals[i] = xvals[i](idx); } octave_scalar_map octave_map::checkelem (octave_idx_type n) const { octave_scalar_map retval (xkeys); // Optimize this so that there is just one check. extract_scalar (retval, compute_index (n, dimensions)); return retval; } octave_scalar_map octave_map::checkelem (octave_idx_type i, octave_idx_type j) const { octave_scalar_map retval (xkeys); // Optimize this so that there is just one check. extract_scalar (retval, compute_index (i, j, dimensions)); return retval; } octave_scalar_map octave_map::checkelem (const Array<octave_idx_type>& ra_idx) const { octave_scalar_map retval (xkeys); // Optimize this so that there is just one check. extract_scalar (retval, compute_index (ra_idx, dimensions)); return retval; } octave_scalar_map octave_map::fast_elem_extract (octave_idx_type n) const { octave_scalar_map retval (xkeys); extract_scalar (retval, n); return retval; } bool octave_map::fast_elem_insert (octave_idx_type n, const octave_scalar_map& rhs) { bool retval = false; octave_idx_type nf = nfields (); if (rhs.xkeys.is_same (xkeys)) { for (octave_idx_type i = 0; i < nf; i++) xvals[i](n) = rhs.xvals[i]; retval = true; } else { OCTAVE_LOCAL_BUFFER (octave_idx_type, perm, nf); if (xkeys.equal_up_to_order (rhs.xkeys, perm)) { for (octave_idx_type i = 0; i < nf; i++) xvals[i](n) = rhs.xvals[perm[i]]; retval = true; } } return retval; } octave_map octave_map::squeeze (void) const { octave_map retval (*this); octave_idx_type nf = nfields (); retval.dimensions = dimensions.squeeze (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[i].squeeze (); retval.optimize_dimensions (); return retval; } /* ## test preservation of xkeys by squeeze %!test %! x(1,1,1,1).d = 10; x(3,5,1,7).a = "b"; x(2,4,1,7).f = 27; %! assert (fieldnames (squeeze (x)), {"d"; "a"; "f"}); */ octave_map octave_map::permute (const Array<int>& vec, bool inv) const { octave_map retval (xkeys); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[i].permute (vec, inv); // FIXME: // There is no dim_vector::permute for technical reasons. // We pick the dim vector from results if possible, otherwise use a dummy // array to get it. Need (?) a better solution to this problem. if (nf > 0) retval.dimensions = retval.xvals[0].dims (); else { Array<char> dummy (dimensions); dummy = dummy.permute (vec, inv); retval.dimensions = dummy.dims (); } retval.optimize_dimensions (); return retval; } /* ## test preservation of key order by permute %!test %! x(1,1,1,1).d = 10; x(3,5,1,7).a = "b"; x(2,4,1,7).f = 27; %! assert (fieldnames (permute (x, [3, 4, 1, 2])), {"d"; "a"; "f"}); */ octave_map octave_map::transpose (void) const { assert (ndims () == 2); octave_map retval (xkeys); retval.dimensions = dim_vector (dimensions (1), dimensions (0)); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[i].transpose (); retval.optimize_dimensions (); return retval; } /* ## test preservation of key order by transpose %!test %! x(1,1).d = 10; x(3,5).a = "b"; x(2,4).f = 27; %! assert (fieldnames (transpose (x)), {"d"; "a"; "f"}); %! assert (fieldnames (x'), {"d"; "a"; "f"}); %! assert (fieldnames (x.'), {"d"; "a"; "f"}); */ octave_map octave_map::reshape (const dim_vector& dv) const { octave_map retval (xkeys); retval.dimensions = dv; octave_idx_type nf = nfields (); if (nf > 0) { retval.xvals.reserve (nf); for (octave_idx_type i = 0; i < nf; i++) retval.xvals[i] = xvals[i].reshape (dv); } else { // FIXME: Do it with a dummy array, to reuse error message. // Need (?) a better solution. Array<char> dummy (dimensions); dummy.reshape (dv); } retval.optimize_dimensions (); return retval; } /* ## test preservation of key order by reshape %!test %! x(1,1).d = 10; x(4,6).a = "b"; x(2,4).f = 27; %! assert (fieldnames (reshape (x, 3, 8)), {"d"; "a"; "f"}); */ void octave_map::resize (const dim_vector& dv, bool fill) { octave_idx_type nf = nfields (); if (nf > 0) { for (octave_idx_type i = 0; i < nf; i++) { if (fill) xvals[i].resize (dv, Matrix ()); else xvals[i].resize (dv); } } else { // FIXME: Do it with a dummy array, to reuse error message. // Need (?) a better solution. Array<char> dummy (dimensions); dummy.resize (dv); } dimensions = dv; optimize_dimensions (); } void octave_map::do_cat (int dim, octave_idx_type n, const octave_scalar_map *map_list, octave_map& retval) { octave_idx_type nf = retval.nfields (); retval.xvals.reserve (nf); dim_vector& rd = retval.dimensions; rd.resize (dim+1, 1); rd(0) = rd(1) = 1; rd(dim) = n; for (octave_idx_type j = 0; j < nf; j++) { retval.xvals.push_back (Cell (rd)); assert (retval.xvals[j].numel () == n); for (octave_idx_type i = 0; i < n; i++) retval.xvals[j].xelem (i) = map_list[i].xvals[j]; } } void octave_map::do_cat (int dim, octave_idx_type n, const octave_map *map_list, octave_map& retval) { octave_idx_type nf = retval.nfields (); retval.xvals.reserve (nf); OCTAVE_LOCAL_BUFFER (Array<octave_value>, field_list, n); for (octave_idx_type j = 0; j < nf; j++) { for (octave_idx_type i = 0; i < n; i++) field_list[i] = map_list[i].xvals[j]; retval.xvals.push_back (Array<octave_value>::cat (dim, n, field_list)); if (j == 0) retval.dimensions = retval.xvals[j].dims (); } } // This is just a wrapper. void permute_to_correct_order1 (const octave_scalar_map& ref, const octave_scalar_map& src, octave_scalar_map& dest, Array<octave_idx_type>& perm) { dest = src.orderfields (ref, perm); } // In non-scalar case, we also promote empty structs without fields. void permute_to_correct_order1 (const octave_map& ref, const octave_map& src, octave_map& dest, Array<octave_idx_type>& perm) { if (src.nfields () == 0 && src.is_empty ()) dest = octave_map (src.dims (), ref.keys ()); else dest = src.orderfields (ref, perm); } template <typename map> static void permute_to_correct_order (octave_idx_type n, octave_idx_type nf, octave_idx_type idx, const map *map_list, map *new_map_list) { new_map_list[idx] = map_list[idx]; Array<octave_idx_type> perm (dim_vector (1, nf)); try { for (octave_idx_type i = 0; i < n; i++) { if (i == idx) continue; permute_to_correct_order1 (map_list[idx], map_list[i], new_map_list[i], perm); } } catch (octave_execution_exception& e) { error (e, "cat: field names mismatch in concatenating structs"); } } octave_map octave_map::cat (int dim, octave_idx_type n, const octave_scalar_map *map_list) { octave_map retval; // Allow dim = -1, -2 for compatibility, though it makes no difference here. if (dim == -1 || dim == -2) dim = -dim - 1; else if (dim < 0) error ("cat: invalid dimension"); if (n == 1) retval = map_list[0]; else if (n > 1) { octave_idx_type idx, nf = 0; for (idx = 0; idx < n; idx++) { nf = map_list[idx].nfields (); if (nf > 0) { retval.xkeys = map_list[idx].xkeys; break; } } if (nf > 0) { // Try the fast case. bool all_same = true; for (octave_idx_type i = 0; i < n; i++) { all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys); if (! all_same) break; } if (all_same) do_cat (dim, n, map_list, retval); else { // permute all structures to common order. OCTAVE_LOCAL_BUFFER (octave_scalar_map, new_map_list, n); permute_to_correct_order (n, nf, idx, map_list, new_map_list); do_cat (dim, n, new_map_list, retval); } } else { dim_vector& rd = retval.dimensions; rd.resize (dim+1, 1); rd(0) = rd(1) = 1; rd(dim) = n; } retval.optimize_dimensions (); } return retval; } octave_map octave_map::cat (int dim, octave_idx_type n, const octave_map *map_list) { octave_map retval; // Allow dim = -1, -2 for compatibility, though it makes no difference here. if (dim == -1 || dim == -2) dim = -dim - 1; else if (dim < 0) error ("cat: invalid dimension"); if (n == 1) retval = map_list[0]; else if (n > 1) { octave_idx_type idx, nf = 0; for (idx = 0; idx < n; idx++) { nf = map_list[idx].nfields (); if (nf > 0) { retval.xkeys = map_list[idx].xkeys; break; } } // Try the fast case. bool all_same = true; if (nf > 0) { for (octave_idx_type i = 0; i < n; i++) { all_same = map_list[idx].xkeys.is_same (map_list[i].xkeys); if (! all_same) break; } } if (all_same && nf > 0) do_cat (dim, n, map_list, retval); else { if (nf > 0) { // permute all structures to correct order. OCTAVE_LOCAL_BUFFER (octave_map, new_map_list, n); permute_to_correct_order (n, nf, idx, map_list, new_map_list); do_cat (dim, n, new_map_list, retval); } else { dim_vector dv = map_list[0].dimensions; for (octave_idx_type i = 1; i < n; i++) { if (! dv.concat (map_list[i].dimensions, dim)) error ("dimension mismatch in struct concatenation"); } retval.dimensions = dv; } } retval.optimize_dimensions (); } return retval; } /* ## test preservation of key order by concatenation %!test %! x(1, 1).d = 10; x(4, 6).a = "b"; x(2, 4).f = 27; %! y(1, 6).f = 11; y(1, 6).a = "c"; y(1, 6).d = 33; %! assert (fieldnames ([x; y]), {"d"; "a"; "f"}); %!test %! s = struct (); %! sr = [s,s]; %! sc = [s;s]; %! sm = [s,s;s,s]; %! assert (numfields (sr), 0); %! assert (numfields (sc), 0); %! assert (numfields (sm), 0); %! assert (size (sr), [1, 2]); %! assert (size (sc), [2, 1]); %! assert (size (sm), [2, 2]); */ octave_map octave_map::index (const idx_vector& i, bool resize_ok) const { octave_map retval (xkeys); octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) retval.xvals[k] = xvals[k].index (i, resize_ok); if (nf > 0) retval.dimensions = retval.xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy = dummy.index (i, resize_ok); retval.dimensions = dummy.dims (); } retval.optimize_dimensions (); return retval; } octave_map octave_map::index (const idx_vector& i, const idx_vector& j, bool resize_ok) const { octave_map retval (xkeys); octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) retval.xvals[k] = xvals[k].index (i, j, resize_ok); if (nf > 0) retval.dimensions = retval.xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy = dummy.index (i, j, resize_ok); retval.dimensions = dummy.dims (); } retval.optimize_dimensions (); return retval; } octave_map octave_map::index (const Array<idx_vector>& ia, bool resize_ok) const { octave_map retval (xkeys); octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) retval.xvals[k] = xvals[k].index (ia, resize_ok); if (nf > 0) retval.dimensions = retval.xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy = dummy.index (ia, resize_ok); retval.dimensions = dummy.dims (); } retval.optimize_dimensions (); return retval; } octave_map octave_map::index (const octave_value_list& idx, bool resize_ok) const { octave_idx_type n_idx = idx.length (); octave_map retval; // If we catch an indexing error in index_vector, we flag an error in // index k. Ensure it is the right value befor each idx_vector call. // Same variable as used in the for loop in the default case. octave_idx_type k = 0; try { switch (n_idx) { case 1: { idx_vector i = idx(0).index_vector (); retval = index (i, resize_ok); } break; case 2: { idx_vector i = idx(0).index_vector (); k = 1; idx_vector j = idx(1).index_vector (); retval = index (i, j, resize_ok); } break; default: { Array<idx_vector> ia (dim_vector (n_idx, 1)); for (k = 0; k < n_idx; k++) ia(k) = idx(k).index_vector (); retval = index (ia, resize_ok); } break; } } catch (index_exception& e) { // Rethrow to allow more info to be reported later. e.set_pos_if_unset (n_idx, k+1); throw; } return retval; } // Perhaps one day these will be optimized. Right now, they just call index. octave_map octave_map::column (octave_idx_type k) const { return index (idx_vector::colon, k); } octave_map octave_map::page (octave_idx_type k) const { static Array<idx_vector> ia (dim_vector (3, 1), idx_vector::colon); ia(2) = k; return index (ia); } void octave_map::assign (const idx_vector& i, const octave_map& rhs) { if (rhs.xkeys.is_same (xkeys)) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].assign (i, rhs.xvals[k], Matrix ()); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions); dummy.assign (i, rhs_dummy);; dimensions = dummy.dims (); } optimize_dimensions (); } else if (nfields () == 0) { octave_map tmp (dimensions, rhs.xkeys); tmp.assign (i, rhs); *this = tmp; } else { Array<octave_idx_type> perm; octave_map rhs1; try { rhs1 = rhs.orderfields (*this, perm); } catch (octave_execution_exception& e) { error (e, "incompatible fields in struct assignment"); } assert (rhs1.xkeys.is_same (xkeys)); assign (i, rhs1); } } void octave_map::assign (const idx_vector& i, const idx_vector& j, const octave_map& rhs) { if (rhs.xkeys.is_same (xkeys)) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].assign (i, j, rhs.xvals[k], Matrix ()); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions); dummy.assign (i, j, rhs_dummy);; dimensions = dummy.dims (); } optimize_dimensions (); } else if (nfields () == 0) { octave_map tmp (dimensions, rhs.xkeys); tmp.assign (i, j, rhs); *this = tmp; } else { Array<octave_idx_type> perm; octave_map rhs1; try { rhs1 = rhs.orderfields (*this, perm); } catch (octave_execution_exception& e) { error (e, "incompatible fields in struct assignment"); } assert (rhs1.xkeys.is_same (xkeys)); assign (i, j, rhs1); } } void octave_map::assign (const Array<idx_vector>& ia, const octave_map& rhs) { if (rhs.xkeys.is_same (xkeys)) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].assign (ia, rhs.xvals[k], Matrix ()); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions), rhs_dummy (rhs.dimensions); dummy.assign (ia, rhs_dummy);; dimensions = dummy.dims (); } optimize_dimensions (); } else if (nfields () == 0) { octave_map tmp (dimensions, rhs.xkeys); tmp.assign (ia, rhs); *this = tmp; } else { Array<octave_idx_type> perm; octave_map rhs1; try { rhs1 = rhs.orderfields (*this, perm); } catch (octave_execution_exception& e) { error (e, "incompatible fields in struct assignment"); } assert (rhs1.xkeys.is_same (xkeys)); assign (ia, rhs1); } } void octave_map::assign (const octave_value_list& idx, const octave_map& rhs) { octave_idx_type n_idx = idx.length (); // If we catch an indexing error in index_vector, we flag an error in // index k. Ensure it is the right value befor each idx_vector call. // Same variable as used in the for loop in the default case. octave_idx_type k = 0; try { switch (n_idx) { case 1: { idx_vector i = idx(0).index_vector (); assign (i, rhs); } break; case 2: { idx_vector i = idx(0).index_vector (); k = 1; idx_vector j = idx(1).index_vector (); assign (i, j, rhs); } break; default: { Array<idx_vector> ia (dim_vector (n_idx, 1)); for (k = 0; k < n_idx; k++) ia(k) = idx(k).index_vector (); assign (ia, rhs); } break; } } catch (index_exception& e) { // Rethrow to allow more info to be reported later. e.set_pos_if_unset (n_idx, k+1); throw; } } void octave_map::assign (const octave_value_list& idx, const std::string& k, const Cell& rhs) { Cell tmp; iterator p = seek (k); Cell& ref = p != end () ? contents (p) : tmp; if (&ref == &tmp) ref = Cell (dimensions); ref.assign (idx, rhs); if (ref.dims () != dimensions) { dimensions = ref.dims (); octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) { if (&xvals[i] != &ref) xvals[i].resize (dimensions, Matrix ()); } optimize_dimensions (); } if (&ref == &tmp) setfield (k, tmp); } /* %!test %! rhs.b = 1; %! a(3) = rhs; %! assert ({a.b}, {[], [], 1}) */ void octave_map::delete_elements (const idx_vector& i) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].delete_elements (i); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy.delete_elements (i); dimensions = dummy.dims (); } optimize_dimensions (); } void octave_map::delete_elements (int dim, const idx_vector& i) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].delete_elements (dim, i); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy.delete_elements (dim, i); dimensions = dummy.dims (); } optimize_dimensions (); } void octave_map::delete_elements (const Array<idx_vector>& ia) { octave_idx_type nf = nfields (); for (octave_idx_type k = 0; k < nf; k++) xvals[k].delete_elements (ia); if (nf > 0) dimensions = xvals[0].dims (); else { // Use dummy array. FIXME: Need(?) a better solution. Array<char> dummy (dimensions); dummy.delete_elements (ia); dimensions = dummy.dims (); } optimize_dimensions (); } void octave_map::delete_elements (const octave_value_list& idx) { octave_idx_type n_idx = idx.length (); Array<idx_vector> ia (dim_vector (n_idx, 1)); for (octave_idx_type i = 0; i < n_idx; i++) { try { ia(i) = idx(i).index_vector (); } catch (index_exception& e) { // Rethrow to allow more info to be reported later. e.set_pos_if_unset (n_idx, i+1); throw; } } delete_elements (ia); } /* ## test preservation of key order by indexing %!test %! x(1, 1).d = 10; x(4, 6).a = "b"; x(2, 4).f = 27; %! assert (fieldnames (x([1, 2], [2:5])), {"d"; "a"; "f"}); */ octave_map octave_map::concat (const octave_map& rb, const Array<octave_idx_type>& ra_idx) { if (nfields () == rb.nfields ()) { for (const_iterator pa = begin (); pa != end (); pa++) { const_iterator pb = rb.seek (key(pa)); if (pb == rb.end ()) error ("field name mismatch in structure concatenation"); contents(pa).insert (rb.contents (pb), ra_idx); } } else { dim_vector dv = dims (); if (dv.all_zero ()) *this = rb; else if (! rb.dims ().all_zero ()) error ("invalid structure concatenation"); } return *this; } void octave_map::optimize_dimensions (void) { octave_idx_type nf = nfields (); for (octave_idx_type i = 0; i < nf; i++) { if (! xvals[i].optimize_dimensions (dimensions)) error ("internal error: dimension mismatch across fields in struct"); } }