diff --git a/docs/sphinx/source/matlab-source/matpower/mp_table_subclass.m b/docs/sphinx/source/matlab-source/matpower/mp_table_subclass.m
new file mode 120000
index 00000000..1057472d
--- /dev/null
+++ b/docs/sphinx/source/matlab-source/matpower/mp_table_subclass.m
@@ -0,0 +1 @@
+../../../../../lib/mp_table_subclass.m
\ No newline at end of file
diff --git a/docs/sphinx/source/ref-manual/classes/index.rst b/docs/sphinx/source/ref-manual/classes/index.rst
index 237644cb..71f3054a 100644
--- a/docs/sphinx/source/ref-manual/classes/index.rst
+++ b/docs/sphinx/source/ref-manual/classes/index.rst
@@ -237,6 +237,7 @@ Miscellaneous Classes
:name: sec_misc_classes
mp_table
+ mp_table_subclass
mp/element_container
mp/mapped_array
mp/NODE_TYPE
diff --git a/docs/sphinx/source/ref-manual/classes/mp_table_subclass.rst b/docs/sphinx/source/ref-manual/classes/mp_table_subclass.rst
new file mode 100644
index 00000000..2c5c9529
--- /dev/null
+++ b/docs/sphinx/source/ref-manual/classes/mp_table_subclass.rst
@@ -0,0 +1,10 @@
+.. automodule:: matpower
+
+:raw-html:`
`
+
+mp_table_subclass
+-----------------
+
+.. autoclass:: mp_table_subclass
+ :show-inheritance:
+ :members:
diff --git a/lib/mp_table.m b/lib/mp_table.m
index 6ec2b58f..1c0b9b84 100644
--- a/lib/mp_table.m
+++ b/lib/mp_table.m
@@ -53,15 +53,15 @@
% ::
%
% T = mp_table(var1, var2, ...);
- % T = mp_table(..., 'VariableNames', {name1, name2, ...}});
- % T = mp_table(..., 'RowNames', {name1, name2, ...}});
- % T = mp_table(..., 'DimensionNames', {name1, name2, ...}});
+ % T = mp_table(..., 'VariableNames', {name1, name2, ...});
+ % T = mp_table(..., 'RowNames', {name1, name2, ...});
+ % T = mp_table(..., 'DimensionNames', {name1, name2, ...});
args = varargin;
if nargin
%% extract named arguments
[var_names, row_names, dim_names, args] = ...
- extract_named_args(obj, args);
+ mp_table.extract_named_args(args);
%% set default variable names
nv = length(args); %% number of variables
@@ -623,10 +623,19 @@ function display(obj)
end
end %% methods (public)
- methods (Access=protected)
+ methods (Static)
function [var_names, row_names, dim_names, args] = ...
- extract_named_args(obj, args)
- % used to extract named arguments pass to constructor
+ extract_named_args(args)
+ % Extracts special named constructor arguments.
+ % ::
+ %
+ % [var_names, row_names, dim_names, args] = extract_named_args(var1, var2, ...);
+ % [...] = extract_named_args(..., 'VariableNames', {name1, name2, ...});
+ % [...] = extract_named_args(..., 'RowNames', {name1, name2, ...});
+ % [...] = extract_named_args(..., 'DimensionNames', {name1, name2, ...});
+ %
+ % Used to extract named arguments, ``'VariableNames'``,
+ % ``'RowNames'``, and ``'DimensionNames'``, to pass to constructor.
var_names = {};
row_names = {};
dim_names = {};
diff --git a/lib/mp_table_subclass.m b/lib/mp_table_subclass.m
new file mode 100644
index 00000000..5d5de306
--- /dev/null
+++ b/lib/mp_table_subclass.m
@@ -0,0 +1,187 @@
+classdef mp_table_subclass
+% mp_table_subclass - Class that acts like a table but isn't one.
+%
+% Addresses two issues with inheriting from **table** classes (:class:`table`)
+% or mp_table).
+%
+% 1. In MATLAB, :class:`table` is a sealed class, so you cannot inherit
+% from it. You can, however, use a subclass of mp_table, but that can
+% result in the next issue under Octave.
+% 2. While nesting of tables works just fine in general, when using mp_table
+% in Octave (at least up through 8.4.0), you cannot nest a subclass of
+% mp_table inside another mp_table object because of this bug:
+% https://savannah.gnu.org/bugs/index.php?65037.
+%
+% To work around these issues, your "table subclass" can inherit from **this**
+% class. An object of this class **isn't** a :class:`table` or mp_table object,
+% but rather it **contains** one and attempts to act like one. That is, it
+% delegates method calls (currently only those available in mp_table, listed
+% below) to the contained table object.
+%
+% The class of the contained table object is either :class:`table` or mp_table
+% and is determined by mp_table_class.
+%
+% .. admonition:: Limitation
+%
+% In MATLAB, when nesting an mp_table_subclass object within another
+% mp_table_subclass object, one cannot use multi-level indexing directly.
+% E.g. If ``T2`` is a variable in ``T1`` and ``x`` is a variable in ``T2``,
+% attempting ``x = T1.T2.x`` will result in an error. The indexing must
+% be done in multiple steps ``T2 = T1.T2; x = T2.x``. Note: This only
+% applies to MATLAB, where the contained table is a :class:`table`. It works
+% just fine in Octave, where the contained table is an :class:`mp_table`.
+%
+% .. important::
+%
+% Since the dot syntax ``T.`` is used to access table variables,
+% you must use a functional syntax ``(T,...)``, as opposed to
+% the object-oriented ``T.(...)``, to call methods of this class
+% or subclasses, as with mp_table.
+%
+% mp.mp_table_subclass Properties:
+% * tab - *(table or mp_table)* contained table object this class emulates
+%
+% mp.cost_table Methods:
+% * mp_table_subclass - construct object
+% * get_table - return the table stored in :attr:`tab`
+% * set_table - assign a table to :attr:`tab`
+% * istable - true for mp_table objects
+% * size - dimensions of table
+% * isempty - true if table has no columns or no rows
+% * end - used to index last row or variable/column
+% * subsref - indexing a table to retrieve data
+% * subsasgn - indexing a table to assign data
+% * horzcat - concatenate tables horizontally
+% * vertcat - concatenate tables vertically
+% * display - display table contents
+%
+% See also mp_table, mp_table_class.
+
+% MATPOWER
+% Copyright (c) 2023, Power Systems Engineering Research Center (PSERC)
+% by Ray Zimmerman, PSERC Cornell
+%
+% This file is part of MATPOWER.
+% Covered by the 3-clause BSD License (see LICENSE file for details).
+% See https://matpower.org for more info.
+
+ properties
+ tab
+ end %% properties
+
+ %% delegate all mp_table methods to obj.tab
+ methods
+ function obj = mp_table_subclass(varargin)
+
+ args = varargin;
+ if nargin
+ %% extract named arguments
+ [var_names, row_names, dim_names, args] = ...
+ mp_table.extract_named_args(args);
+
+ %% set default variable names
+ nv = length(args); %% number of variables
+ if length(var_names) < nv
+ for k = nv:-1:length(var_names)+1
+ var_names{k} = inputname(k);
+ if isempty(var_names{k})
+ var_names{k} = sprintf('Var%d', k);
+ end
+ end
+ end
+ args(end+1:end+2) = {'VariableNames', var_names};
+ if ~isempty(row_names)
+ args(end+1:end+2) = {'RowNames', row_names};
+ end
+ if ~isempty(dim_names)
+ args(end+1:end+2) = {'DimensionNames', dim_names};
+ end
+ end
+
+ table_class = mp_table_class();
+ obj.tab = table_class(args{:});
+ end
+
+ function tab = get_table(obj)
+ %
+ % ::
+ %
+ % T = get_table(obj)
+ tab = obj.tab;
+ end
+
+ function obj = set_table(obj, T)
+ %
+ % ::
+ %
+ % set_table(obj, T)
+ obj.tab = T;
+ end
+
+ function TorF = istable(obj)
+ TorF = istable(obj.tab);
+ end
+
+ function varargout = size(obj, varargin)
+ [varargout{1:nargout}] = size(obj.tab, varargin{:});
+ end
+
+ function TorF = isempty(obj)
+ TorF = isempty(obj.tab);
+ end
+
+ function N = end(obj, k, n)
+ N = size(obj.tab, k);
+ end
+
+ function n = numArgumentsFromSubscript(obj, varargin)
+ n = numArgumentsFromSubscript(obj.tab, varargin{:});
+ end
+
+ function n = numel(obj, varargin)
+ n = numel(obj.tab, varargin{:});
+ end
+
+ function b = subsref(obj, varargin)
+ b = subsref(obj.tab, varargin{:});
+ if varargin{1}(1).type(1) == '(' && ...
+ (isa(b, 'table') || isa(b, 'mp_table'))
+ o = feval(class(obj));
+ b = set_table(o, b);
+ end
+ end
+
+ function obj = subsasgn(obj, varargin)
+ for k = 2:length(varargin)
+ if isa(varargin{k}, 'mp_table_subclass')
+ varargin{k} = get_table(varargin{k});
+ end
+ end
+ obj.tab = subsasgn(obj.tab, varargin{:});
+ end
+
+ function obj = horzcat(obj, varargin)
+ args = varargin;
+ for k = 1:length(args)
+ if isa(args{k}, 'mp_table_subclass')
+ args{k} = args{k}.tab;
+ end
+ end
+ obj.tab = horzcat(obj.tab, args{:});
+ end
+
+ function obj = vertcat(obj, varargin)
+ args = varargin;
+ for k = 1:length(args)
+ if isa(args{k}, 'mp_table_subclass')
+ args{k} = args{k}.tab;
+ end
+ end
+ obj.tab = vertcat(obj.tab, args{:});
+ end
+
+ function display(obj)
+ obj.tab
+ end
+ end %% methods
+end %% classdef
diff --git a/lib/t/t_mp_table.m b/lib/t/t_mp_table.m
index 758aa7b8..b146dcb8 100644
--- a/lib/t/t_mp_table.m
+++ b/lib/t/t_mp_table.m
@@ -20,15 +20,15 @@
verbose = 1;
end
-nt = 169;
skip_tests_for_tablicious = 1;
-table_classes = {@mp_table};
-class_names = {'mp_table'};
+table_classes = {@mp_table, @mp_table_subclass};
+class_names = {'mp_table', 'mp_table_subclass'};
if have_feature('table')
table_classes = {@table, table_classes{:}};
class_names = {'table', class_names{:}};
end
nc = length(table_classes);
+nt = 161 + 8*nc;
t_begin(nc*nt, quiet);
@@ -53,8 +53,12 @@
T = table_class();
skip_oct_tab = isa(T, 'table') && have_feature('octave') && ...
skip_tests_for_tablicious;
- skip_ml_tab = isa(T, 'table') && have_feature('matlab') && ...
- have_feature('matlab', 'vnum') < 9.010;
+ skip_oct_tab2 = isa(T, 'mp_table_subclass') && have_feature('table') && ...
+ have_feature('octave') && skip_tests_for_tablicious;
+ skip_ml_tab = (isa(T, 'table') || isa(T, 'mp_table_subclass')) && ...
+ have_feature('matlab') && have_feature('matlab', 'vnum') < 9.010;
+ skip_ml_tab2 = (isa(T, 'table') || isa(T, 'mp_table_subclass')) && ...
+ have_feature('matlab') && have_feature('matlab', 'vnum') < 9.012;
t_ok(isa(T, class_names{k}), [t 'class']);
t_ok(isempty(T), [t 'isempty']);
@@ -95,7 +99,7 @@
t_ok(isempty(T1), [t 'true']);
t = sprintf('%s : constructor - ind vars, w/names : ', cls);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
T = table_class(var1, var2, var3, var4, var5, var6, ...
'VariableNames', var_names, 'RowNames', row_names);
else
@@ -112,7 +116,7 @@
t_is([nr, nz], [6 6], 12, [t '[nr, nz] = size(T)']);
t_ok(isequal(T.Properties.VariableNames, var_names), [t 'VariableNames'] );
t_ok(isequal(T.Properties.RowNames, row_names), [t 'RowNames'] );
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'] );
else
t_ok(isequal(T.Properties.DimensionNames, dim_names), [t 'DimensionNames'] );
@@ -183,7 +187,7 @@
%% {} indexing
t = sprintf('%s : subsref {} : ', cls);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(6, [t 'T{:, j} syntax not yet supported'])
else
t_ok(isequal(T{:, 1}, v1), [t 'T{:, 1} == v1']);
@@ -195,7 +199,7 @@
end
t_ok(isequal(T{2, 1}, v1(2)), [t 'T{i, j} == v(i)']);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(1, [t 'T{i, j} syntax not yet supported for matrices'])
else
t_ok(isequal(T{4, 6}, v6(4, :)), [t 'T{i, j} == v(i)']);
@@ -203,12 +207,12 @@
%% remove skip_oct_tab when
%% https://github.com/apjanke/octave-tablicious/pull/89 is merged
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(1, [t 'T{end, end} syntax not yet supported'])
else
t_ok(isequal(T{end, end}, v6(end,:)), [t 'T{end, end} == v(end,:)']);
end
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(8, [t 'T{ii, j} syntax not yet supported'])
else
t_ok(isequal(T{1:3, 2}, v2(1:3)), [t 'T{i1:iN, j} == v(i1:iN)']);
@@ -232,7 +236,7 @@
t_is(T.dbl, var4, 12, [t 'T{:, 4} = var4']);
T{:, 5} = var5;
t_is(T.boo, var5, 12, [t 'T{:, 5} = var5']);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(1, 'T{:, j} = M syntax not yet supported for matrices');
else
T{:, 6} = var6;
@@ -241,7 +245,7 @@
T{2, 1} = v1(2);
t_ok(isequal(T{2, 1}, v1(2)), [t 'T{i, j} = v(i)']);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(1, 'T{i, j} = M syntax not yet supported for matrices');
else
T{4, 6} = v6(4, :);
@@ -249,7 +253,7 @@
end
T{1:3, 2} = v2(1:3);
t_ok(isequal(T.flt(1:3), v2(1:3)), [t 'T{i1:iN, j} = v(i1:iN)']);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(2, 'T{i1:iN, j} = M syntax not yet supported for matrices');
else
T{1:3, 6} = v6(1:3, :);
@@ -259,7 +263,7 @@
end
T{[6;3], 5} = v5([6;3]);
t_ok(isequal(T.boo([6;3]), v5([6;3])), [t 'T{ii, j} = v(ii)']);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(2, 'T{ii, j} = M syntax not yet supported for matrices');
else
T{[6;3], 6} = v6([6;3], :);
@@ -267,7 +271,7 @@
T{[6;3], 6} = v6([6;3], [2;1]);
t_ok(isequal(T.mat([6;3], :), v6([6;3], [2;1])), [t 'T{ii, j} = v(ii, jj)']);
end
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(2, [t 'T{ii, jj} syntax not yet supported'])
else
T{6:-1:3, [2;4;6;5]} = [v2(6:-1:3) v4(6:-1:3) v6(6:-1:3, :) v5(6:-1:3)];
@@ -280,7 +284,7 @@
T{:, 3} = v3;
T{:, 4} = v4;
T{:, 5} = v5;
- if ~skip_oct_tab
+ if ~skip_oct_tab && ~skip_oct_tab2
T{:, 6} = v6;
end
@@ -293,7 +297,7 @@
t_ok(isequal(T2.Properties.VariableNames, var_names(jj)), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v1(ii), v3(ii), v4(ii), v6(ii, :)}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names(ii)), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
@@ -307,7 +311,7 @@
t_ok(isequal(T2.Properties.VariableNames, var_names(jj)), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v2, v4, v6}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
@@ -321,7 +325,7 @@
t_ok(isequal(T2.Properties.VariableNames, var_names), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v1(ii), v2(ii), v3(ii), v4(ii), v5(ii), v6(ii, :)}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names(ii)), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
@@ -334,7 +338,7 @@
t_ok(isequal(T2.Properties.VariableNames, var_names(4)), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v4(5)}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names(5)), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
@@ -345,7 +349,7 @@
t_ok(isequal(T2.Properties.VariableNames, var_names(6)), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v6(3, :)}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names(3)), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
@@ -363,14 +367,14 @@
t_ok(isequal(T2.Properties.VariableNames, var_names(6)), [t 'VariableNames']);
t_ok(isequal(table_values(T2), {v6(end, :)}), [t 'VariableValues']);
t_ok(isequal(T2.Properties.RowNames, row_names(end)), [t 'RowNames']);
- if skip_oct_tab || skip_ml_tab
+ if skip_oct_tab || skip_ml_tab || skip_oct_tab2
t_skip(1, [t 'DimensionNames not yet supported'])
else
t_ok(isequal(T2.Properties.DimensionNames, dim_names), [t 'DimensionNames']);
end
end
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(20, sprintf('%s : subsasgn () not yet supported.', cls));
else
t = sprintf('%s : subsasgn () : T(ii,jj) : ', cls);
@@ -459,7 +463,7 @@
t_ok(isequal(T4, T3), [t '[T1;T2]']);
T5 = table_class([7;8],[7.7;8.8],{'seven';'eight'},1./[7;8],[-1;2]<=0, [70 75; 80 85], ...
'VariableNames', var_names);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(1, [t 'RowNames auto-generation not yet supported']);
else
T6 = [T5; T2; T1];
@@ -479,7 +483,7 @@
%% deleting variables
t = sprintf('%s : delete variables : ', cls);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2 || skip_ml_tab2
t_skip(1, [t 'not yet supported']);
else
T7 = T;
@@ -501,7 +505,7 @@
T3 = T6(:, 6:7);
ii = [5;3;1];
jj = [6:7];
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(6, [t 'T{ii, :} syntax not yet supported'])
else
ex = horzcat(v3, var3);
@@ -514,7 +518,7 @@
end
t = sprintf('%s : more subsasgn {} : ', cls);
- if skip_oct_tab
+ if skip_oct_tab || skip_oct_tab2
t_skip(6, [t 'T{ii, :} syntax not yet supported'])
else
T2{ii, :} = [var1(ii) var2(ii) var4(ii) var6(ii, :) var5(ii)];
@@ -541,21 +545,36 @@
t_is(T2.igr(2), 55, 12, t);
%% nested tables
- t = sprintf('%s : nested tables : ', cls);
- T1 = table_class([1;2;3],[4;5;6]);
- T2 = table_class({'one';'two';'three'},{'four';'five';'six'});
- T3 = table_class([10;20;30],{'uno';'dos';'tres'}, T1, T2);
- t_ok(isequal(T3.T1, T1), [t 'T.T1 == T1']);
- t_ok(isequal(T3.T2, T2), [t 'T.T2 == T2']);
- t_ok(isequal(T3.T1([1;3], :), T1([1;3], :)), [t 'T.T1(ii, :) == T1(ii, :)']);
- t_ok(isequal(T3.T2([1;3], :), T2([1;3], :)), [t 'T.T2(ii, :) == T2(ii, :)']);
- t_ok(isequal(T3.T1.Var1, T1.Var1), [t 'T.T1.Var1 == T1.Var1']);
- t_ok(isequal(T3.T2.Var2([1;3], :), T2.Var2([1;3], :)), [t 'T.T2.Var2(ii) == T.T2.Var2(ii)']);
- %% check for Octave trouble in subsref
- T4 = T3(:, :);
- T5 = T3([1;2;3], :);
- t_ok(isequal(T3, T4), [t 'T == T(:, :))']);
- t_ok(isequal(T3, T5), [t 'T == T(ii, :))']);
+ for k2 = 1:nc
+ nested_table_class = table_classes{k2};
+ nstcls = upper(class_names{k2});
+
+ t = sprintf('%s . %s : nested tables : ', cls, nstcls);
+ T1 = nested_table_class([1;2;3],[4;5;6]);
+ T2 = nested_table_class({'one';'two';'three'},{'four';'five';'six'});
+ T3 = table_class([10;20;30],{'uno';'dos';'tres'}, T1, T2, ...
+ 'VariableNames', {'v1', 'v2', 'T1', 'T2'});
+ t_ok(isequal(T3.T1, T1), [t 'T.T1 == T1']);
+ t_ok(isequal(T3.T2, T2), [t 'T.T2 == T2']);
+ if have_feature('matlab') && isa(T1, 'mp_table_subclass') && ...
+ isa(T3, 'mp_table_subclass')
+ t_skip(4, 'multiple indexing of nested mp_table_subclasses');
+ else
+ t_ok(isequal(T3.T1([1;3], :), T1([1;3], :)), [t 'T.T1(ii, :) == T1(ii, :)']);
+ t_ok(isequal(T3.T2([1;3], :), T2([1;3], :)), [t 'T.T2(ii, :) == T2(ii, :)']);
+ t_ok(isequal(T3.T1.Var1, T1.Var1), [t 'T.T1.Var1 == T1.Var1']);
+ t_ok(isequal(T3.T2.Var2([1;3], :), T2.Var2([1;3], :)), [t 'T.T2.Var2(ii) == T.T2.Var2(ii)']);
+ end
+ %% check for Octave trouble in subsref
+ if (skip_oct_tab && isa(T3, 'table')) || skip_oct_tab2
+ t_skip(2, 'mp_table_subclass does not handle this yet');
+ else
+ T4 = T3(:, :);
+ T5 = T3([1;2;3], :);
+ t_ok(isequal(T3, T4), [t 'T == T(:, :))']);
+ t_ok(isequal(T3, T5), [t 'T == T(ii, :))']);
+ end
+ end
end
if nargout
@@ -565,6 +584,9 @@
t_end;
function Tv = table_values(T)
+if isa(T, 'mp_table_subclass')
+ T = get_table(T);
+end
if isa(T, 'table') && have_feature('matlab')
Tv = cellfun(@(c)T{:, c}, num2cell(1:size(T, 2)), 'UniformOutput', false);
else