Skip to content

Commit 029a9d8

Browse files
committed
mex: parent 10x faster
1 parent c43eddf commit 029a9d8

File tree

7 files changed

+78
-9
lines changed

7 files changed

+78
-9
lines changed

+stdlib/parent.m

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
%% PARENT parent directory of path
2+
% optional: mex
23
%
4+
%% Examples:
5+
% parent("a/b/c") == "a/b"
6+
% parent("a/b/c/") == "a/b"
7+
%
8+
% MEX is about 10x faster than plain Matlab for this function
39

410
function p = parent(pth)
511
arguments

buildfile.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ function publishTask(context)
9797
srcs = {
9898
["src/is_admin.cpp", "src/admin_fs.cpp"] ...
9999
"src/is_char_device.cpp", ...
100+
["src/parent.cpp", normal], ...
100101
"src/relative_to.cpp", ...
101102
"src/proximate_to.cpp", ...
102103
["src/is_wsl.cpp", linux], ...

example/bench_parent.m

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
f = mfilename("fullpath") + ".m";
2-
%f = tempname;
32

4-
fno = @() stdlib.parent(f, false);
5-
fjava = @() stdlib.parent(f, true);
3+
fno = @() stdlib.parent(f);
64

75
t_no = timeit(fno);
8-
t_java = timeit(fjava);
96

107
disp("No Java: " + t_no + " s")
11-
disp("Java: " + t_java + " s")
12-
13-
disp("Java is " + t_no/t_java + " times faster")

octave_build.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ function octave_build(overwrite)
1515
fullfile(d, "is_wsl.cpp"), ...
1616
fullfile(d, "is_rosetta.cpp"), ...
1717
fullfile(d, "is_admin.cpp"), ...
18+
fullfile(d, "parent.cpp"), ...
1819
fullfile(d, "proximate_to.cpp"), ...
1920
fullfile(d, "relative_to.cpp"), ...
2021
};

src/normalize.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
std::string fs_drop_slash(std::string_view in)
1111
{
1212
// drop all trailing "/" and duplicated internal "/"
13-
if (fs_is_url(in))
14-
return {};
1513

1614
std::filesystem::path p(in);
1715

src/octave/parent.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <octave/oct.h>
2+
3+
#include <string>
4+
#include <filesystem>
5+
6+
#include "pure.cpp"
7+
#include "normalize.cpp"
8+
9+
10+
DEFUN_DLD (parent, args, nargout,
11+
"get parent directory")
12+
{
13+
if (args.length() != 1){
14+
octave_stdout << "Oct: One input required\n";
15+
return octave_value("");
16+
}
17+
18+
std::string out = std::filesystem::path(fs_drop_slash(args(0).string_value())).parent_path().generic_string();
19+
20+
return octave_value(out);
21+
}

src/parent.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "mex.hpp"
2+
#include "mexAdapter.hpp"
3+
4+
#include <string>
5+
6+
#include <vector>
7+
#include <memory>
8+
9+
#include <filesystem>
10+
11+
#include "ffilesystem.h"
12+
13+
14+
class MexFunction : public matlab::mex::Function {
15+
public:
16+
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
17+
// boilerplate engine & ArrayFactory setup
18+
std::shared_ptr<matlab::engine::MATLABEngine> matlabEng = getEngine();
19+
20+
matlab::data::ArrayFactory factory;
21+
// wrangle inputs
22+
std::string in;
23+
24+
if (inputs.size() != 1) {
25+
matlabEng->feval(u"error", 0,
26+
std::vector<matlab::data::Array>({ factory.createScalar("Mex: One input required") }));
27+
}
28+
if ((inputs[0].getType() == matlab::data::ArrayType::MATLAB_STRING && inputs[0].getNumberOfElements() == 1)){
29+
matlab::data::TypedArray<matlab::data::MATLABString> stringArr = inputs[0];
30+
in = stringArr[0];
31+
} else if (inputs[0].getType() == matlab::data::ArrayType::CHAR){
32+
matlab::data::CharArray charArr = inputs[0];
33+
in.assign(charArr.begin(), charArr.end());
34+
} else {
35+
matlabEng->feval(u"error", 0,
36+
std::vector<matlab::data::Array>({ factory.createScalar("Mex: First input must be a scalar string or char vector") }));
37+
}
38+
39+
// actual function algorithm / computation
40+
std::string out;
41+
if(in.empty())
42+
out = ".";
43+
else
44+
out = std::filesystem::path(fs_drop_slash(in)).parent_path().generic_string();
45+
46+
outputs[0] = factory.createScalar(out);
47+
}
48+
};

0 commit comments

Comments
 (0)