Scientific Computing

Eliminate old C-style casts in C++

The C++ named casts such as static_cast, dynamic_cast, and reinterpret_cast are preferred in C++ Core Guideline ES.49 over ambiguous old C-style casts. C++ named casts can help provide type safety by making the intention of the cast explicit / readable. C++ compilers can detect and warn about improper or unsafe casts when using named casts. C-style cast mistakes are more difficult to detect by humans or automated tools.

static_cast is used for conversions between compatible types, such as converting an int to a float or a pointer to a base class to a pointer to a derived class. Another common static_cast use case is interfacing with C functions such as Windows API functions that require specific types less common in pure C++ code.

int a = 10;
float b = static_cast<float>(a);

reinterpret_cast is used for low-level reinterpreting of bit patterns. It casts a type to a completely different type. This cast is not type safe and should be used with caution to avoid undefined behavior. reinterpret_cast is commonly used in low-level programming, such as interfacing with hardware or converting between pointers and integers.

int a = 10;
char* b = reinterpret_cast<char*>(&a);

dynamic_cast is used for safe downcasting of pointers or references to classes in a class hierarchy. It performs a runtime or RTTI check to help ensure that the cast is valid. dynamic_cast is used when you need to convert a pointer or reference to a base class to a pointer or reference to a derived class. static_cast is more common and faster than dynamic_cast, but dynamic_cast is safer when downcasting in a class hierarchy.

Detecting Old-Style Casts with GCC or Clang

To ensure that old C-style casts are not used in a codebase, consider the -Wold-style-cast flag with GCC or Clang. This flag generates warnings for any old-style casts found in the code.

In CMake, this flag is applied like:

dd_compile_options("$<$<COMPILE_LANG_AND_ID:CXX,AppleClang,Clang,GNU>:-Wold-style-cast>")

If the CMake variable CMAKE_COMPILE_WARNING_AS_ERROR is set true, the old-style cast warnings (and other compile warnings) will be treated as errors.

Matlab / Octave integer representation

For proper integer representation in Matlab / Octave use explicit type to avoid Matlab unwanted casting to “double” for integers.

x = int64(2^63);

Operations involving an explicitly-typed variable will retain that type, assuming implicit casting due to other variables or operations doesn’t occur. Precise string representation of “x” can be done using int2str(), sprintf(), or string():

xc = int2str(x);

xf = sprintf('%d', x);

xs = string(x);

sprintf() gives more control over the string output format, while string() or int2str() are more concise.

ATSC 1.0 MPEG-4 older TVs no video

In 2008 the ATSC ratified the MPEG-4 TV broadcast standard. Numerous ATSC 1.0 TVs were sold before this standard was ratified, and still operate today. TV manufacturers continued to make some non-MPEG-4 TVs for a decade after the standard was ratified. As a practical matter to avoid abandoning viewers with older receivers, ATSC 1.0 broadcasts remain on while implementing ATSC 3.0 broadcasts. This lighthousing of ATSC 1.0 broadcasts leads broadcasters to use MPEG-4 encoding for ATSC 1.0 broadcasts.

MPEG-2 is the legacy encoding standard for ATSC 1.0 broadcasts, which any old DTV can receive. A typical ATSC 1.0 MPEG-2 broadcast channel layout was one 1080i channel and several 480i channels, or 1-2 720p channel(s) with even more 480i channels. ATSC broadcast channel layout is a tradespace between the number of subchannels vs. the bandwidth per subchannel. This database lists the channels available in a given area. Click “Technical Data” to see the resolution and encoding of each channel.

As ATSC 3.0 broadcasts roll out, the number of ATSC 1.0 channels are expected to decrease. A mitigation for broadcasters is to switch to MPEG-4 encoding for the ATSC 1.0 broadcasts, which is more efficient than MPEG-2 and allows packing more channels into the same transmitter bandwidth. This leaves older TVs and receivers with audio-only on MPEG-4 channels. This MPEG-4 list is missing some broadcasters. Note that some ATSC broadcasts have audio-only subchannels.

A solution for the end user lacking an MPEG-4-capable TV is to buy an ATSC receiver box that supports MPEG-4. These can be obtained for less than $50. ATSC 3.0 receivers are available for less than $100 if desired to access ATSC 3.0 broadcasts not available even on some new TVs.

Enthusiasts make their “band scan” data available for TV and FM radio typically using a Raspberry Pi to enjoy and share the hobby of broadcast DXing.

Free 2-D CAD drawing programs

AutoCAD 2-D libre alternatives are available for Linux, macOS and Windows. They generally require retraining for users coming from AutoCAD. Libre 2-D AutoCAD-like choices include FreeCAD, QCAD and LibreCAD.

FreeCAD is 3-D parametric modeling akin to SolidWorks that can import DXF or DWG. QCAD has distinct paid vs. Community Edition features include DWG and DXF read / write. LibreCAD can read / write DXF and read DWG.

The no-cost ODA File Converter converts DXF to / from DWG.

Install Nvidia HPC C, C++, Fortran compilers

The free-to-use Nvidia HPC SDK offers possible speed improvements and CUDA Fortran. A typical reason for using Nvidia HPC SDK is the Cuda GPU features. Nvidia HPC compilers support C11, C++23, and partial Fortran 2008 including submodule and error stop.

Download and install Nvidia HPC SDK. Create a script nvidia.sh:

To use NVIDIA HPC SDK, source the script:

source ~/nvidia.sh

CMake

In CMake, set NVIDIA HPC compiler-specific options in CMakeLists.txt like:

if(CMAKE_Fortran_COMPILER_ID STREQUAL "NVHPC")
  add_compile_options($<$<COMPILE_LANGUAGE:Fortran>:-Mdclchk;-Munixlogical>)
endif()

To use newer languages standard features ensure the underlying GCC toolchain is set to a new-enough compiler as per Nvidia HPC SDK documentation. The compiler path can be determined on RHEL-like Linux distros like:

scl enable gcc-toolset-12 "dirname $(which g++)"

If using a CMake toolchain file, instead of CXXFLAGS environment variable, one can set

set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN "/opt/rh/gcc-toolset-12/root/usr/")

Visual Studio /utf-8 source files

The MSVC compiler needs the /utf-8 flag when UTF-8 strings are in the source file. If not specified, too many bytes are assigned to each character, leading to incorrect string lengths. This will lead to failures with string width conversions such as WideCharToMultiByte.

Windows Intel oneAPI compiler didn’t need the /utf-8 flag when tested.

In CMake, apply the /utf-8 flag like:

add_compile_options($<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/utf-8>)

In Meson, the /utf-8 flag is applied automatically to C++ source files with MSVC compilers.

Beggar Barons of Software

Zed Shaw coins the term Beggar Barons in his blog post on being a popular software author begged to make significant changes to software to accommodate the large company’s needs. The recent situation involving Python vis-à-vis the Apple App Store reminds us of this phenomenon via Zed’s article. Python with iOS or Android requires using libpython in a compiled application, rather than the more typical terminal use–although there are apps that bring that experience to mobile devices as well.

Datetime vectors in Matlab / Octave

Generating a range of datetime data is a common data analysis and simulation task across programming languages. Matlab and GNU Octave can also generate datetime vectors.

Matlab datetime deprecates datenum. Generate a sequence of datetime like:

t0 = datetime('2020-01-05 12:30:00');
t1 = datetime('2020-01-06 18:15:10');
dt = hours(5.5);

t = t0:dt:t1;

disp(t)

GNU Octave can use many datetime features via the tablicious package.

pkg install tablicious

Load in Octave prompt:

pkg load tablicious

Then use the same Matlab code above.

No strict aliasing C / C++

Optimizing compilers may enable strict aliasing. For a wide variety of existing projects, strict aliasing provides additional optimization. For some projects, such as MUMPS, memory leaks have been observed that are resolved by disabling strict aliasing using GCC flag “-fno-strict-aliasing”.

Compilers with ability to switch on / off strict aliasing include:

libuv recommends -fno-strict-aliasing due to type punning.

References:

CMake Zstd compression

Zstd is an open file compression standard. Zstd has become widely used and is incorporated in the Linux kernel and GCC. We use Zstd for data archiving particularly for large files where size and speed are a concern. CMake supports Zstd compression throughout, including file(ARCHIVE_CREATE) and file(ARCHIVE_EXTRACT). Zstd is vendored into CMake, so there is no need to worry about system libraries for Zstd.

file(ARCHIVE_CREATE ... WORKING_DIRECTORY ...) is necessary to avoid system-specific relative path issues.

set(archive "example.zst")
set(in_dir "data/")

file(ARCHIVE_CREATE
  OUTPUT ${archive}
  PATHS ${in_dir}
  COMPRESSION Zstd
  COMPRESSION_LEVEL 3
  WORKING_DIRECTORY ${in_dir}
  )
COMPRESSION_LEVEL
arbitrary, bigger value is more compressed.
FORMAT
not used for Zstd.