Scientific Computing

Matlab builtin() function overload

Matlab built-in functions can be overloaded in classes or in general. This can be useful when making code compatible with both Matlab and GNU Octave, or to be compatible with older Matlab versions.

For example, the Matlab built-in function strlength gets the length of char and string arrays, but older Matlab and GNU Octave don’t have this function. We made a function in strlength.m in a project’s private/ directory like:

%% STRLENGTH get length of character vector or scalar string

function L = strlength(s)

L = [];

if ischar(s)
  L = length(s);
elseif isstring(s)
  L = builtin('strlength', char(s));
  % char() is workaround for bug described below
end

end

A bug we found and confirmed by Xinyue Xia of Mathworks Technical Support is as follows: strlength() works with char, or string scalars or N-D arrays. However, when using

builtin('strlength')

only char is accepted. Scalar or N-D string array errors unexpectedly.

Example:

builtin('strlength', ["hi", "there"])

we expect to get [2,5] but instead get:

Error using strlength First argument must be text.

builtin('strlength', "hi")

expect value 2, but instead get

Error using strlength First argument must be text.

Matlab refresh function cache

Matlab might not use newly-compiled MEX functions if the function cache is not cleared. This can happen when the MEX function was previously called before building the MEX code. For example, suppose a project has a Matlab function timestwo.m and optionally MEX compiled function also called timestwo.

function y = timestwo(x)
  disp("this is plain Matlab script")
  y = 2 * x;
end

If one builds the MEX function with the same name and then calls the function, Matlab may not use the MEX compiled version until the function cache is cleared. Clear the Matlab function cache, thereby enabling newly-compiled MEX functions to be used by command

clear functions

% or

clear all

These commands do NOT clear the function cache:

% these don't help
rehash
rehash path
clear mex

Matlab remote desktop plot rendering

Matlab graphics rendering can break with remote desktop via VNC or X11 forwarding. Local Matlab plots can break due to GPU graphics driver problems. Before Matlab R2025a, setting Matlab figure renderer could workaround Matlab plot issues. Consider using Matlab Online for remote development if available.

f = figure;

% Obsolete as of Matlab R2025a
set(f, Renderer='painters', RendererMode='manual')

Matlab rendererinfo() provides extensive details about the rendering backend.

Conda commands fail with Windows PowerShell 7.5

With Conda older than 25.0 on Windows, upon upgrading to PowerShell 7.5, all Conda commands might fail like:

Invoke-Expression: Cannot bind argument to parameter ‘Command’ because it is an empty string.

The underlying issue is the faulty syntax of the Conda scripts.

The easiest solution is to uninstall and reinstall Miniconda or Anaconda.

Year 2038 long int on Windows

The POSIX epoch time is the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970. Operations involving POSIX epoch time, particularly on Windows, may run into Year 2038 problems if “long” type is used to store the epoch time in seconds. The “long” int type only guarantees 32-bit integers, which can store values up to 2,147,483,647. The maximum value that can be stored in a 32-bit signed integer is 2,147,483,647, which corresponds to 03:14:07 UTC on Tuesday, 19 January 2038. After this time, a 32-bit “long” value will overflow, which can cause unexpected behavior in applications that rely on the epoch time. To avoid this problem in a cross-platform compatible manner, consider the explicit 64-bit integer type int64_t to store the epoch time in programs written in C, C++ or likewise in other code languages to store POSIX epoch time. We chose “int64_t” instead of “long long” to be explicit about the integer size needed and useful, which is a general best practice in C / C++.

Example using std::difftime to calculate the difference between two time points:

#include <cstdint>
#include <ctime>
#include <string>
#include <iostream>

int main() {
    std::time_t t1 = 0;
    std::time_t t2 = 2147483648; // 03:14:08 UTC on Tuesday, 19 January 2038
    std::string posix = std::to_string(static_cast<std::int64_t>(std::difftime(t2, t1)));

    std::cout << "POSIX time difference: " << posix << " seconds\n";

    return 0;
}

CMake end of support schedule

CMake 4.0 introduced a formal end of support schedule for older CMake versions. This schedule impacts cmake_minimum_required in that a CMake project will not configure if CMAKE_POLICY_VERSION_MINIMUM is older than the minimum version of CMake that is still supported.

Practical observations of CMake projects are that projects too often have CMake minimum versions that aren’t actually usable, or set to CMake versions so old that they are difficult to run on modern computers. A good CI test is to have an old CMake version that matches cmake_minimum_required(VERSION) to see if the project actually works with such an old CMake version.

Find the date of a CMake release under Milestones.

GitLab download specific commit archive

Git hosting providers typically provide a way to download an archive of specific Git commit hashes. There may or may not be an archive link on the project page, but there is typically a URL format to download Git commit archives directly. On GitLab, download a specific commit archive using the following URL format:

https://gitlab.com/<namespace>/<project>/-/archive/<commit_hash>/<project>-<commit_hash>.tar.bz2

The older and less efficient suffix .tar.gz can be used if a system doesn’t have BZip2 installed, but that would be uncommon.

Windows 32-bit binaries with CMake + MSVC

Certain program and drivers on Windows require 32-bit binaries. Perhaps the source code for the program or driver is lost or otherwise not available, and reverse engineering is not an option. Or perhaps an embedded Windows system requires a 32-bit binary. CMake and MSVC can easily build 32-bit binaries on 64-bit Windows. It’s also possible to cross-compile 32-bit binaries on 64-bit Linux or Windows using MinGW, but this article focuses solely on MSVC.

The “Visual Studio” CMake generator is necessary with CMake architecture specified as “Win32”. Using non-Visual Studio CMake generators like Ninja require a cross-compiler CMake toolchain or using the 32-bit native Visual Studio prompt. To avoid these complications, this example uses the Visual Studio CMake generator. Think of it like a simple cross-compilation setup. This can be done from the command line like:

cmake -G "Visual Studio 17 2022" -A Win32 -B build
cmake --build build

This can be turned into a one-step workflow using a CMakePresets.json like:

{
  "version": 6,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 25,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "default",
      "generator": "Visual Studio 17 2022",
      "architecture": "Win32",
      "binaryDir": "${sourceDir}/build"
    }
  ],
    "buildPresets": [
        {
        "name": "default",
        "configurePreset": "default",
        "configuration": "Release"
        }
      ],
"workflowPresets": [
  {
    "name": "default",
    "steps": [
      {
        "type": "configure",
        "name": "default"
      },
      {
        "type": "build",
        "name": "default"
      }
    ]
  }
]
}

and then build with:

cmake --workflow --preset default

DLL building

Regardless of 32-bit or 64-bit binaries, if a DLL is required to be built, use the add_library(... SHARED ...) command in the CMakeLists.txt file.

Suspend a Windows program

The Windows PsSuspend SysInternals tool can suspend (pause) and resume a Windows program. This is useful for programs that take time to startup, close, or configure but that the user doesn’t want to leave running all the time. For example, a game or control program that polls repeatedly for changes but the user doesn’t always need to have the program constantly running.