基本数学函数的 Dart 源代码

问题描述 投票:0回答:1

出于兴趣,我最近尝试查看 dart 编程语言中一些基本数学函数的源代码(更具体地说,在

dart:math
包中)。

以余弦函数。很容易找到它的文档

余弦文档

然后单击右上角的“查看源代码”按钮。然而,问题就从这里开始了。在相应的文件中,唯一相关的代码行是

/// Converts [radians] to a [double] and returns the cosine of the value.
///
/// If [radians] is not a finite number, the result is NaN.
external double cos(num radians);

没有任何提示在哪里可以找到实际的实现。事实上,它似乎根本没有像人们想象的那样包含在

sdk/lib/math
目录中。

有人知道在哪里可以找到它吗?预先感谢您!

dart math implementation
1个回答
0
投票

我不是 Dart 项目的开发人员,所以我可能会弄错所有这些。因此,请将此我的答案视为我对正在发生的事情的最佳猜测。 :)

原生运行时,Dart 使用

cos
的 libc 版本。实现有点难找到,但让我们尝试一下。您找到的定义被定义为
external
,这意味着实际的实现正在根据运行平台进行修补。

所以对于本地人来说,我们需要看:

@pragma("vm:exact-result-type", "dart:core#_Double")
@pragma("vm:prefer-inline")
double cos(num radians) => _cos(radians.toDouble());
...
@pragma("vm:recognized", "other")
@pragma("vm:prefer-inline")
external double _cos(double x);

https://github.com/dart-lang/sdk/blob/3b128c5454834a1aaef37d9bb12595e7c217ab61/sdk/lib/_internal/vm/lib/math_patch.dart#L133-L135

这里的提示是

vm:recognized
,它告诉 Dart 编译器应该特殊处理这个方法调用。我们可以在 SDK 中找到它应该识别以进行特殊处理的方法列表。在这里我们发现:

// (class-name, function-name, recognized enum, fingerprint).
// When adding a new function, add a 0 as the fingerprint and run the build in
// debug mode to get the correct fingerprint from the mismatch error.
...
  V(::, _sin, MathSin, 0x17cc3e23)                                             \
  V(::, _cos, MathCos, 0xf485f165)                                             \
  V(::, _tan, MathTan, 0xeb0bc957)                                             \
  V(::, _asin, MathAsin, 0x29d649be)                                           \
  V(::, _acos, MathAcos, 0x1ffc14fb)                                           \
  V(::, _atan, MathAtan, 0x10ebd512)                                           \
  V(::, _atan2, MathAtan2, 0x58c66573)                                         \
  V(::, _sqrt, MathSqrt, 0x0309a7b0)                                           \
  V(::, _exp, MathExp, 0x00e673f0)                                             \
  V(::, _log, MathLog, 0x099ff882)                                             \
...

我们稍后可以在

MathCos
中找到
il.cc
的踪迹:

const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const {
  switch (recognized_kind_) {
    case MethodRecognizer::kDoubleTruncateToDouble:
      return kLibcTruncRuntimeEntry;
    case MethodRecognizer::kDoubleRoundToDouble:
      return kLibcRoundRuntimeEntry;
    case MethodRecognizer::kDoubleFloorToDouble:
      return kLibcFloorRuntimeEntry;
    case MethodRecognizer::kDoubleCeilToDouble:
      return kLibcCeilRuntimeEntry;
    case MethodRecognizer::kMathDoublePow:
      return kLibcPowRuntimeEntry;
    case MethodRecognizer::kDoubleMod:
      return kDartModuloRuntimeEntry;
    case MethodRecognizer::kMathTan:
      return kLibcTanRuntimeEntry;
    case MethodRecognizer::kMathAsin:
      return kLibcAsinRuntimeEntry;
    case MethodRecognizer::kMathSin:
      return kLibcSinRuntimeEntry;
    case MethodRecognizer::kMathCos:
      return kLibcCosRuntimeEntry;
    case MethodRecognizer::kMathAcos:
      return kLibcAcosRuntimeEntry;
    case MethodRecognizer::kMathAtan:
      return kLibcAtanRuntimeEntry;
    case MethodRecognizer::kMathAtan2:
      return kLibcAtan2RuntimeEntry;
    case MethodRecognizer::kMathExp:
      return kLibcExpRuntimeEntry;
    case MethodRecognizer::kMathLog:
      return kLibcLogRuntimeEntry;
    default:
      UNREACHABLE();
  }
  return kLibcPowRuntimeEntry;
}

https://github.com/dart-lang/sdk/blob/3b128c5454834a1aaef37d9bb12595e7c217ab61/runtime/vm/compiler/backend/il.cc#L6991-L7027

这个常量的名称有点泄露了我们正在使用 libc。但是找到

kLibcCosRuntimeEntry
的定义并不明显,因为这个常量是使用以下宏生成的:

#define DEFINE_RAW_LEAF_RUNTIME_ENTRY(name, argument_count, is_float, func)    \
  extern const RuntimeEntry k##name##RuntimeEntry(                             \
      "DFLRT_" #name, func, argument_count, true, is_float,                    \
      /*can_lazy_deopt=*/false)

https://github.com/dart-lang/sdk/blob/3b128c5454834a1aaef37d9bb12595e7c217ab61/runtime/vm/runtime_entry.h#L147-L150

然后在这里使用:

DEFINE_RAW_LEAF_RUNTIME_ENTRY(
    LibcCos,
    1,
    true /* is_float */,
    reinterpret_cast<RuntimeFunction>(static_cast<UnaryMathCFunction>(&cos)));

https://github.com/dart-lang/sdk/blob/3b128c5454834a1aaef37d9bb12595e7c217ab61/runtime/vm/runtime_entry.cc#L3894-L3898

其中

&cos
指的是从
cos
全局导入的
math.h
方法:

#include <math.h>

https://github.com/dart-lang/sdk/blob/3b128c5454834a1aaef37d9bb12595e7c217ab61/runtime/platform/globals.h#L83

© www.soinside.com 2019 - 2024. All rights reserved.