You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MATLAB MEX修改默认逻辑量kind导致Fortran代码类型不匹配问询

通过MEX对接Fortran 2003+代码时默认逻辑量kind不匹配问题

问题描述

在通过MEX将Fortran 2003及以上版本代码与MATLAB对接时,我发现MEX会修改默认逻辑量的kind值,该问题具有致命性:原本可正常编译的Fortran代码会因类型不匹配无法完成mex编译,我在实际项目中就遇到了该问题。

最小复现示例

将如下代码命名为test_kind.F,在MATLAB中执行mex test_kind.F编译,再运行test_kind指令,会生成名为fort.99的纯文本文件,WRITE指令输出两个数值分别为"4"和"8"。

! test_kind.F
! 测试环境:MATLAB 9.8.0.1323502 (R2020a) + GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

#include "fintrf.h"

      subroutine mexFunction(nlhs, plhs, nrhs, prhs)

      use ieee_arithmetic, only : ieee_is_nan
      implicit none
      mwPointer plhs(*), prhs(*)
      integer nlhs, nrhs

      write(99, *) kind(ieee_is_nan(1.0))  ! 输出值写入fort.99
      write(99, *) kind(.false.)  ! 基准值,理论上应与上一行输出相同
      close(99)

      end subroutine mexFunction

我原本认为这两个输出值应当始终相等,具体数值随编译器变化,不一定是4或8。正如Fortran专家SteveLionel强调的,Fortran标准并未规定kind值与数据占用字节数的对应关系。

【更新】尽管Fortran 2018标准规定kind(ieee_is_nan(1.0))=kind(.false.),但上述推测实际不成立:使用特定编译选项时二者值可能不同,违反Fortran标准要求。

【更新】原问题中我将"4"和"8"的对应关系搞反了,误以为kind(ieee_is_nan(1.0))被修改,实际是kind(.false.)从4变为8,而kind(ieee_is_nan(1.0))始终为4,francescalus的回答已完整解释该现象,在此表示感谢。

对照测试(无MATLAB MEX环境)

以下是未对接MATLAB的相同代码,使用gfortran编译运行时屏幕输出"4"和"4";使用nagfor编译时两个输出值均为3,始终相等。

! test_kind.f90
! 测试环境:GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0

program test_kind

use ieee_arithmetic, only: ieee_is_nan
implicit none

write(*, *) kind(ieee_is_nan(1.0))  ! 输出到屏幕
write(*, *) kind(.false.)   ! 基准值,理论上应与上一行输出相同

end program test_kind

标准依据参考

Fortran 2018标准中关于ieee_is_nan的章节如下,明确规定ieee_is_nan返回值为「默认逻辑量」,我理解其类型应当与内置常量.true.、.false.的类型一致,不知该理解是否有误?

17.11.13 IEEE_IS_NAN (X)
1 功能:判断数值是否为IEEE NaN
2 类型:元素函数
3 参数:X应为实数类型
4 使用限制:若IEEE_SUPPORT_NAN (X)返回false,不可调用IEEE_IS_NAN (X)
5 返回值特征:默认逻辑类型
6 返回值:若X的值为IEEE NaN则返回true,否则返回false

疑问

MEX在修改默认逻辑量类型时未兼顾ieee_is_nan的表现非常反常,是否存在MEX选项可以修正该行为?为何该异常表现会成为MEX的默认配置?

多环境复现结果

我在多台设备、不同版本MATLAB和Fortran编译器上复现了该问题,结果一致:

  • MATLAB 9.7.0.1319299 (R2019b) Update 5搭配GNU Fortran (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5):
    kind(ieee_is_nan(1.0))= 4, kind(.false.) = 8
    相同编译器不对接MATLAB时:
    kind(ieee_is_nan(1.0)) = 4 = kind(.false.)
  • MATLAB 9.5.0.1049112 (R2018b) Update 3搭配GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0:
    kind(ieee_is_nan(1.0)) = 4, kind(.false.) = 8
    相同编译器不对接MATLAB时:
    kind(ieee_is_nan(1.0)) = 4 = kind(.false.)
  • Windows 10环境下MATLAB 9.5.0.944444 (R2018b)搭配Intel(R) Visual Fortran Intel (R) 64 Compiler Version 19.1.1.216 Build 20200306:
    kind(ieee_is_nan(1.0)) = 4, kind(.false.) = 8
    相同编译器不对接MATLAB时:
    kind(ieee_is_nan(1.0)) = 4 = kind(.false.)

问题总结

在参考francescalus的回答后,总结如下:

  1. kind(.false.)与kind(ieee_is_nan(1.0))不匹配的根源是MEX默认启用了gfortran的-fdefault-integer-8选项,该选项强制gfortran使用64位整数和64位逻辑量作为默认kind,但不会修改ieee_is_nan的返回值kind,违反了Fortran标准的规定,可能是因为ieee_is_nan并非纯内置过程,而是内置模块ieee_arithmetic提供的过程。
  2. ifort(版本ifort (IFORT) 2021.2.0 20210228)和nagfor(NAG Fortran Compiler Release 7.0 (Yurakucho) Build 7036)存在相同表现,对应的编译选项为-i8,说明编译器厂商均认为启用特定选项时破坏部分内置模块的一致性是可接受的,这一点令人意外。好在flang(clang 7.1.0版本)即使用了-fdefault-integer-8选项也符合Fortran标准要求,能保持kind(is_ieee_nan(1.0)) == kind(.false.),说明该问题是可修复的。
  3. nagfor在使用-i8选项时会对ieee_is_nan给出不兼容警告,但gfortran即使用-Wall -Wexta、ifort即使用-warn all也不会给出任何提示,这一点更令人意外。
  4. 基于上述情况,我决定不再使用ieee_is_nan,而是自行实现is_nan,同时对所有内置模块提供的过程保持警惕或弃用,否则如果用户选择强制默认使用64位整数(用户本无需考虑逻辑量kind的问题),我的程序包就会因类型不匹配编译失败,更严重的是MATLAB已经为所有用户默认做了该配置却未告知。
  5. 该问题引发了不少有价值的讨论,鉴于部分编译器在该问题上存在优化空间,我已在Fortran社区发布相关帖子,希望能引起社区关注,至少推动gfortran这类开源编译器修复该问题。

欢迎各位提出意见和批评。


内容的提问来源于stack exchange,提问作者Nuno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:39:02