void RegisterScalarArithmetic()

in cpp/src/arrow/compute/kernels/scalar_arithmetic.cc [1415:1904]


void RegisterScalarArithmetic(FunctionRegistry* registry) {
  // NOTE for registration of arithmetic kernels: to minimize code generation,
  // it is advised to template the actual executors with physical execution
  // types (e.g. Int64 instead of Duration or Timestamp).

  // ----------------------------------------------------------------------
  auto absolute_value =
      MakeUnaryArithmeticFunction<AbsoluteValue>("abs", absolute_value_doc);
  AddDecimalUnaryKernels<AbsoluteValue>(absolute_value.get());

  // abs(duration)
  for (auto unit : TimeUnit::values()) {
    auto exec = ArithmeticExecFromOp<ScalarUnary, AbsoluteValue>(duration(unit));
    DCHECK_OK(
        absolute_value->AddKernel({duration(unit)}, OutputType(duration(unit)), exec));
  }

  DCHECK_OK(registry->AddFunction(std::move(absolute_value)));

  // ----------------------------------------------------------------------
  auto absolute_value_checked = MakeUnaryArithmeticFunctionNotNull<AbsoluteValueChecked>(
      "abs_checked", absolute_value_checked_doc);
  AddDecimalUnaryKernels<AbsoluteValueChecked>(absolute_value_checked.get());
  // abs_checked(duraton)
  for (auto unit : TimeUnit::values()) {
    auto exec =
        ArithmeticExecFromOp<ScalarUnaryNotNull, AbsoluteValueChecked>(duration(unit));
    DCHECK_OK(absolute_value_checked->AddKernel({duration(unit)},
                                                OutputType(duration(unit)), exec));
  }
  DCHECK_OK(registry->AddFunction(std::move(absolute_value_checked)));

  // ----------------------------------------------------------------------
  auto add = MakeArithmeticFunction<Add>("add", add_doc);
  AddDecimalBinaryKernels<Add>("add", add.get());

  // Add add(timestamp, duration) -> timestamp
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec = ScalarBinary<Int64Type, Int64Type, Int64Type, Add>::Exec;
    DCHECK_OK(add->AddKernel({in_type, duration(unit)}, OutputType(FirstType), exec));
    DCHECK_OK(add->AddKernel({duration(unit), in_type}, OutputType(LastType), exec));
  }

  // Add add(duration, duration) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::DurationTypeUnit(unit));
    auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, Add>(Type::DURATION);
    DCHECK_OK(add->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  AddArithmeticFunctionTimeDuration<AddTimeDuration>(add);
  AddArithmeticFunctionDurationTime<AddTimeDuration>(add);

  DCHECK_OK(registry->AddFunction(std::move(add)));

  // ----------------------------------------------------------------------
  auto add_checked =
      MakeArithmeticFunctionNotNull<AddChecked>("add_checked", add_checked_doc);
  AddDecimalBinaryKernels<AddChecked>("add_checked", add_checked.get());

  // Add add_checked(timestamp, duration) -> timestamp
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec = ScalarBinary<Int64Type, Int64Type, Int64Type, AddChecked>::Exec;
    DCHECK_OK(
        add_checked->AddKernel({in_type, duration(unit)}, OutputType(FirstType), exec));
    DCHECK_OK(
        add_checked->AddKernel({duration(unit), in_type}, OutputType(LastType), exec));
  }

  // Add add(duration, duration) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::DurationTypeUnit(unit));
    auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, AddChecked>(Type::DURATION);
    DCHECK_OK(
        add_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  AddArithmeticFunctionTimeDuration<AddTimeDurationChecked>(add_checked);
  AddArithmeticFunctionDurationTime<AddTimeDurationChecked>(add_checked);

  DCHECK_OK(registry->AddFunction(std::move(add_checked)));

  // ----------------------------------------------------------------------
  auto subtract = MakeArithmeticFunction<Subtract>("subtract", sub_doc);
  AddDecimalBinaryKernels<Subtract>("subtract", subtract.get());

  // Add subtract(timestamp, timestamp) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, Subtract>(Type::TIMESTAMP);
    DCHECK_OK(subtract->AddKernel({in_type, in_type},
                                  OutputType::Resolver(ResolveTemporalOutput),
                                  std::move(exec)));
  }

  // Add subtract(timestamp, duration) -> timestamp
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec = ScalarBinary<Int64Type, Int64Type, Int64Type, Subtract>::Exec;
    DCHECK_OK(subtract->AddKernel({in_type, duration(unit)}, OutputType(FirstType),
                                  std::move(exec)));
  }

  // Add subtract(duration, duration) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::DurationTypeUnit(unit));
    auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, Subtract>(Type::DURATION);
    DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  // Add subtract(time32, time32) -> duration
  for (auto unit : {TimeUnit::SECOND, TimeUnit::MILLI}) {
    InputType in_type(match::Time32TypeUnit(unit));
    auto exec = ScalarBinaryEqualTypes<Int64Type, Int32Type, Subtract>::Exec;
    DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  // Add subtract(time64, time64) -> duration
  for (auto unit : {TimeUnit::MICRO, TimeUnit::NANO}) {
    InputType in_type(match::Time64TypeUnit(unit));
    auto exec = ScalarBinaryEqualTypes<Int64Type, Int64Type, Subtract>::Exec;
    DCHECK_OK(subtract->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  // Add subtract(date32, date32) -> duration(TimeUnit::SECOND)
  InputType in_type_date_32(date32());
  auto exec_date_32 = ScalarBinaryEqualTypes<Int64Type, Int32Type, SubtractDate32>::Exec;
  DCHECK_OK(subtract->AddKernel({in_type_date_32, in_type_date_32},
                                duration(TimeUnit::SECOND), std::move(exec_date_32)));

  // Add subtract(date64, date64) -> duration(TimeUnit::MILLI)
  InputType in_type_date_64(date64());
  auto exec_date_64 = ScalarBinaryEqualTypes<Int64Type, Int64Type, Subtract>::Exec;
  DCHECK_OK(subtract->AddKernel({in_type_date_64, in_type_date_64},
                                duration(TimeUnit::MILLI), std::move(exec_date_64)));

  AddArithmeticFunctionTimeDuration<SubtractTimeDuration>(subtract);

  DCHECK_OK(registry->AddFunction(std::move(subtract)));

  // ----------------------------------------------------------------------
  auto subtract_checked =
      MakeArithmeticFunctionNotNull<SubtractChecked>("subtract_checked", sub_checked_doc);
  AddDecimalBinaryKernels<SubtractChecked>("subtract_checked", subtract_checked.get());

  // Add subtract_checked(timestamp, timestamp) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec =
        ArithmeticExecFromOp<ScalarBinaryEqualTypes, SubtractChecked>(Type::TIMESTAMP);
    DCHECK_OK(subtract_checked->AddKernel({in_type, in_type},
                                          OutputType::Resolver(ResolveTemporalOutput),
                                          std::move(exec)));
  }

  // Add subtract_checked(timestamp, duration) -> timestamp
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::TimestampTypeUnit(unit));
    auto exec = ScalarBinary<Int64Type, Int64Type, Int64Type, SubtractChecked>::Exec;
    DCHECK_OK(subtract_checked->AddKernel({in_type, duration(unit)},
                                          OutputType(FirstType), std::move(exec)));
  }

  // Add subtract_checked(duration, duration) -> duration
  for (auto unit : TimeUnit::values()) {
    InputType in_type(match::DurationTypeUnit(unit));
    auto exec =
        ArithmeticExecFromOp<ScalarBinaryEqualTypes, SubtractChecked>(Type::DURATION);
    DCHECK_OK(
        subtract_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  // Add subtract_checked(date32, date32) -> duration(TimeUnit::SECOND)
  auto exec_date_32_checked =
      ScalarBinaryEqualTypes<Int64Type, Int32Type, SubtractCheckedDate32>::Exec;
  DCHECK_OK(subtract_checked->AddKernel({in_type_date_32, in_type_date_32},
                                        duration(TimeUnit::SECOND),
                                        std::move(exec_date_32_checked)));

  // Add subtract_checked(date64, date64) -> duration(TimeUnit::MILLI)
  auto exec_date_64_checked =
      ScalarBinaryEqualTypes<Int64Type, Int64Type, SubtractChecked>::Exec;
  DCHECK_OK(subtract_checked->AddKernel({in_type_date_64, in_type_date_64},
                                        duration(TimeUnit::MILLI),
                                        std::move(exec_date_64_checked)));

  // Add subtract_checked(time32, time32) -> duration
  for (auto unit : {TimeUnit::SECOND, TimeUnit::MILLI}) {
    InputType in_type(match::Time32TypeUnit(unit));
    auto exec = ScalarBinaryEqualTypes<Int64Type, Int32Type, SubtractChecked>::Exec;
    DCHECK_OK(
        subtract_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  // Add subtract_checked(time64, time64) -> duration
  for (auto unit : {TimeUnit::MICRO, TimeUnit::NANO}) {
    InputType in_type(match::Time64TypeUnit(unit));
    auto exec = ScalarBinaryEqualTypes<Int64Type, Int64Type, SubtractChecked>::Exec;
    DCHECK_OK(
        subtract_checked->AddKernel({in_type, in_type}, duration(unit), std::move(exec)));
  }

  AddArithmeticFunctionTimeDuration<SubtractTimeDurationChecked>(subtract_checked);

  DCHECK_OK(registry->AddFunction(std::move(subtract_checked)));

  // ----------------------------------------------------------------------
  auto multiply = MakeArithmeticFunction<Multiply>("multiply", mul_doc);
  AddDecimalBinaryKernels<Multiply>("multiply", multiply.get());

  // Add multiply(duration, int64) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec = ArithmeticExecFromOp<ScalarBinaryEqualTypes, Multiply>(Type::DURATION);
    DCHECK_OK(multiply->AddKernel({duration(unit), int64()}, duration(unit), exec));
    DCHECK_OK(multiply->AddKernel({int64(), duration(unit)}, duration(unit), exec));
  }

  DCHECK_OK(registry->AddFunction(std::move(multiply)));

  // ----------------------------------------------------------------------
  auto multiply_checked =
      MakeArithmeticFunctionNotNull<MultiplyChecked>("multiply_checked", mul_checked_doc);
  AddDecimalBinaryKernels<MultiplyChecked>("multiply_checked", multiply_checked.get());

  // Add multiply_checked(duration, int64) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec =
        ArithmeticExecFromOp<ScalarBinaryEqualTypes, MultiplyChecked>(Type::DURATION);
    DCHECK_OK(
        multiply_checked->AddKernel({duration(unit), int64()}, duration(unit), exec));
    DCHECK_OK(
        multiply_checked->AddKernel({int64(), duration(unit)}, duration(unit), exec));
  }

  DCHECK_OK(registry->AddFunction(std::move(multiply_checked)));

  // ----------------------------------------------------------------------
  auto divide = MakeArithmeticFunctionNotNull<Divide>("divide", div_doc);
  AddDecimalBinaryKernels<Divide>("divide", divide.get());

  // Add divide(duration, int64) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec = ScalarBinaryNotNull<Int64Type, Int64Type, Int64Type, Divide>::Exec;
    DCHECK_OK(
        divide->AddKernel({duration(unit), int64()}, duration(unit), std::move(exec)));
  }

  // Add divide(duration, duration) -> float64
  for (auto unit : TimeUnit::values()) {
    auto exec =
        ScalarBinaryNotNull<DoubleType, Int64Type, Int64Type, FloatingDivide>::Exec;
    DCHECK_OK(
        divide->AddKernel({duration(unit), duration(unit)}, float64(), std::move(exec)));
  }
  DCHECK_OK(registry->AddFunction(std::move(divide)));

  // ----------------------------------------------------------------------
  auto divide_checked =
      MakeArithmeticFunctionNotNull<DivideChecked>("divide_checked", div_checked_doc);
  AddDecimalBinaryKernels<DivideChecked>("divide_checked", divide_checked.get());

  // Add divide_checked(duration, int64) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec = ScalarBinaryNotNull<Int64Type, Int64Type, Int64Type, DivideChecked>::Exec;
    DCHECK_OK(divide_checked->AddKernel({duration(unit), int64()}, duration(unit),
                                        std::move(exec)));
  }

  // Add divide_checked(duration, duration) -> float64
  for (auto unit : TimeUnit::values()) {
    auto exec = ScalarBinaryNotNull<DoubleType, Int64Type, Int64Type,
                                    FloatingDivideChecked>::Exec;
    DCHECK_OK(divide_checked->AddKernel({duration(unit), duration(unit)}, float64(),
                                        std::move(exec)));
  }

  DCHECK_OK(registry->AddFunction(std::move(divide_checked)));

  // ----------------------------------------------------------------------
  auto negate = MakeUnaryArithmeticFunction<Negate>("negate", negate_doc);
  AddDecimalUnaryKernels<Negate>(negate.get());

  // Add neg(duration) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec = ArithmeticExecFromOp<ScalarUnary, Negate>(duration(unit));
    DCHECK_OK(negate->AddKernel({duration(unit)}, OutputType(duration(unit)), exec));
  }

  DCHECK_OK(registry->AddFunction(std::move(negate)));

  // ----------------------------------------------------------------------
  auto negate_checked = MakeUnarySignedArithmeticFunctionNotNull<NegateChecked>(
      "negate_checked", negate_checked_doc);
  AddDecimalUnaryKernels<NegateChecked>(negate_checked.get());

  // Add neg_checked(duration) -> duration
  for (auto unit : TimeUnit::values()) {
    auto exec = ArithmeticExecFromOp<ScalarUnaryNotNull, Negate>(duration(unit));
    DCHECK_OK(
        negate_checked->AddKernel({duration(unit)}, OutputType(duration(unit)), exec));
  }

  DCHECK_OK(registry->AddFunction(std::move(negate_checked)));

  // ----------------------------------------------------------------------
  auto power = MakeArithmeticFunction<Power, ArithmeticDecimalToFloatingPointFunction>(
      "power", pow_doc);
  DCHECK_OK(registry->AddFunction(std::move(power)));

  // ----------------------------------------------------------------------
  auto power_checked =
      MakeArithmeticFunctionNotNull<PowerChecked,
                                    ArithmeticDecimalToFloatingPointFunction>(
          "power_checked", pow_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(power_checked)));

  // ----------------------------------------------------------------------
  auto exp = MakeUnaryArithmeticFunctionFloatingPoint<Exp>("exp", exp_doc);
  DCHECK_OK(registry->AddFunction(std::move(exp)));

  // ----------------------------------------------------------------------
  auto expm1 = MakeUnaryArithmeticFunctionFloatingPoint<Expm1>("expm1", expm1_doc);
  DCHECK_OK(registry->AddFunction(std::move(expm1)));

  // ----------------------------------------------------------------------
  auto sqrt = MakeUnaryArithmeticFunctionFloatingPoint<SquareRoot>("sqrt", sqrt_doc);
  DCHECK_OK(registry->AddFunction(std::move(sqrt)));

  // ----------------------------------------------------------------------
  auto sqrt_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<SquareRootChecked>(
      "sqrt_checked", sqrt_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(sqrt_checked)));

  // ----------------------------------------------------------------------
  auto sign =
      MakeUnaryArithmeticFunctionWithFixedIntOutType<Sign, Int8Type>("sign", sign_doc);
  // sign(duration)
  for (auto unit : TimeUnit::values()) {
    auto exec = ScalarUnary<Int8Type, Int64Type, Sign>::Exec;
    DCHECK_OK(sign->AddKernel({duration(unit)}, int8(), std::move(exec)));
  }
  DCHECK_OK(registry->AddFunction(std::move(sign)));

  // ----------------------------------------------------------------------
  // Bitwise functions
  {
    auto bit_wise_not = std::make_shared<ArithmeticFunction>(
        "bit_wise_not", Arity::Unary(), bit_wise_not_doc);
    for (const auto& ty : IntTypes()) {
      auto exec = TypeAgnosticBitWiseExecFromOp<ScalarUnaryNotNull, BitWiseNot>(ty);
      DCHECK_OK(bit_wise_not->AddKernel({ty}, ty, exec));
    }
    AddNullExec(bit_wise_not.get());
    DCHECK_OK(registry->AddFunction(std::move(bit_wise_not)));
  }

  auto bit_wise_and =
      MakeBitWiseFunctionNotNull<BitWiseAnd>("bit_wise_and", bit_wise_and_doc);
  DCHECK_OK(registry->AddFunction(std::move(bit_wise_and)));

  auto bit_wise_or =
      MakeBitWiseFunctionNotNull<BitWiseOr>("bit_wise_or", bit_wise_or_doc);
  DCHECK_OK(registry->AddFunction(std::move(bit_wise_or)));

  auto bit_wise_xor =
      MakeBitWiseFunctionNotNull<BitWiseXor>("bit_wise_xor", bit_wise_xor_doc);
  DCHECK_OK(registry->AddFunction(std::move(bit_wise_xor)));

  auto shift_left = MakeShiftFunctionNotNull<ShiftLeft>("shift_left", shift_left_doc);
  DCHECK_OK(registry->AddFunction(std::move(shift_left)));

  auto shift_left_checked = MakeShiftFunctionNotNull<ShiftLeftChecked>(
      "shift_left_checked", shift_left_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(shift_left_checked)));

  auto shift_right = MakeShiftFunctionNotNull<ShiftRight>("shift_right", shift_right_doc);
  DCHECK_OK(registry->AddFunction(std::move(shift_right)));

  auto shift_right_checked = MakeShiftFunctionNotNull<ShiftRightChecked>(
      "shift_right_checked", shift_right_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(shift_right_checked)));

  // ----------------------------------------------------------------------
  // Trig functions
  auto sin = MakeUnaryArithmeticFunctionFloatingPoint<Sin>("sin", sin_doc);
  DCHECK_OK(registry->AddFunction(std::move(sin)));

  auto sin_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<SinChecked>(
      "sin_checked", sin_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(sin_checked)));

  auto sinh = MakeUnaryArithmeticFunctionFloatingPoint<Sinh>("sinh", sinh_doc);
  DCHECK_OK(registry->AddFunction(std::move(sinh)));

  auto cos = MakeUnaryArithmeticFunctionFloatingPoint<Cos>("cos", cos_doc);
  DCHECK_OK(registry->AddFunction(std::move(cos)));

  auto cos_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<CosChecked>(
      "cos_checked", cos_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(cos_checked)));

  auto cosh = MakeUnaryArithmeticFunctionFloatingPoint<Cosh>("cosh", cosh_doc);
  DCHECK_OK(registry->AddFunction(std::move(cosh)));

  auto tan = MakeUnaryArithmeticFunctionFloatingPoint<Tan>("tan", tan_doc);
  DCHECK_OK(registry->AddFunction(std::move(tan)));

  auto tan_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<TanChecked>(
      "tan_checked", tan_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(tan_checked)));

  auto tanh = MakeUnaryArithmeticFunctionFloatingPoint<Tanh>("tanh", tanh_doc);
  DCHECK_OK(registry->AddFunction(std::move(tanh)));

  auto asin = MakeUnaryArithmeticFunctionFloatingPoint<Asin>("asin", asin_doc);
  DCHECK_OK(registry->AddFunction(std::move(asin)));

  auto asin_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<AsinChecked>(
      "asin_checked", asin_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(asin_checked)));

  auto asinh = MakeUnaryArithmeticFunctionFloatingPoint<Asinh>("asinh", asinh_doc);
  DCHECK_OK(registry->AddFunction(std::move(asinh)));

  auto acos = MakeUnaryArithmeticFunctionFloatingPoint<Acos>("acos", acos_doc);
  DCHECK_OK(registry->AddFunction(std::move(acos)));

  auto acos_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<AcosChecked>(
      "acos_checked", acos_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(acos_checked)));

  auto acosh = MakeUnaryArithmeticFunctionFloatingPoint<Acosh>("acosh", acosh_doc);
  DCHECK_OK(registry->AddFunction(std::move(acosh)));

  auto acosh_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<AcoshChecked>(
      "acosh_checked", acosh_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(acosh_checked)));

  auto atan = MakeUnaryArithmeticFunctionFloatingPoint<Atan>("atan", atan_doc);
  DCHECK_OK(registry->AddFunction(std::move(atan)));

  auto atan2 = MakeArithmeticFunctionFloatingPoint<Atan2>("atan2", atan2_doc);
  DCHECK_OK(registry->AddFunction(std::move(atan2)));

  auto atanh = MakeUnaryArithmeticFunctionFloatingPoint<Atanh>("atanh", atanh_doc);
  DCHECK_OK(registry->AddFunction(std::move(atanh)));

  auto atanh_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<AtanhChecked>(
      "atanh_checked", atanh_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(atanh_checked)));

  // ----------------------------------------------------------------------
  // Logarithms
  auto ln = MakeUnaryArithmeticFunctionFloatingPoint<LogNatural>("ln", ln_doc);
  DCHECK_OK(registry->AddFunction(std::move(ln)));

  auto ln_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<LogNaturalChecked>(
      "ln_checked", ln_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(ln_checked)));

  auto log10 = MakeUnaryArithmeticFunctionFloatingPoint<Log10>("log10", log10_doc);
  DCHECK_OK(registry->AddFunction(std::move(log10)));

  auto log10_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<Log10Checked>(
      "log10_checked", log10_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(log10_checked)));

  auto log2 = MakeUnaryArithmeticFunctionFloatingPoint<Log2>("log2", log2_doc);
  DCHECK_OK(registry->AddFunction(std::move(log2)));

  auto log2_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<Log2Checked>(
      "log2_checked", log2_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(log2_checked)));

  auto log1p = MakeUnaryArithmeticFunctionFloatingPoint<Log1p>("log1p", log1p_doc);
  DCHECK_OK(registry->AddFunction(std::move(log1p)));

  auto log1p_checked = MakeUnaryArithmeticFunctionFloatingPointNotNull<Log1pChecked>(
      "log1p_checked", log1p_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(log1p_checked)));

  auto logb = MakeArithmeticFunctionFloatingPoint<Logb>("logb", logb_doc);
  DCHECK_OK(registry->AddFunction(std::move(logb)));

  auto logb_checked = MakeArithmeticFunctionFloatingPointNotNull<LogbChecked>(
      "logb_checked", logb_checked_doc);
  DCHECK_OK(registry->AddFunction(std::move(logb_checked)));
}