Matlab arguments validation

Matlab function arguments validation syntax is generally recommended over the legacy validateattributes() and inputParser() techniques. Function arguments validation specification coerces the input and/or output variables to the class declaration given if possible, and errors otherwise.

  • Default values are easily specified, which required such verbose syntax before.
  • only a single class can be specified
  • recall the .empty method of most Matlab classes e.g. datetime.empty() that allows initializing an empty array.

Matlab argument validation syntax coerces class at runtime.

An example of Matlab function argument validate on input and output arguments is in matlab-stdlib.

Free C C++ Fortran compiler families

Several modern, currently-supported compiler families are free-to-use for C, C++ and Fortran.

GCC has broad support of modern standards on a very wide range of computing platforms. GCC’s downside in some cases can be slower runtime performance than compilers having less broad language and platform support.

Compiler C C++ Fortran
GNU gcc: C17 g++ C++20 gfortran: F2018
Intel oneAPI icx: C17 icpx: C++20 ifx: F2018
LLVM clang: C17 clang++: C++20 flang-f18: F2018
AOCC clang: C17 clang++: C++17 flang: F2003
NVidia HPC SDK nvc: C11 nvc++: C++20 nvfortran: F2003
IBM OpenXL xlc: C17 xlc++: C++17 xlf: F2018

Intel oneAPI compilers are free to use for any user. The Intel performance libraries like MKL, IPP, and TBB are available at no cost.


LLVM Clang and Flang have significant industry support, including from Nvidia, and are known for high performance.


AMD AOCC LLVM compiler is tuned for AMD CPUs.


Nvidia HPC SDK is free to use. A key feature of the HPC SDK compilers is intrinsic support for CUDA Fortran.


IBM OpenXL LLVM-based compilers are currently for POWER CPUs only e.g. ppc64le. IBM OpenXL compilers do not work with a typical x86-based computer.

Git default text editor

Git uses the EDITOR environment variable to determine which text editor to use for commit messages. Since the commit message editing is typically small and simple, it may be desired to set a distinct text editor just for Git. This is done via Git global config:

git config --global core.editor "nano"

CMake environment variable names with special characters

Most environment variable have alphanumeric names and don’t need any special consideration to access. On Windows, some important programs still use the “Program Files (x86)” directory, denoted by environment variable “ProgramFiles(x86)”.

cmake_minimum_required(VERSION 3.5)

set(px $ENV{ProgramFiles\(x86\)})

message(STATUS "${px}")

Most other code languages don’t have any particular issues using environment variables named with special characters.

All of the following print like:

C:\Program Files (x86)

Matlab:

getenv("ProgramFiles(x86)")

Python:

python -c "import os; print(os.environ['ProgramFiles(x86)'])"

C++:

#include <cstdlib>
#include <iostream>

int main()
{
    std::cout << std::getenv("ProgramFiles(x86)") << "\n";
    return EXIT_SUCCESS;
}

Fortran:

program env

implicit none

integer :: i
character(100) :: path

call get_environment_variable('ProgramFiles(x86)', path, status=i)
if (i/=0) error stop "env var ProgramFiles(x86) not found"

print '(a)', path

end program env

Matplotlib datetime tick labels

Matplotlib plots with datetime axes can benefit from rotating axes tick labels or concise tick labels to avoid overlapping text.

Example code used in this post with synthetic data:

from matplotlib.pyplot import Figure
import matplotlib.dates as mdates
from datetime import datetime, timedelta

def datetime_range(start: datetime, end: datetime, step: timedelta) -> list[datetime]:
    """like range() for datetime"""
    return [start + i * step for i in range((end - start) // step)]

t = datetime_range(datetime(2021, 1, 1), datetime(2021, 1, 2), timedelta(minutes=30))
y = range(len(t))

Rotate datetime tick labels

If rotating tick labels, the overall axes typically need to be positioned to allow for the rotated labels, otherwise the tick labels can be cut off the figure edges. The axes position is updated automatically with constrained_layout option of figure().

fg = Figure(constrained_layout=True)
ax = fg.gca()

ax.plot(t, y)
ax.set_xlabel('time')
ax.set_ylabel('y')
ax.tick_params(axis="x", labelrotation=30)  # arbitrary rotation amount

fg.savefig("example.png")

Matplotlib date formatting

Matplotlib datetime axes have numerous formatting options. Here we show the ConciseFormatter, which may avoid the need to rotate tick labels.

fg = Figure(constrained_layout=True)
ax = fg.gca()

ax.plot(t, y)
ax.set_xlabel('time')
ax.set_ylabel('y')

ax.xaxis.set_major_formatter(
    mdates.ConciseDateFormatter(ax.xaxis.get_major_locator()))

fg.savefig("example.png")

Diagnose silent quit program DLL conflict Windows

If a DLL conflicts with a programs needed DLLs, the program may quit with a specific message, or it may silently exit. The return code may correspond to segfault or other error. To help see if a DLL conflict is occurring, use gdb to run the program. This works even for general programs that weren’t built on the system. We suggest obtaining GDB via MSYS2. If there is a problem with a DLL, GDB will often print the name of the DLL. If the DLL is in an unexpected location, this may indicate a directory that should not be in environment variable Path.

Start GDB Fortran debugger: assuming executable myprog

gdb myprog.exe

Run program from (gdb) prompt:

r

AppleClang + GFortran no compact unwind warnings

On macOS when using the default “AppleClang” compiler in a Fortran project where GFortran objects are linked with C/C++ objects, the ld linker may emit warnings like:

ld: warning: could not create compact unwind for ...: register .. saved somewhere other than in frame
ld: warning: could not create compact unwind for ...: registers .. and .. not saved contiguously in frame

This is an actual issue because C++ exception handling will not completely work when this warning is emitted from C++ code coupled with Fortran code. In general, using C++ exception handling within C++ code that is linked with Fortran code will work just fine, except when this warning is issued. The solution is to use GNU GCC C++ compiler with GFortran instead of mixing AppleClang with GFortran.

Specifying environment variable:

LDFLAGS="-Wl,-no_compact_unwind"

removes the warning, but this also disables C++ exception handling so is not recommended.

It is possible to programmatically detect this link conflict from CMake using try_compile.

try_compile(abi_compile
PROJECT abi_check
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/abi_check
OUTPUT_VARIABLE abi_output
)

if(abi_output MATCHES "ld: warning: could not create compact unwind for")
  message(WARNING "C++ exception handling will not work reliably due to incompatible compilers:
  C++ compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}
  Fortran compiler ${CMAKE_Fortran_COMPILER_ID} ${CMAKE_Fortran_COMPILER_VERSION}"
  )
endif()

where directory “abi_check” contains a small C program that links with a Fortran program.

CMake CppCheck static code checks

CMake has built-in support for C/C++ static code analysis tools such as CppCheck. Apply CppCheck to CMake targets with CMakeLists.txt by setting CMAKE_CXX_CPPCHECK.

File “cppcheck.supp” contains suppressions for false positives. NOTE: CMake runs cppcheck from an arbitrary directory, so per-file suppressions in the file don’t work as usual. To suppress a warning for a specific file, use the --suppress option to cppcheck in CMakeLists.txt like:

set_property(TARGET MyTarget PROPERTY CXX_CPPCHECK "${CMAKE_CXX_CPPCHECK};--suppress=containerOutOfBounds")

Don’t just blindly modify code based on CppCheck output. Think of it like any code analysis tool–there are false positives (and false negatives).

Configure Bash or Zsh shell

When moving between Linux systems that often default to Bash, and macOS systems that often default to Zsh, one may wish to change the default shell parameters.

For example, to remove duplicate entries in shell history, so that pressing “up” on repeated commands doesn’t make you press “up” repeatedly to get to the last non-duplicated command, set like the following.

Bash: ~/.inputrc: ignore duplicate lines, and omits lines that start with space.

export HISTCONTROL=ignoreboth

Zsh: ~/.zshrc: approximately the equivalent of the above Bash setting.

setopt hist_ignore_dups
setopt hist_ignore_space