Main Content

Results for

Luis
Luis
Last activity on 29 Dec 2025 at 12:15

I’m currently developing a multi-platform viewer using Flutter to eliminate the hassle of manual channel setup. Instead of adding IDs one by one, the app uses your User API Key to automatically discover and list all your ThingSpeak channels instantly.
Key Highlights (Work in Progress):
  • Automatic Sync: All your channels appear in seconds.
  • Multi-platform: Built for Web, Android, Windows, and Linux.
  • Privacy-Focused: Secure local storage for your API keys.
If you use tables extensively to perform data analysis, you may at some point have wanted to add new functionalities suited to your specific applications. One straightforward idea is to create a new class that subclasses the built-in table class. You would then benefit from all inherited existing methods.
Unfortunately, as has been observed, that is not possible because the table class is Sealed.
One workaround is to create a new class that wraps a table as a Property, and re-implement all the methods that you need and are already defined for table. The is not too difficult, except for the subsref method, for which I’ll provide the code below.
Class definition
Defining a wrapper of the table class is quite straightforward. In this example, I call the class “Report” because that is what I intend to use the class for, to compute and store reports. The constructor just takes a table as input:
classdef Rapport
methods
function obj = Report(t)
if isa(t, 'Report')
obj = t;
else
obj.t_ = t;
end
end
end
properties (GetAccess = private, SetAccess = private)
t_ table = table();
end
end
I designed the constructor so that it converts a table into a Report object, but also so that if we accidentally provide it with a Report object instead of a table, it will not generate an error.
Reproducing the behaviour of the table class
Implementing the existing methods of the table class for the Report class if pretty easy in most cases.
I made use of a method called “table” in order to be able to get the data back in table format instead of a Report, instead of accessing the property t_ of the object. That method can also be useful whenever you wish to use the methods or functions already existing for tables (such as writetable, rowfun, groupsummary…).
classdef Rapport
...
methods
function t = table(obj)
t = obj.t_;
end
function r = eq(obj1,obj2)
r = isequaln(table(obj1), table(obj2));
end
function ind = size(obj, varargin)
ind = size(table(obj), varargin{:});
end
function ind = height(obj, varargin)
ind = height(table(obj), varargin{:});
end
function ind = width(obj, varargin)
ind = width(table(obj), varargin{:});
end
function ind = end(A,k,n)
% ind = end(A.t_,k,n);
sz = size(table(A));
if k < n
ind = sz(k);
else
ind = prod(sz(k:end));
end
end
end
end
In the case of horzcat (same principle for vertcat), it is just a matter of converting back and forth between the table and Report classes:
classdef Rapport
...
methods
function r = horzcat(obj1,varargin)
listT = cell(1, nargin);
listT{1} = table(obj1);
for k = 1:numel(varargin)
kth = varargin{k};
if isa(kth, 'Report')
listT{k+1} = table(kth);
elseif isa(kth, 'table')
listT{k+1} = kth;
else
error('Input must be a table or a Report');
end
end
res = horzcat(listT{:});
r = Report(res);
end
end
end
Adding a new method
The plus operator already exists for the table class and works when the table contains all numeric values. It sums columns as long as the tables have the same length.
Something I think would be nice would be to be able to write t1 + t2, and that would perform an outerjoin operation between the tables and any sizes having similar indexing columns.
That would be so concise, and that's what we’re going to implement for the Report class as an example. That is called “plus operator overloading”. Of course, you could imagine that the “+” operator is used to compute something else, for example adding columns together with regard to the keys index. That depends on your needs.
Here’s a unittest example:
classdef ReportTest < matlab.unittest.TestCase
methods (Test)
function testPlusOperatorOverload(testCase)
t1 = array2table( ...
{ 'Smith', 'Male' ...
; 'JACKSON', 'Male' ...
; 'Williams', 'Female' ...
} , 'VariableNames', {'LastName' 'Gender'} ...
);
t2 = array2table( ...
{ 'Smith', 13 ...
; 'Williams', 6 ...
; 'JACKSON', 4 ...
}, 'VariableNames', {'LastName' 'Age'} ...
);
r1 = Report(t1);
r2 = Report(t2);
tRes = r1 + r2;
tExpected = Report( array2table( ...
{ 'JACKSON' , 'Male', 4 ...
; 'Smith' , 'Male', 13 ...
; 'Williams', 'Female', 6 ...
} , 'VariableNames', {'LastName' 'Gender' 'Age'} ...
) );
testCase.verifyEqual(tRes, tExpected);
end
end
end
And here’s how I’d implement the plus operator in the Report class definition, so that it also works if I add a table and a Report:
classdef Rapport
...
methods
function r = plus(obj1,obj2)
table1 = table(obj1);
table2 = table(obj2);
result = outerjoin(table1, table2 ...
, 'Type', 'full', 'MergeKeys', true);
r = reportingits.dom.Rapport(result);
end
end
end
The case of the subsref method
If we wish to access the elements of an instance the same way we would with regular tables, whether with parentheses, curly braces or directly with the name of the column, we need to implement the subsref and subsasgn methods. The second one, subsasgn is pretty easy, but subsref is a bit tricky, because we need to detect whether we’re directing towards existing methods or not.
Here’s the code:
classdef Rapport
...
methods
function A = subsasgn(A,S,B)
A.t_ = subsasgn(A.t_,S,B);
end
function B = subsref(A,S)
isTableMethod = @(m) ismember(m, methods('table'));
isReportMethod = @(m) ismember(m, methods('Report'));
switch true
case strcmp(S(1).type, '.') && isReportMethod(S(1).subs)
methodName = S(1).subs;
B = A.(methodName)(S(2).subs{:});
if numel(S) > 2
B = subsref(B, S(3:end));
end
case strcmp(S(1).type, '.') && isTableMethod (S(1).subs)
methodName = S(1).subs;
if ~isReportMethod(methodName)
error('The method "%s" needs to be implemented!', methodName)
end
otherwise
B = subsref(table(A),S(1));
if istable(B)
B = Report(B);
end
if numel(S) > 1
B = subsref(B, S(2:end));
end
end
end
end
end
Conclusion
I believe that the table class is Sealed because is case new methods are introduced in MATLAB in the future, the subclass might not be compatible if we created any or generate unexpected complexity.
The table class is a really powerful feature.
I hope this example has shown you how it is possible to extend the use of tables by adding new functionalities and maybe given you some ideas to simplify some usages. I’ve only happened to find it useful in very restricted cases, but was still happy to be able to do so.
In case you need to add other methods of the table class, you can see the list simply by calling methods(’table’).
Feel free to share your thoughts or any questions you might have! Maybe you’ll decide that doing so is a bad idea in the end and opt for another solution.
Give your LLM an easier time looking for information on mathworks.com: point it to the recently released llms.txt files. The top-level one is www.mathworks.com/llms.txt, release changes use www.mathworks.com/help/relnotes. How does it work for you??
(Requested for newer MATLAB releases (e.g. R2026B), MATLAB Parallel Processing toolbox.)
Lower precision array types have been gaining more popularity over the years for deep learning. The current lowest precision built-in array type offered by MATLAB are 8-bit precision arrays, e.g. int8 and uint8. A good thing is that these 8-bit array types do have gpuArray support, meaning that one is able to design GPU MEX codes that take in these 8-bit arrays and reinterpret them bit-wise as other 8-bit array types, e.g. FP8, which is especially common array type used in modern day deep learning applications. I myself have used this to develop forward pass operations with 8-bit precision that are around twice as fast as 16-bit operations and with output arrays that still agree well with 16-bit outputs (measured with high cosine similarity). So the 8-bit support that MATLAB offers is already quite sufficient.
Recently, 4-bit precision array types have been shown also capable of being very useful in deep learning. These array types can be processed with Tensor Cores of more modern GPUs, such as NVIDIA's Blackwell architecture. However, MATLAB does not yet have a built-in 4-bit precision array type.
Just like MATLAB has int8 and uint8, both also with gpuArray support, it would also be nice to have MATLAB have int4 and uint4, also with gpuArray support.
Walter Roberson
Walter Roberson
Last activity on 11 Dec 2025 at 0:54

I can't believe someone put time into this ;-)
Hi everyone
I've been using ThingSpeak for several years now without an issue until last Thursday.
I have four ThingSpeak channels which are used by three Arduino devices (in two locations/on two distinct networks) all running the same code.
All three devices stopped being able to write data to my ThingSpeak channels around 17:00 CET on 4 Dec and are still unable to.
Nothing changed on this side, let alone something that would explain the problem.
I would note that data can still be written to all the channels via a browser so there is no fundamental problem with the channels (such as being full).
Since the above date and time, any HTTP/1.1 'update' (write) requests via the REST API (using both simple one-write GET requests or bulk JSON POST requests) are timing out after 5 seconds and no data is being written. The 5 second timeout is my Arduino code's default, but even increasing it to 30 seconds makes no difference. Before all this, responses from ThingSpeak were sub-second.
I have recompiled the Arduino code using the latest libraries and that didn't help.
I have tested the same code again another random api (api.ipify.org) and that works just fine.
Curl works just fine too, also usng HTTP/1.1
So the issue appears to be something particular to the combination of my Arduino code *and* the ThingSpeak environment, where something changed on the ThingSpeak end at the above date and time.
If anyone in the community has any suggestions as to what might be going on, I would greatly appreciate the help.
Peter
The formula comes from @yuruyurau. (https://x.com/yuruyurau)
digital life 1
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:2e4;
x = mod(i, 100);
y = floor(i./100);
k = x./4 - 12.5;
e = y./9 + 5;
o = vecnorm([k; e])./9;
while true
t = t + pi/90;
q = x + 99 + tan(1./k) + o.*k.*(cos(e.*9)./4 + cos(y./2)).*sin(o.*4 - t);
c = o.*e./30 - t./8;
SHdl.XData = (q.*0.7.*sin(c)) + 9.*cos(y./19 + t) + 200;
SHdl.YData = 200 + (q./2.*cos(c));
drawnow
end
digital life 2
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:1e4;
x = i;
y = i./235;
e = y./8 - 13;
while true
t = t + pi/240;
k = (4 + sin(y.*2 - t).*3).*cos(x./29);
d = vecnorm([k; e]);
q = 3.*sin(k.*2) + 0.3./k + sin(y./25).*k.*(9 + 4.*sin(e.*9 - d.*3 + t.*2));
SHdl.XData = q + 30.*cos(d - t) + 200;
SHdl.YData = 620 - q.*sin(d - t) - d.*39;
drawnow
end
digital life 3
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 1, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:1e4;
x = mod(i, 200);
y = i./43;
k = 5.*cos(x./14).*cos(y./30);
e = y./8 - 13;
d = (k.^2 + e.^2)./59 + 4;
a = atan2(k, e);
while true
t = t + pi/20;
q = 60 - 3.*sin(a.*e) + k.*(3 + 4./d.*sin(d.^2 - t.*2));
c = d./2 + e./99 - t./18;
SHdl.XData = q.*sin(c) + 200;
SHdl.YData = (q + d.*9).*cos(c) + 200;
drawnow; pause(1e-2)
end
digital life 4
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 1, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:4e4;
x = mod(i, 200);
y = i./200;
k = x./8 - 12.5;
e = y./8 - 12.5;
o = (k.^2 + e.^2)./169;
d = .5 + 5.*cos(o);
while true
t = t + pi/120;
SHdl.XData = x + d.*k.*sin(d.*2 + o + t) + e.*cos(e + t) + 100;
SHdl.YData = y./4 - o.*135 + d.*6.*cos(d.*3 + o.*9 + t) + 275;
SHdl.CData = ((d.*sin(k).*sin(t.*4 + e)).^2).'.*[1,1,1];
drawnow;
end
digital life 5
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 1, 'filled','o','w',...
'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 0:1e4;
x = mod(i, 200);
y = i./55;
k = 9.*cos(x./8);
e = y./8 - 12.5;
while true
t = t + pi/120;
d = (k.^2 + e.^2)./99 + sin(t)./6 + .5;
q = 99 - e.*sin(atan2(k, e).*7)./d + k.*(3 + cos(d.^2 - t).*2);
c = d./2 + e./69 - t./16;
SHdl.XData = q.*sin(c) + 200;
SHdl.YData = (q + 19.*d).*cos(c) + 200;
drawnow;
end
digital life 6
clc; clear
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 1:1e4;
y = i./790;
k = y; idx = y < 5;
k(idx) = 6 + sin(bitxor(floor(y(idx)), 1)).*6;
k(~idx) = 4 + cos(y(~idx));
while true
t = t + pi/90;
d = sqrt((k.*cos(i + t./4)).^2 + (y/3-13).^2);
q = y.*k.*cos(i + t./4)./5.*(2 + sin(d.*2 + y - t.*4));
c = d./3 - t./2 + mod(i, 2);
SHdl.XData = q + 90.*cos(c) + 200;
SHdl.YData = 400 - (q.*sin(c) + d.*29 - 170);
drawnow; pause(1e-2)
end
digital life 7
clc; clear
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.4);
t = 0;
i = 1:1e4;
y = i./345;
x = y; idx = y < 11;
x(idx) = 6 + sin(bitxor(floor(x(idx)), 8))*6;
x(~idx) = x(~idx)./5 + cos(x(~idx)./2);
e = y./7 - 13;
while true
t = t + pi/120;
k = x.*cos(i - t./4);
d = sqrt(k.^2 + e.^2) + sin(e./4 + t)./2;
q = y.*k./d.*(3 + sin(d.*2 + y./2 - t.*4));
c = d./2 + 1 - t./2;
SHdl.XData = q + 60.*cos(c) + 200;
SHdl.YData = 400 - (q.*sin(c) + d.*29 - 170);
drawnow; pause(5e-3)
end
digital life 8
clc; clear
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl{6} = [];
for j = 1:6
SHdl{j} = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.3);
end
t = 0;
i = 1:2e4;
k = mod(i, 25) - 12;
e = i./800; m = 200;
theta = pi/3;
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
while true
t = t + pi/240;
d = 7.*cos(sqrt(k.^2 + e.^2)./3 + t./2);
XY = [k.*4 + d.*k.*sin(d + e./9 + t);
e.*2 - d.*9 - d.*9.*cos(d + t)];
for j = 1:6
XY = R*XY;
SHdl{j}.XData = XY(1,:) + m;
SHdl{j}.YData = XY(2,:) + m;
end
drawnow;
end
digital life 9
clc; clear
figure('Position',[300,50,900,900], 'Color','k');
axes(gcf, 'NextPlot','add', 'Position',[0,0,1,1], 'Color','k');
axis([0, 400, 0, 400])
SHdl{14} = [];
for j = 1:14
SHdl{j} = scatter([], [], 2, 'filled','o','w', 'MarkerEdgeColor','none', 'MarkerFaceAlpha',.1);
end
t = 0;
i = 1:2e4;
k = mod(i, 50) - 25;
e = i./1100; m = 200;
theta = pi/7;
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
while true
t = t + pi/240;
d = 5.*cos(sqrt(k.^2 + e.^2) - t + mod(i, 2));
XY = [k + k.*d./6.*sin(d + e./3 + t);
90 + e.*d - e./d.*2.*cos(d + t)];
for j = 1:14
XY = R*XY;
SHdl{j}.XData = XY(1,:) + m;
SHdl{j}.YData = XY(2,:) + m;
end
drawnow;
end
Hello,
I have Arduino DIY Geiger Counter, that uploads data to my channel here in ThingSpeak (3171809), using ESP8266 WiFi board. It sends CPM values (counts per minute), Dose, VCC and Max CPM for 24h. They are assignet to Field from 1 to 4 respectively. How can I duplicate Field 1, so I could create different time chart for the same measured unit? Or should I duplicate Field 1 chart, and how? I tried to find the answer here in the blog, but I couldn't.
I have to say that I'm not an engineer or coder, just can simply load some Arduino sketches and few more things, so I'll be very thankfull if someone could explain like for non-IT users.
Regards,
Emo
It’s exciting to dive into a new dataset full of unfamiliar variables but it can also be overwhelming if you’re not sure where to start. Recently, I discovered some new interactive features in MATLAB live scripts that make it much easier to get an overview of your data. With just a few clicks, you can display sparklines and summary statistics using table variables, sort and filter variables, and even have MATLAB generate the corresponding code for reproducibility.
The Graphics and App Building blog published an article that walks through these features showing how to explore, clean, and analyze data—all without writing any code.
If you’re interested in streamlining your exploratory data analysis or want to see what’s new in live scripts, you might find it helpful:
If you’ve tried these features or have your own tips for quick data exploration in MATLAB, I’d love to hear your thoughts!
Ludvig Nordin
Ludvig Nordin
Last activity on 13 Nov 2025

Pure Matlab
82%
Simulink
18%
11 votes
Jorge Bernal-AlvizJorge Bernal-Alviz shared the following code that requires R2025a or later:
Test()
Warning: Hardware-accelerated graphics is unavailable. Displaying fewer markers to preserve interactivity.
function Test()
duration = 10;
numFrames = 800;
frameInterval = duration / numFrames;
w = 400;
t = 0;
i_vals = 1:10000;
x_vals = i_vals;
y_vals = i_vals / 235;
r = linspace(0, 1, 300)';
g = linspace(0, 0.1, 300)';
b = linspace(1, 0, 300)';
r = r * 0.8 + 0.1;
g = g * 0.6 + 0.1;
b = b * 0.9 + 0.1;
customColormap = [r, g, b];
figure('Position', [100, 100, w, w], 'Color', [0, 0, 0]);
axis equal;
axis off;
xlim([0, w]);
ylim([0, w]);
hold on;
colormap default;
colormap(customColormap);
plothandle = scatter([], [], 1, 'filled', 'MarkerFaceAlpha', 0.12);
for i = 1:numFrames
t = t + pi/240;
k = (4 + 3 * sin(y_vals * 2 - t)) .* cos(x_vals / 29);
e = y_vals / 8 - 13;
d = sqrt(k.^2 + e.^2);
c = d - t;
q = 3 * sin(2 * k) + 0.3 ./ (k + 1e-10) + ...
sin(y_vals / 25) .* k .* (9 + 4 * sin(9 * e - 3 * d + 2 * t));
points_x = q + 30 * cos(c) + 200;
points_y = q .* sin(c) + 39 * d - 220;
points_y = w - points_y;
CData = (1 + sin(0.1 * (d - t))) / 3;
CData = max(0, min(1, CData));
set(plothandle, 'XData', points_x, 'YData', points_y, 'CData', CData);
brightness = 0.5 + 0.3 * sin(t * 0.2);
set(plothandle, 'MarkerFaceAlpha', brightness);
drawnow;
pause(frameInterval);
end
end
From my experience, MATLAB's Deep Learning Toolbox is quite user-friendly, but it still falls short of libraries like PyTorch in many respects. Most users tend to choose PyTorch because of its flexibility, efficiency, and rich support for many mathematical operators. In recent years, the number of dlarray-compatible mathematical functions added to the toolbox has been very limited, which makes it difficult to experiment with many custom networks. For example, svd is currently not supported for dlarray inputs.
This link (List of Functions with dlarray Support - MATLAB & Simulink) lists all functions that support dlarray as of R2026a — only around 200 functions (including toolbox-specific ones). I would like to see support for many more fundamental mathematical functions so that users have greater freedom when building and researching custom models. For context, the core MATLAB mathematics module contains roughly 600 functions, and many application domains build on that foundation.
I hope MathWorks will prioritize and accelerate expanding dlarray support for basic math functions. Doing so would significantly increase the Deep Learning Toolbox's utility and appeal for researchers and practitioners.
Thank you.
We’re excited to invite you to Cody Contest 2025! 🎉
Pick a team, solve Cody problems, and share your best tips and tricks. Whether you’re a beginner or a seasoned MATLAB user, you’ll have fun learning, connecting with others, and competing for amazing prizes, including MathWorks swags, Amazon gift cards, and virtual badges.
How to Participate
  • Join a team that matches your coding personality
  • Solve Cody problems, complete the contest problem group, or share Tips & Tricks articles
  • Bonus Round: Two top players from each team will be invited to a fun code-along event
Contest Timeline
  • Main Round: Nov 10 – Dec 7, 2025
  • Bonus Round: Dec 8 – Dec 19, 2025
Prizes (updated 11/19)
  • (New prize) Solving just one problem in the contest problem group gives you a chance to win MathWorks T-shirts or socks each week.
  • Finishing the entire problem group will greatly increase your chances—while helping your team win.
  • Share high-quality Tips & Tricks articles to earn you a coveted MathWorks Yeti Bottle.
  • Become a top finisher in your team to win Amazon gift cards and an invitation to the bonus round.
Join now! Get ready to learn and have fun!
как я получил api Token
David
David
Last activity on 8 Dec 2025 at 15:44

I just learned you can access MATLAB Online from the following shortcut in your web browser: https://matlab.new
Hey everyone,
I’m currently working with MATLAB R2025b and using the MQTT blocks from the Industrial Communication Toolbox inside Simulink. I’ve run into an issue that’s driving me a bit crazy, and I’m not sure if it’s a bug or if I’m missing something obvious.
Here’s what’s happening:
  • I open the MQTT Configure block.
  • I fill out all the required fields — Broker address, Port, Client ID, Username, and Password.
  • When I click Test Connection, it says “Connection established successfully.” So far so good.
  • Then I click Apply, close the dialog, set the topic name, and try to run the simulation.
  • At this point, I get the following error:Caused by: Invalid value for 'ClientID', 'Username' or 'Password'.
  • When I reopen the MQTT config block, I notice that the Password field is empty again — even though I definitely entered it before and the connection test worked earlier.
It seems like Simulink is somehow not saving the password after hitting Apply, which leads to the authentication error during simulation.
Has anyone else faced this? Is this a bug in R2025b, or do I need to configure something differently to make the password persist?
Would really appreciate any insights, workarounds, or confirmations from anyone who has used MQTT in Simulink recently.
Thanks in advance!
I'm working on training neural networks without backpropagation / automatic differentiation, using locally derived analytic forms of update rules. Given that this allows a direct formula to be derived for the update rule, it removes alot of the overhead that is otherwise required from automatic differentiation.
However, matlab's functionalities for neural networks are currently solely based around backpropagation and automatic differentiation, such as the dlgradient function and requiring everything to be dlarrays during training.
I have two main requests, specifically for functions that perform a single operation within a single layer of a neural network, such as "dlconv", "fullyconnect", "maxpool", "avgpool", "relu", etc:
  • these functions should also allow normal gpuArray data instead of requiring everything to be dlarrays.
  • these functions are currently designed to only perform the forward pass. I request that these also be designed to perform the backward pass if user requests. There can be another input user flag that can be "forward" (default) or "backward", and then the function should have all the necessary inputs to perform that operation (e.g. for "avgpool" forward pass it only needs the avgpool input data and the avgpool parameters, but for the "avgpool" backward pass it needs the deriviative w.r.t. the avgpool output data, the avgpool parameters, and the original data dimensions). I know that there is a maxunpool function that achieves this for maxpool, but it has significant issues when trying to use it this way instead of by backpropagation in a dlgradient type layer, see (https://www.mathworks.com/matlabcentral/answers/2179587-making-a-custom-way-to-train-cnns-and-i-am-noticing-that-avgpool-is-significantly-faster-than-maxpo?s_tid=srchtitle).
I don't know how many people would benefit from this feature, and someone could always spend their time creating these functionalities themselves by matlab scripts, cuDNN mex, etc., but regardless it would be nice for matlab to have this allowable for more customizable neural net training.
Inspired by @xingxingcui's post about old MATLAB versions and @유장's post about an old Easter egg, I thought it might be fun to share some MATLAB-Old-Timer Stories™.
Back in the early 90s, MATLAB had been ported to MacOS, but there were some interesting wrinkles. One that kept me earning my money as a computer lab tutor was that MATLAB required file names to follow Windows standards - no spaces or other special characters. But on a Mac, nothing stopped you from naming your script "hello world - 123.m". The problem came when you tried to run it. MATLAB was essentially doing an eval on the script name, assuming the file name would follow Windows (and MATLAB) naming rules.
So now imagine a lab full of students taking a university course. As is common in many universities, the course was given a numeric code. For whatever historical reason, my school at that time was also using numeric codes for the departments. Despite being told the rules for naming scripts, many students would default to something like "26.165 - 1.1" for problem one on HW1 for the intro applied math course 26.165.
No matter what they did in their script, when they ran it, MATLAB would just say "ans = 25.0650".
Nothing brings you more MATLAB-god credibility as a student tutor than walking over to someone's computer, taking one look at their output, saying "rename your file", and walking away like a boss.
It was 2010 when I was a sophomore in university. I chose to learn MATLAB because of a mathematical modeling competition, and the university provided MATLAB 7.0, a very classic release. To get started, I borrowed many MATLAB books from the library and began by learning simple numerical calculations, plotting, and solving equations. Gradually I was drawn in by MATLAB’s powerful capabilities and became interested; I often used it as a big calculator for fun. That version didn’t have MATLAB Live Script; instead it used MATLAB Notebook (M-Book), which allowed MATLAB functions to be used directly within Microsoft Word, and it also had the Symbolic Math Toolbox’s MuPAD interactive environment. These were later gradually replaced by Live Scripts introduced in R2016a. There are many similar examples...
Out of curiosity, I still have screenshots on my computer showing MATLAB 7.0 running compatibly. I’d love to hear your thoughts?
Edit 15 Oct 2025: Removed incorrect code. Replaced symmatrix2sym and symfunmatrix2symfun with sym and symfun respectively (latter supported as of 2024b).
The Symbolic Math Toolbox does not have its own dot and and cross functions. That's o.k. (maybe) for garden variety vectors of sym objects where those operations get shipped off to the base Matlab functions
x = sym('x',[3,1]); y = sym('y',[3,1]);
which dot(x,y)
/MATLAB/toolbox/matlab/specfun/dot.m
dot(x,y)
ans = 
which cross(x,y)
/MATLAB/toolbox/matlab/specfun/cross.m
cross(x,y)
ans = 
But now we have symmatrix et. al., and things don't work as nicely
clearvars
x = symmatrix('x',[3,1]); y = symmatrix('y',[3,1]);
z = symmatrix('z',[1,1]);
sympref('AbbreviateOutput',false);
dot() expands the result, which isn't really desirable for exposition.
eqn = z == dot(x,y)
eqn = 
Also, dot() returns the the result in terms of the conjugate of x, which can't be simplifed away at the symmatrix level
assumeAlso(sym(x),'real')
class(eqn)
ans = 'symmatrix'
try
eqn = z == simplify(dot(x,y))
catch ME
ME.message
end
ans = 'Undefined function 'simplify' for input arguments of type 'symmatrix'.'
To get rid of the conjugate, we have to resort to sym
eqn = simplify(sym(eqn))
eqn = 
but again we are in expanded form, which defeats the purpose of symmatrix (et. al.)
But at least we can do this to get a nice equation
eqn = z == x.'*y
eqn = 
dot errors with symfunmatrix inputs
clearvars
syms t real
x = symfunmatrix('x(t)',t,[3,1]); y = symfunmatrix('y(t)',t,[3,1]);
try
dot(x,y)
catch ME
ME.message
end
ans = 'Invalid argument at position 2. Symbolic function is evaluated at the input arguments and does not accept colon indexing. Instead, use FORMULA on the function and perform colon indexing on the returned output.'
Cross works (accidentally IMO) with symmatrix, but expands the result, which isn't really desirable for exposition
clearvars
x = symmatrix('x',[3,1]); y = symmatrix('y',[3,1]);
z = symmatrix('z',[3,1]);
eqn = z == cross(x,y)
eqn = 
And it doesn't work at all if an input is a symfunmatrix
syms t
w = symfunmatrix('w(t)',t,[3,1]);
try
eqn = z == cross(x,w);
catch ME
ME.message
end
ans = 'A and B must be of length 3 in the dimension in which the cross product is taken.'
In the latter case we can expand with
eqn = z == cross(sym(x),symfun(w)) % x has to be converted
eqn(t) = 
But we can't do the same with dot (as shown above, dot doesn't like symfun inputs)
try
eqn = z == dot(sym(x),symfun(w))
catch ME
ME.message
end
ans = 'Invalid argument at position 2. Symbolic function is evaluated at the input arguments and does not accept colon indexing. Instead, use FORMULA on the function and perform colon indexing on the returned output.'
Looks like the only choice for dot with symfunmatrix is to write it by hand at the matrix level
x.'*w
ans(t) = 
or at the sym/symfun level
sym(x).'*symfun(w) % assuming x is real
ans(t) = 
Ideally, I'd like to see dot and cross implemented for symmatrix and symfunmatrix types where neither function would evaluate, i.e., expand, until both arguments are subs-ed with sym or symfun objects of appropriate dimension.
Also, it would be nice if symmatrix could be assumed to be real. Is there a reason why being able to do so wouldn't make sense?
try
assume(x,'real')
catch ME
ME.message
end
ans = 'Undefined function 'assume' for input arguments of type 'symmatrix'.'