【问题标题】:Absolute value squared of a complex number in FortranFortran中复数的绝对值平方
【发布时间】:2017-08-06 06:51:02
【问题描述】:

Fortran 中是否有一个内在函数来计算复数 z 的平方模 |z|^2

如果没有,是否有比以下更简单或更好的计算方法?

REAL(z, precision_specifier)**2 + AIMAG(z)**2

【问题讨论】:

  • 你可以使用abs(z)**2(见here
  • 我认为关键是要避免采取昂贵的 sqrt。
  • 这听起来效率很低,因为它会计算一个实数的平方根,然后再次平方。
  • 是的,确实如此——如果这是您的应用程序所关心的问题,则可能值得在问题中提及(这可能有助于使某些答案更清晰,因为 cmets 可能是暂时的)。
  • 不仅要避免 sqrt,而且在复杂限制范围以外的编译模式下,编译器将扩​​展代码或调用库函数以避免乘法溢出(您似乎没有担心)。

标签: math fortran arithmetic-expressions


【解决方案1】:

不,Fortran 标准没有定义这样的内在例程。据我所知,目前广泛使用的编译器也没有提供这样的例程。

如果 OP 真的想避免 昂贵的 sqrt,并且不喜欢她现有的解决方案,OP 可以尝试:

real :: rslt
real, dimension(2) :: parts
complex :: z
...
parts = transfer(z, parts)
rslt = dot_product(parts, parts)

或者,给定相同的声明,这可能是首选

rslt = dot_product(transfer(z, parts), transfer(z, parts))

与往常一样,如果性能对您很重要,请衡量它。

更简单还是更好?由你决定。

与往常一样,transfer 不得由 18 岁以下的人或受酒精或其他影响表现的药物影响的人操作。

【讨论】:

    【解决方案2】:

    只是为了好玩,这里有一些尝试使用(旧的??)语句函数来定义 abs2() 并希望被内联......(不推荐使用它,只是实验!)

    program main
        implicit none
        integer, parameter :: dp = kind(0.0d0)
        complex(dp) z
    
        real(dp) abs2
        abs2( z ) = real(z)**2 + aimag(z)**2    ! (could be included or macro-ed??)
    
        ! abs2( z ) = conjg( z ) * z          ! maybe slower
        ! abs2( z ) = z % re**2 + z % im**2   ! near future
        ! intrinsic :: abs2                   ! best solution   
    
        z = ( 1.0_dp, 2.0_dp )
    
        print *, abs( z )**2
        print *, abs2( z )
    
        print *, abs( z + 1.0_dp )**2
        print *, abs2( z + 1.0_dp )
    end program
    
    Result:
       5.0000000000000009     
       5.0000000000000000     
       8.0000000000000018     
       8.0000000000000000  
    

    我希望 z% rez% im 即将推出...(还没有使用 gfortran-6 和 ifort-16)

    【讨论】:

    • 如果你想让这个更漂亮(这不是声明函数的目标吗?):那么real(z,dp)可以替换为real(z),效果相同。
    • real(z) 也有效... :o 我不知道这会返回与 z 相同的类型...
    【解决方案3】:

    只需利用众所周知的公式(a+i*b)*(a-i*b) = a^2 + b^2

     SquaredModulus = real part of (Z * CONJG(Z))
    

    CONJG 是complex conjugate

    【讨论】:

    • @francescalus 我添加了关于实部的注释
    • 您的编辑使您的答案不正确 - 模平方不等于实部乘以复共轭。
    • @Ross 括号已添加 ;)
    【解决方案4】:

    https://gcc.gnu.org/onlinedocs/gfortran/ABS.html

    您可能正在寻找 CABS() 或 CDABS() 然后对其进行平方。我刚刚检查了一下,它可以与 f95 编译器一起使用。

    【讨论】:

    • 欢迎您,我建议您使用tour。使用 CABS 或 CDABS 没有意义。自 Fortran 77 以来提供的通用 ABS 就可以了。问题的重点可能是避免 ABS 进行平方根并再次对其进行平方。请参阅问题下的 cmets。
    猜你喜欢
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多