Contenido principal

Resultados de

Luis
Luis
Última actividad el 29 de Dic. de 2025 a las 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.
(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
Última actividad el 11 de Dic. de 2025 a las 0:54

I can't believe someone put time into this ;-)
Peter
Peter
Última actividad el 31 de Dic. de 2025 a las 11:12

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
Martinov
Martinov
Última actividad el 26 de Nov. de 2025

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
Última actividad el 13 de Nov. de 2025

Pure Matlab
82%
Simulink
18%
11 votos
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.
Diyorbek
Diyorbek
Última actividad el 28 de Oct. de 2025

как я получил api Token
David
David
Última actividad el 8 de Dic. de 2025 a las 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.
xingxingcui
xingxingcui
Última actividad el 13 de Oct. de 2025

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'.'
Nicolas Douillet
Nicolas Douillet
Última actividad el 10 de Oct. de 2025

What if you had no isprime utility to rely on in MATLAB? How would you identify a number as prime? An easy answer might be something tricky, like that in simpleIsPrime0.
simpleIsPrime0 = @(N) ismember(N,primes(N));
But I’ll also disallow the use of primes here, as it does not really test to see if a number is prime. As well, it would seem horribly inefficient, generating a possibly huge list of primes, merely to learn something about the last member of the list.
Looking for a more serious test for primality, I’ve already shown how to lighten the load by a bit using roughness, to sometimes identify numbers as composite and therefore not prime.
But to actually learn if some number is prime, we must do a little more. Yes, this is a common homework problem assigned to students, something we have seen many times on Answers. It can be approached in many ways too, so it is worth looking at the problem in some depth.
The definition of a prime number is a natural number greater than 1, which has only two factors, thus 1 and itself. That makes a simple test for primality of the number N easy. We just try dividing the number by every integer greater than 1, and not exceeding N-1. If any of those trial divides leaves a zero remainder, then N cannot be prime. And of course we can use mod or rem instead of an explicit divide, so we need not worry about floating point trash, as long as the numbers being tested are not too large.
simpleIsPrime1 = @(N) all(mod(N,2:N-1) ~= 0);
Of course, simpleIsPrime1 is not a good code, in the sense that it fails to check if N is an integer, or if N is less than or equal to 1. It is not vectorized, and it has no documentation at all. But it does the job well enough for one simple line of code. There is some virtue in simplicity after all, and it is certainly easy to read. But sometimes, I wish a function handle could include some help comments too! A feature request might be in the offing.
simpleIsPrime1(9931)
ans = logical
1
simpleIsPrime1(9932)
ans = logical
0
simpleIsPrime1 works quite nicely, and seems pretty fast. What could be wrong? At some point, the student is given a more difficult problem, to identify if a significantly larger integer is prime. simpleIsPrime1 will then cause a computer to grind to a distressing halt if given a sufficiently large number to test. Or it might even error out, when too large a vector of numbers was generated to test against. For example, I don't think you want to test a number of the order of 2^64 using simpleIsPrime1, as performing on the order of 2^64 divides will be highly time consuming.
uint64(2)^63-25
ans = uint64 9223372036854775783
Is it prime? I’ve not tested it to learn if it is, and simpleIsPrime1 is not the tool to perform that test anyway.
A student might realize the largest possible integer factors of some number N are the numbers N/2 and N itself. But, if N/2 is a factor, then so is 2, and some thought would suggest it is sufficient to test only for factors that do not exceed sqrt(N). This is because if a is a divisor of N, then so is b=N/a. If one of them is larger than sqrt(N), then the other must be smaller. That could lead us to an improved scheme in simpleIsPrime2.
simpleIsPrime2 = @(N) all(mod(N,2:sqrt(N)));
For an integer of the size 2^64, now you only need to perform roughly 2^32 trial divides. Maybe we might consider the subtle improvement found in simpleIsPrime3, which avoids trial divides by the even integers greater than 2.
simpleIsPrime3 = @(N) (N == 2) || (mod(N,2) && all(mod(N,3:2:sqrt(N))));
simpleIsPrime3 needs only an approximate maximum of 2^31 trial divides even for numbers as large as uint64 can represent. While that is large, it is still generally doable on the computers we have today, even if it might be slow.
Sadly, my goals are higher than even the rather lofty limit given by UINT64 numbers. The problem of course is that a trial divide scheme, despite being 100% accurate in its assessment of primality, is a time hog. Even an O(sqrt(N)) scheme is far too slow for numbers with thousands or millions of digits. And even for a number as “small” as 1e100, a direct set of trial divides by all primes less than sqrt(1e100) would still be practically impossible, as there are roughly n/log(n) primes that do not exceed n. For an integer on the order of 1e50,
1e50/log(1e50)
ans = 8.6859e+47
It is practically impossible to perform that many divides on any computer we can make today. Can we do better? Is there some more efficient test for primality? For example, we could write a simple sieve of Eratosthenes to check each prime found not exceeding sqrt(N).
function [TF,SmallPrime] = simpleIsPrime4(N)
% simpleIsPrime3 - Sieve of Eratosthenes to identify if N is prime
% [TF,SmallPrime] = simpleIsPrime3(N)
%
% Returns true if N is prime, as well as the smallest prime factor
% of N when N is composite. If N is prime, then SmallPrime will be N.
Nroot = ceil(sqrt(N)); % ceil caters for floating point issues with the sqrt
TF = true;
SieveList = true(1,Nroot+1); SieveList(1) = false;
SmallPrime = 2;
while TF
% Find the "next" true element in SieveList
while (SmallPrime <= Nroot+1) && ~SieveList(SmallPrime)
SmallPrime = SmallPrime + 1;
end
% When we drop out of this loop, we have found the next
% small prime to check to see if it divides N, OR, we
% have gone past sqrt(N)
if SmallPrime > Nroot
% this is the case where we have now looked at all
% primes not exceeding sqrt(N), and have found none
% that divide N. This is where we will drop out to
% identify N as prime. TF is already true, so we need
% not set TF.
SmallPrime = N;
return
else
if mod(N,SmallPrime) == 0
% smallPrime does divide N, so we are done
TF = false;
return
end
% update SieveList
SieveList(SmallPrime:SmallPrime:Nroot) = false;
end
end
end
simpleIsPrime4 does indeed work reasonably well, though it is sometimes a little slower than is simpleIsPrime3, and everything is hugely faster than simpleIsPrime1.
timeit(@() simpleIsPrime1(111111111))
ans = 0.6447
timeit(@() simpleIsPrime2(111111111))
ans = 1.1932e-04
timeit(@() simpleIsPrime3(111111111))
ans = 6.4815e-05
timeit(@() simpleIsPrime4(111111111))
ans = 7.5757e-06
All of those times will slow to a crawl for much larger numbers of course. And while I might find a way to subtly improve upon these codes, any improvement will be marginal in the end if I try to use any such direct approach to primality. We must look in a different direction completely to find serious gains.
At this point, I want to distinguish between two distinct classes of tests for primality of some large number. One class of test is what I might call an absolute or infallible test, one that is perfectly reliable. These are tests where if X is identified as prime/composite then we can trust the result absolutely. The tests I showed in the form of simpleIsPrime1, simpleIsPrime2, simpleIsPrime3 and aimpleIsprime4, were all 100% accurate, thus they fall into the class of infallible tests.
The second general class of test for primality is what I will call an evidentiary test. Such a test provides evidence, possibly quite strong evidence, that the given number is prime, but in some cases, it might be mistaken. I've already offered a basic example of a weak evidentiary test for primality in the form of roughness. All primes are maximally rough. And therefore, if you can identify X as being rough to some extent, this provides evidence that X is also prime, and the depth of the roughness test influences the strength of the evidence for primality. While this is generally a fairly weak test, it is a test nevertheless, and a good exclusionary test, a good way to avoid more sophisticated but time consuming tests.
These evidentiary tests all have the property that if they do identify X as being composite, then they are always correct. In the context of roughness, if X is not sufficiently rough, then X is also not prime. On the other side of the coin, if you can show X is at least (sqrt(X)+1)-rough, then it is positively prime. (I say this to suggest that some evidentiary tests for primality can be turned into truth telling tests, but that may take more effort than you can afford.) The problem is of course that is literally impossible to verify that degree of roughness for numbers with many thousands of digits.
In my next post, I'll look at the Fermat test for primality, based on Fermat's little theorem.