Scientific Computing

List MAC of Bluetooth devices on Windows

Find the MAC address of a Bluetooth device in Windows from Windows Device Manager under Bluetooth, (select device in list), Properties, Details, Bluetooth Device Address.

List all Bluetooth devices and their MAC addresses from PowerShell:

$devices = Get-PnpDevice | Where-Object { $_.Class -eq "Bluetooth" -and $_.FriendlyName }

$results = foreach ($device in $devices) {
    $id = $device.InstanceId
    $name = $device.FriendlyName

    $addressProp = Get-PnpDeviceProperty -InstanceId $id -ErrorAction SilentlyContinue |
                   Where-Object { $_.KeyName -like "*Address*" -and $_.Data -match '^\w{12}$' } |
                   Select-Object -First 1

    if ($addressProp) {
        $raw = $addressProp.Data.ToUpper()
        $bytes = for ($i = 0; $i -lt 12; $i += 2) {
            [convert]::ToByte($raw.Substring($i, 2), 16)
        }
        [array]::Reverse($bytes)
        $mac = ($bytes | ForEach-Object { $_.ToString('X2') }) -join ':'
        [PSCustomObject]@{ Device = $name; 'MAC Address' = $mac }
    }
}

$results | Format-Table -AutoSize

TeXstudio and VS Code team editing

TeXstudio and VS Code are among the IDEs that support remote collaborative code / document editing with real-time updates. The program Teamtype is free, open-source, serverless, peer-to-peer, non-AI tech that enables no-cost real-time collaboration. 2 or more users connect via a Teamtype shared link code - no account or signup is used. Git can be used to capture specific versions or milestones of the LaTeX document. For general code editing and development with VS Code, Teamtype is also supported.

Overleaf has progressively added restrictions to its free plan, making TeXstudio (or VS Code)with Teamtype a good alternative for collaborative LaTeX editing. To have essential security features with an on-premises instantiation of open-source Overleaf Community Edition, a paid Overleaf Pro plan is required.


Alternatives:

  • server-based collaborative team editing is possible with VS Code Live Share.
  • Crixet has an appealing free plan, watch to see how the features evolve vs. pricing
  • Papeeria free version is quite restrictive, only 1 private project
  • Scienhub free version lacks Git integration and has limited storage
  • Authorea

AM two-way radio channel spacing

Since 1972, standard VHF AM used 25 kHz channel spacing generally worldwide. In 1999, European regulations began a mandatory phase-in of 8.33 kHz channel spacing for VHF AM aviation communications to increase the number of available channels. The rest of the world generally remains on 25 kHz spacing for aviation. One factor driving the 8.33 kHz spacing in Europe was the number of relatively close proximity airports and large number of small nations each having their own aviation communication needs. Other countries like China and the United States also have regions with many airports and a lot of air traffic, but each have a unified regulatory framework managing all VHF airband communications.

Anyone who has used AM CB radio or AM broadcast radio would understand why 25 kHz channel spacing is reasonable to avoid adjacent channel interference with real-world AM transmitters and receivers in most reasonable proximities. Even without overmodulated, splattering transmitters, an AM receiver can experience noticeable adjacent channel interference when within about 1 km of another AM transmitter operating on a channel just 10 kHz away. If the CB radio transmitter is operating properly, 20 kHz spacing is adequate when not closer than about 1 km.

This observation can be loosely derived from a typical AM CB radio (say the Cobra 19 mini) receiver’s selectivity performance of say 6 dB at 7 kHz spacing and 60 dB at 10 kHz spacing. Consider also the dynamic range of the receiver, akin to Sherwood Engineering’s Receiver test data, which doesn’t include CB radios. Assume the CB radio transmitter ERP is 36 dBm (4 watts) and the receiver sensitivity for 20 dB SINAD is -113 dBm (0.5 µV). At 1 km distance, free-space path loss at 27 MHz is about 61 dB. This first order approximation neglects important factors like radiation pattern distortion from ground reflections. Assuming 0 dB receiver antenna gain, received signal strength would be about -25 dBm, which can exceed the maximum dynamic range of the receiver front end, if we arbitrarily assume a receiver dynamic range of about 80 dB. However, the typical environmental noise floor on 27 MHz - neglecting skip or other anthropogenic interference - may be ~ -110 dBm in the AM receiver bandwidth, so the dynamic range impacts of a legal CB radio transmitter 1 km away may not be noticeable. An adjacent channel signal 10 kHz away (neglecting modulation bandwidth) would be attenuated by about 60 dB, resulting in a received adjacent channel signal strength of about -85 dBm. The adjacent channel signal would be strong enough to cause noticeable interference on the desired channel, and unwantedly open the squelch if no desired signal is present. With 20 kHz spacing, the adjacent channel signal would be attenuated by over 80 dB, approaching the general receiver’s dynamic range limit vs. the noise floor, and would be much less likely to cause noticeable interference, assuming the transmitter is clean.

The emissions mask in FCC part 95.979 requires better than -35 dBc in the band 8 kHz to 10 kHz from the carrier, and better than -59 dBc beyond 10 kHz from the carrier. The radio transmitter will often do better than -59 dBc at 20 kHz from the carrier and increasingly better beyond that.

Switching to AM VHF airband radio, a typical installed receiver such as the Icom IC-A220 has receiver selectivity at the 25 kHz step of 6 dB at 3 kHz spacing and 60 dB at 22 kHz spacing, and at the 8.33 kHz step of 6 dB at 2.8 kHz spacing and 60 dB at 7.4 kHz spacing. A typical handheld airband transceiver such as the Yaesu FTA-250L RX selectivity in the 25 kHz step of 6dB at 8 kHz spacing and 60 dB at 25 kHz spacing, and at the 8.33 kHz step of 6dB at 2.8 kHz spacing and 60 dB at 8.3 kHz spacing. Thus we see how at airband, where the frequency plans would be made to slice up former 25 kHz step frequencies into distant frequency reuse at 8.33 kHz step, while avoiding close-by overload, the 8.33 kHz step is quite useful.

To put this back into CB radio terms, suppose CB radio is popular in a town. The typical use I’ve seen is for local groups to be at least 20 kHz apart to avoid adjacent channel interference. For example, CB channel 20 (27.205 MHz) is more popular as a “local” channel than channel 18 (27.175 MHz) to avoid adjacent channel interference to/from channel 19 (27.185 MHz). Since CB radio use by definition is entirely ad hoc, users generally space themselves 2 channels (20 kHz) apart in real-world observations. For airband VHF AM in Europe, channels of 8.33 kHz spacing are successfully used with proper frequency planning considering physical separation to avoid adjacent channel interference and overload.

Given the above, I think President should have make like 8 P-channels and not have had “P4” as CB channel 18. They should have instead done like P1 = CB1, P2 = CB3, P3 = CB12, P4 = CB14, P5 = CB22, P6 = CB23, P7 = CB27, P8 = CB29. This avoids CB channels 6, 9, 16 (SSB use), 19, and 20 and the SSB channels 30-40. However those are only hypothetical channel assignments, and President did not in fact do that. Given the existing President P-channel assignments, I think President should consider adding P6-P9 like: P6 = CB14, P7 = CB22, P8 = CB23, P9 = CB27. Again that’s hypothetical. First we need to get more P-channel or at least FM + CTCSS users on CB radio.

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++ AppleClang 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="$LDFLAGS -Wl,-no_compact_unwind"

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

It is possible to programmatically detect this link conflict from CMake using try_compile. In this example, directory “abi_check” contains a small C program that links with a Fortran program.

if(NOT DEFINED ok_compile)

message(CHECK_START "Checking for C++ exception handling with Fortran")

try_compile(ok_compile
PROJECT exception_check
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/exception_check
CMAKE_FLAGS -DCMAKE_LINK_WARNING_AS_ERROR:BOOL=on
OUTPUT_VARIABLE _out
)

# _out is used for CMake < 4.0

if(NOT ok_compile OR _out MATCHES "ld: warning: could not create compact unwind for")
  message(CHECK_FAIL "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}"
  )
else()
  message(CHECK_PASS "OK")
endif()

endif()

Outboard compandoring for radio comms

Compandoring for two-way radio discussion:

Inexpensive integrated circuits like the On Semiconductor SA572 can be used for compandored audio. Compandored audio increases the perceived SNR by greatly reducing audio gain for signals below a threshold, and greatly increasing gain for signals above that threshold. It could be of interest to amateur radio operators to have such a circuit for noisy HF SSB / AM / FM. CB radios before digital NRC features used compandoring e.g. Cobra SoundTracker or Realistic “Audio Clarity Enhancer”. Narrowband FM two-way radios (2 kHz maximum deviation) often use compandoring to improve the audio quality.

Note that compandoring has a downside – when communicating with non-compandored stations, the audio may sound unnatural. Even communicating with another compandored station may sound odd if the settings are not matched well. Compandoring has fallen a bit out of favor due to DSP-based noise reduction (NRC) generally doing a better job of improving apparent SNR with fewer audio artifacts vs. compandoring.

A compandor IC such as used in commercial two-way radio can improve the apparent audio SNR of analog voice communications, whether AM / FM / SSB. The circuit thresholds and compresses transmitted audio, in a better fashion than the simpler clipping circuits sometimes used in ham radio. The circuit also has the capacity to “expand” the receive audio when the transmitting station is transmitting “compressed” audio.

The apparent SNR increase can be on the order of 20 dB if the transmit and receiver compandoring settings are matched. Note that this apparent increase is caused by increasing the average power of the transmission; peak power is still limited by the radio.

The compandor IC SA572NG is available from Mouser for $2. It needs a few common resistors and capacitors external to the IC as well.

ACSSB and 220 MHz two-way radio

The 220 MHz ACSSB two-way radio system in the USA was a remarkable last gasp of analog technology trailing off as DMR, NXDN, P25, and other digital modes began to dominate the land-mobile radio landscape. ACSSB squeezed into 5 kHz channel spacing in contrast to the 12.5 - 25 kHz common for two-way radio FM channels. Digital two-way radio modes achieve 6.25 kHz effective channel spacing via TDMA (DMR, P25 Phase II) or FDMA (NXDN). A vital contemporary use of 220 MHz band is for data telemetry (e.g. SCADA via GE Vernova / MDS radios) and Positive Train Control (PTC).

Technical deep dive links:

The construction requirements for SMRs in the 220, 800, and 900MHz band across the 1990s and 2000s led to some interesting scenarios. One that I saw in the Lansing, Michigan area in the late 1990s was an 800 MHz 5 channel LTR system that used 5 Realistic analog scanning receivers set to a single frequency each, with 5 EF Johnson 8600-series mobile radios set to talkaround on the repeater output frequency. The scanners and mobile were each wired to an LTR controller panel to make a functioning trunked repeater system. This actually worked, but was certainly not to the RF performance of a dedicated repeater design. This was done after the SMR licensee lost 5 of their original 10 channel license due to failure to meet construction requirements.

An attempt to provide a 220 MHz LTR-Net system and data telemetry network across 80% of the continental USA and 2/3 of the population was made by Cornerstone SMR, who was one of the 220 MHz auction 72 winners, but adoption stalled and Cornerstone SMR was denied a waiver on their 220 MHz license construction requirements in 2018. Cornerstone SMR aimed to raise about $5 million in 2003-2004 from investors to build out the wide-area 220 MHz LTR-Net network. Civil theft litigation due to an employee stealing nearly $500k led to an appeal ending in 2015 (Cornerstone SMR, Inc. v. Bank of Am., N.A. , 163 So. 3d 565, 568 (Fla. 4th DCA 2015)) and set a precedent in Florida case law. Cornerstone SMR’s idea to use their 220 MHz spectrum for a nationwide IoT network and proposed business merger to make innovative IoT hardware ultimately led to litigation filed in Delaware in Sept. 2025.

CMake version recommendations and install

Downloading the latest release of CMake is usually easy. Admin / sudo is not required.

  • Linux: snap install cmake
  • macOS: brew install cmake
  • Windows: winget install Kitware.CMake
  • PyPI CMake package: python -m pip install cmake

For platforms where CMake binaries aren’t easily available, build CMake using scripts/build_cmake.cmake.

To see the merge requests for a certain release, use a URL like: https://gitlab.kitware.com/cmake/cmake/-/merge_requests?milestone_title=3.32.0&scope=all&state=all


CMake 4.2 enables Visual Studio 18 2026 generator. The FASTBuild generator is added, and has impressive benchmarks. FASTBuild supports more modern platforms including Windows, versus ccache or distcc.

ExternalProject added options to modify environment variables at each step by CONFIGURE_ENVIRONMENT_MODIFICATION, BUILD_ENVIRONMENT_MODIFICATION, INSTALL_ENVIRONMENT_MODIFICATION, TEST_ENVIRONMENT_MODIFICATION

Targets gain property SPDX_LICENSE


CMake 4.1 project() added COMPAT_VERSION that propagates to subdirectories and can be queried for the top-level COMPAT_VERSION.


CMake 4.0 enables CMAKE_LINK_WARNING_AS_ERROR boolean option sets most compilers to error if a compile warning occurs, which is generally a good setting for CI systems. target_link_libraries() can use a LINKER: prefix to abstract options. CMake SARIF output allows IDEs to better parse build status. CTest –interactive-debug-mode is particularly useful on Windows to enable debug dumps and error popup windows.


CMake 3.31 warns if cmake_minimum_required() is < 3.10. TLS ≥ 1.2 is required by default for internet operations e.g. file(DOWNLOAD), ExternalProject, FetchContent, and similar. file(ARCHIVE_CREATE) gained a long-needed WORKING_DIRECTORY parameter that is essentially necessary to avoid machine-specific paths being embedded in the archive. CMAKE_LINK_LIBRARIES_STRATEGY allows specifying a strategy for ordering target direct link dependencies.


CMake 3.30 adds C++26 support. CMAKE_TLS_VERIFY environment variable was added to set TLS verification (true, false). CMake 3.31 defaults CMAKE_TLS_VERIFY to on, where previously it was off.


CMake 3.29 adds cmake_language(EXIT code) to exit CMake script mode with a specific return code. This is useful when using CMake as a platform-agnostic scripting language instead of shell script.

Environment variable CMAKE_INSTALL_PREFIX is used to set the default install prefix across projects–it can be overridden as typical by cmake -DCMAKE_INSTALL_PREFIX= option.

Target property TEST_LAUNCHER allows specifying a test launcher. For MPI program this allows deduplicating or making more programmatic test runner scripts.

Linker information variables including CMAKE__COMPILER_LINKER_ID have been added to allow programmatic logic like setting target_link_options() based on the particular linker.

ctest --parallel without a number or 0 will use unbounded test run parallelism.


CMake 3.28 changes PATH behavior for Windows find_{library,path,file}() to no longer search PATH. This may break some projects that rely on PATH for finding libraries. The MSYS2-distributed CMake is patched to include PATH like earlier CMake, which can be confusing for CI etc. not using MSYS CMake with that patch. Windows CI/user may need to specify CMAKE_PREFIX_PATH like

cmake -DCMAKE_PREFIX_PATH=$Env:SYSTEMDRIVE/msys64/ucrt64/lib -B build

Support for C++20 modules is considerably improved and most users will want at least CMake 3.28 to make C++ modules usable. Generator expressions $<IF> $<AND> $<OR> now short circuit. Test properties now have a DIRECTORY parameter, useful for setting test parameters from the project’s top level CMakeLists.txt. CMake 3.28.4 fixed a long-standing bug in Ninja Fortran targets that use include statements.


CMake 3.27 emits warning for cmake_minimum_required(VERSION) < 3.5. CTest test properties TIMEOUT_SIGNAL_NAME and TIMEOUT_SIGNAL_GRACE_PERIOD specify a POSIX signal to send to a timed out test process. Interactive CMake debugger added by cmake --debugger is used with an IDE such as Visual Studio. CMake script command cmake_file_api() allows querying CMake File API from within CMake.

ℹ️ Note

Fortran + Ninja was broken for OBJECT libraries in CMake 3.27.0..3.27.8 and fixed in 3.27.9.


Older CMake changelog

Other Tech Blogs

The brief listing of other, somewhat similar blogs is not in any way an endorsement or indication of curation. It’s simply a notepad to remember what other blogs I might have once looked at that reminded me of content I’ve written or helped produce in the past. Since blog addresses might change, discontinue, or go off the deep end, I just put the plain non-linked text.

  • justine.lol - developed Cosmopolitan libc
  • eli.thegreenplace.net
  • noswampcoolers.blogspot.com
  • codeaholicguy.com
  • joelonsoftware.com

Matlab detect Java

Matlab or GNU Octave “.m” script functionality can be readily extended with Java code within the “.m” file. Matlab or GNU Octave do not necessarily include Java from the factory installation. Even if a compatible JDK is installed in Matlab or GNU Octave, Java can be disabled by -nojvm.

Detect if JVM is available from within a Matlab script by:

ok = usejava('jvm');

Obtain the Java version:

javaMethod('getProperty', 'java.lang.System', 'java.version')

GNU Octave Java

GNU Octave also has a JVM interface that extends Octave functionality.

The same commands as for Matlab generally work in Octave via builtin functions javaMethod() and javaObject().

If Java isn’t available in Octave, see if no location or an out of date location to Java is set in the environment variable JAVA_HOME:

getenv('JAVA_HOME')

Currently GNU Octave doesn’t have a way to disable Java from the command line like Matlab’s -nojvm option. One might try setting environment variable JAVA_HOME to an invalid location before starting Octave to simulate no JVM.

macOS

On macOS with Homebrew, Java for Octave can be installed and configured like:

brew install openjdk

Determine the location of the Java Virtual Machine library “libjvm.dylib”:

gfind -L $(brew --prefix openjdk) -name libjvm.dylib

Assuming the path is like “/opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/lib/server/libjvm.dylib”, add to file “~/.octaverc”:

setenv('JAVA_HOME', '/opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home/lib/server/')

Matlab Startup Accelerator for Windows

Matlab Startup Accelerator for Windows is intended to speed up Matlab startup. However, by default Matlab disables the Startup Accelerator on many systems. To check if Matlab Startup Accelerator is enabled on a Windows system, check Windows Task Scheduler by the snapin:

taskschd.msc

Look under Task Scheduler Library for a task named Matlab R20XXx Startup Accelerator (where 20XXx is the Matlab release). Consider disabling it to avoid needless resource usage if it is not already disabled. On modern computers with SSD drives, Matlab startup is already fast.