Initial Commit

This commit is contained in:
2026-09-15 15:24:03 -04:00
commit 4dc7086e7e
605 changed files with 101380 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
#!/bin/sh
# Guard the MATLAB compatibility shims at image build time.
#
# Two jobs, both of which have to happen before anyone can run code
# against this image rather than after:
#
# 1. DROP any shim whose name Octave has since acquired. The shim
# directory sits ahead of everything on the path, so a stale copy
# would shadow the real implementation - our four-signature `contains`
# would quietly replace a complete one. Octave gaining a function is
# good news; the correct response is to delete ours, not to keep it.
#
# 2. TEST what survives. Each shim is asserted against the behaviour the
# MATLAB documentation specifies - including the edge conventions that
# are the whole reason these are not one-line aliases. A failure fails
# the build: a wrong answer that runs is the one outcome this sandbox
# exists to prevent.
#
# print.m is exempt from (1). It shadows Octave's own print deliberately
# and permanently; see shim/print.m.
set -e
SHIM_DIR=/opt/owuitools-shim
[ -d "$SHIM_DIR" ] || { echo "check-shims: $SHIM_DIR missing"; exit 1; }
for f in "$SHIM_DIR"/*.m; do
name=$(basename "$f" .m)
case "$name" in
print|owuitools_*) continue ;;
esac
# Asked WITHOUT the shim directory on the path, which is where Octave
# starts. The answer is printed rather than returned as an exit code, so
# that an Octave that fails for some unrelated reason cannot be read as
# "this function exists" - an unreadable answer keeps the shim, and the
# behaviour tests below then have the last word.
have=$(octave --no-window-system --norc --quiet \
--eval "printf('%d', exist('$name') > 0)" 2>/dev/null)
case "$have" in
1) echo "check-shims: DROPPING $name - this Octave provides it"
rm -f "$f" ;;
0) echo "check-shims: keeping $name (Octave has no such function)" ;;
*) echo "check-shims: could not test $name (got '$have'), keeping it" ;;
esac
done
echo "check-shims: running the behaviour tests"
octave --no-window-system --norc --quiet --eval "
addpath('$SHIM_DIR', '-begin');
function check(label, cond)
if (~cond)
error('check-shims FAILED: %s', label);
end
printf(' ok %s\n', label);
end
if (exist('contains') > 0)
check('contains char', contains('hello world', 'o w') == true);
check('contains miss', contains('hello', 'zz') == false);
check('contains cell', isequal(contains({'ab','cd'}, 'c'), [false true]));
check('contains any of', contains('abc', {'x','b'}) == true);
check('contains IgnoreCase', contains('ABC', 'b', 'IgnoreCase', true) == true);
end
if (exist('strlength') > 0)
check('strlength char', strlength('abcd') == 4);
check('strlength cell', isequal(strlength({'a','abc'}), [1 3]));
check('strlength empty', strlength('') == 0);
end
if (exist('matches') > 0)
check('matches exact', matches('abc', 'abc') == true);
check('matches not substring', matches('abc', 'ab') == false);
end
if (exist('maxk') > 0)
check('maxk values', isequal(maxk([3 1 4 1 5], 2), [5 4]));
check('maxk row shape', size(maxk([3 1 4], 2), 1) == 1);
[~, i] = maxk([3 1 4 1 5], 2);
check('maxk indices', isequal(i, [5 3]));
check('maxk k over n', numel(maxk([1 2], 9)) == 2);
check('maxk matrix is column-wise', isequal(maxk([1 9; 5 2], 1), [5 9]));
end
if (exist('mink') > 0)
check('mink values', isequal(mink([3 1 4 1 5], 2), [1 1]));
end
if (exist('histcounts') > 0)
check('histcounts counts', isequal(histcounts([1 2 2 3], [1 2 3 4]), [1 2 1]));
check('histcounts last bin closed', isequal(histcounts([4], [1 2 3 4]), [0 0 1]));
check('histcounts half open', isequal(histcounts([2], [1 2 3 4]), [0 1 0]));
check('histcounts drops NaN', sum(histcounts([1 NaN], [1 2])) == 1);
failed = false;
try
histcounts([1 2 3]);
catch
failed = true;
end
check('histcounts refuses auto bins', failed);
end
if (exist('discretize') > 0)
check('discretize bins', isequal(discretize([1 2.5 4], [1 2 3 4]), [1 2 3]));
check('discretize outside is NaN', isnan(discretize(9, [1 2])));
end
if (exist('rmmissing') > 0)
check('rmmissing vector', isequal(rmmissing([1 NaN 3]), [1 3]));
check('rmmissing keeps row shape', size(rmmissing([1 NaN 3]), 1) == 1);
check('rmmissing matrix drops rows', isequal(rmmissing([1 2; NaN 4; 5 6]), [1 2; 5 6]));
failed = false;
try
rmmissing({'a'});
catch
failed = true;
end
check('rmmissing refuses cells', failed);
end
printf('check-shims: all shim behaviour tests pass\n');
"