ClickHouse/src/Functions/vectorFunctions.cpp

681 lines
27 KiB
C++
Raw Normal View History

#include <Columns/ColumnTuple.h>
#include <DataTypes/DataTypeTuple.h>
#include <DataTypes/DataTypesNumber.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/TupleIFunction.h>
#include <Functions/castTypeToEither.h>
namespace DB
{
namespace ErrorCodes
{
2021-08-20 21:14:26 +00:00
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
2021-08-25 14:56:31 +00:00
template <const char * func_name>
class TuplesToTupleFunction : public TupleIFunction {
public:
explicit TuplesToTupleFunction(ContextPtr context_) : TupleIFunction(context_) {}
size_t getNumberOfArguments() const override { return 2; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
const auto * left_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto * right_tuple = checkAndGetDataType<DataTypeTuple>(arguments[1].type.get());
if (!left_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
if (!right_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 1 of function {} should be tuples, got {}",
getName(), arguments[1].type->getName());
const auto & left_types = left_tuple->getElements();
const auto & right_types = right_tuple->getElements();
Columns left_elements;
Columns right_elements;
if (arguments[0].column)
left_elements = getTupleElements(*arguments[0].column);
if (arguments[1].column)
right_elements = getTupleElements(*arguments[1].column);
if (left_types.size() != right_types.size())
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Expected tuples of the same size as arguments of function {}. Got {} and {}",
getName(), arguments[0].type->getName(), arguments[1].type->getName());
size_t tuple_size = left_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
auto func = FunctionFactory::instance().get(func_name, context);
DataTypes types(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
ColumnWithTypeAndName left{left_elements.empty() ? nullptr : left_elements[i], left_types[i], {}};
ColumnWithTypeAndName right{right_elements.empty() ? nullptr : right_elements[i], right_types[i], {}};
auto elem_func = func->build(ColumnsWithTypeAndName{left, right});
types[i] = elem_func->getResultType();
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
return std::make_shared<DataTypeTuple>(types);
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * left_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto * right_tuple = checkAndGetDataType<DataTypeTuple>(arguments[1].type.get());
const auto & left_types = left_tuple->getElements();
const auto & right_types = right_tuple->getElements();
auto left_elements = getTupleElements(*arguments[0].column);
auto right_elements = getTupleElements(*arguments[1].column);
size_t tuple_size = left_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
auto func = FunctionFactory::instance().get(func_name, context);
Columns columns(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
{
ColumnWithTypeAndName left{left_elements[i], left_types[i], {}};
ColumnWithTypeAndName right{right_elements[i], right_types[i], {}};
auto elem_func = func->build(ColumnsWithTypeAndName{left, right});
columns[i] = elem_func->execute({left, right}, elem_func->getResultType(), input_rows_count);
}
return ColumnTuple::create(columns);
}
};
2021-08-25 14:02:04 +00:00
static const char PLUS_NAME[] = "plus";
class FunctionTuplePlus : public TuplesToTupleFunction<PLUS_NAME>
{
public:
static constexpr auto name = "tuplePlus";
2021-08-25 14:02:04 +00:00
explicit FunctionTuplePlus(ContextPtr context_) : TuplesToTupleFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionTuplePlus>(context_); }
String getName() const override { return name; }
};
2021-08-25 14:02:04 +00:00
static const char MINUS_NAME[] = "minus";
class FunctionTupleMinus : public TuplesToTupleFunction<MINUS_NAME>
{
public:
static constexpr auto name = "tupleMinus";
2021-08-25 14:02:04 +00:00
explicit FunctionTupleMinus(ContextPtr context_) : TuplesToTupleFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionTupleMinus>(context_); }
String getName() const override { return name; }
2021-08-25 14:02:04 +00:00
};
2021-08-25 14:02:04 +00:00
static const char MULTIPLY_NAME[] = "multiply";
class FunctionTupleMultiply : public TuplesToTupleFunction<MULTIPLY_NAME>
{
public:
static constexpr auto name = "tupleMultiply";
2021-08-25 14:02:04 +00:00
explicit FunctionTupleMultiply(ContextPtr context_) : TuplesToTupleFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionTupleMultiply>(context_); }
2021-08-25 14:02:04 +00:00
String getName() const override { return name; }
};
2021-08-25 14:02:04 +00:00
static const char DIVIDE_NAME[] = "divide";
class FunctionTupleDivide : public TuplesToTupleFunction<DIVIDE_NAME>
{
public:
static constexpr auto name = "tupleDivide";
2021-08-25 14:02:04 +00:00
explicit FunctionTupleDivide(ContextPtr context_) : TuplesToTupleFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionTupleDivide>(context_); }
2021-08-25 14:02:04 +00:00
String getName() const override { return name; }
};
2021-08-25 14:02:04 +00:00
class FunctionTupleNegate : public TupleIFunction
{
public:
2021-08-25 14:02:04 +00:00
static constexpr auto name = "tupleNegate";
2021-08-25 14:02:04 +00:00
explicit FunctionTupleNegate(ContextPtr context_) : TupleIFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionTupleNegate>(context_); }
String getName() const override { return name; }
2021-08-25 14:02:04 +00:00
size_t getNumberOfArguments() const override { return 1; }
2021-08-20 16:23:51 +00:00
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
2021-08-25 14:02:04 +00:00
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
2021-08-25 14:02:04 +00:00
if (!cur_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
2021-08-25 14:02:04 +00:00
const auto & cur_types = cur_tuple->getElements();
2021-08-25 14:02:04 +00:00
Columns cur_elements;
if (arguments[0].column)
2021-08-25 14:02:04 +00:00
cur_elements = getTupleElements(*arguments[0].column);
2021-08-25 14:02:04 +00:00
size_t tuple_size = cur_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
2021-08-25 14:02:04 +00:00
auto negate = FunctionFactory::instance().get("negate", context);
DataTypes types(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
2021-08-25 14:02:04 +00:00
ColumnWithTypeAndName cur{cur_elements.empty() ? nullptr : cur_elements[i], cur_types[i], {}};
auto elem_negate = negate->build(ColumnsWithTypeAndName{cur});
types[i] = elem_negate->getResultType();
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
return std::make_shared<DataTypeTuple>(types);
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
2021-08-25 14:02:04 +00:00
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto & cur_types = cur_tuple->getElements();
auto cur_elements = getTupleElements(*arguments[0].column);
2021-08-25 14:02:04 +00:00
size_t tuple_size = cur_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
2021-08-25 14:02:04 +00:00
auto negate = FunctionFactory::instance().get("negate", context);
Columns columns(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
{
2021-08-25 14:02:04 +00:00
ColumnWithTypeAndName cur{cur_elements[i], cur_types[i], {}};
auto elem_negate= negate->build(ColumnsWithTypeAndName{cur});
columns[i] = elem_negate->execute({cur}, elem_negate->getResultType(), input_rows_count);
}
return ColumnTuple::create(columns);
}
};
2021-08-25 14:02:04 +00:00
class FunctionDotProduct : public TupleIFunction
2021-08-23 13:41:20 +00:00
{
public:
2021-08-25 14:02:04 +00:00
static constexpr auto name = "dotProduct";
2021-08-23 13:41:20 +00:00
2021-08-25 14:02:04 +00:00
explicit FunctionDotProduct(ContextPtr context_) : TupleIFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionDotProduct>(context_); }
2021-08-23 13:41:20 +00:00
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 2; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
const auto * left_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto * right_tuple = checkAndGetDataType<DataTypeTuple>(arguments[1].type.get());
if (!left_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
if (!right_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 1 of function {} should be tuples, got {}",
getName(), arguments[1].type->getName());
const auto & left_types = left_tuple->getElements();
const auto & right_types = right_tuple->getElements();
Columns left_elements;
Columns right_elements;
if (arguments[0].column)
left_elements = getTupleElements(*arguments[0].column);
if (arguments[1].column)
right_elements = getTupleElements(*arguments[1].column);
if (left_types.size() != right_types.size())
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Expected tuples of the same size as arguments of function {}. Got {} and {}",
getName(), arguments[0].type->getName(), arguments[1].type->getName());
size_t tuple_size = left_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
2021-08-25 14:02:04 +00:00
auto multiply = FunctionFactory::instance().get("multiply", context);
auto plus = FunctionFactory::instance().get("plus", context);
DataTypePtr res_type;
2021-08-23 13:41:20 +00:00
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
ColumnWithTypeAndName left{left_elements.empty() ? nullptr : left_elements[i], left_types[i], {}};
ColumnWithTypeAndName right{right_elements.empty() ? nullptr : right_elements[i], right_types[i], {}};
2021-08-25 14:02:04 +00:00
auto elem_multiply = multiply->build(ColumnsWithTypeAndName{left, right});
if (i == 0)
{
res_type = elem_multiply->getResultType();
continue;
}
ColumnWithTypeAndName left_type{res_type, {}};
ColumnWithTypeAndName right_type{elem_multiply->getResultType(), {}};
auto plus_elem = plus->build({left_type, right_type});
res_type = plus_elem->getResultType();
2021-08-23 13:41:20 +00:00
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
2021-08-25 14:02:04 +00:00
return res_type;
2021-08-23 13:41:20 +00:00
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * left_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto * right_tuple = checkAndGetDataType<DataTypeTuple>(arguments[1].type.get());
const auto & left_types = left_tuple->getElements();
const auto & right_types = right_tuple->getElements();
auto left_elements = getTupleElements(*arguments[0].column);
auto right_elements = getTupleElements(*arguments[1].column);
size_t tuple_size = left_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
2021-08-25 14:02:04 +00:00
auto multiply = FunctionFactory::instance().get("multiply", context);
auto plus = FunctionFactory::instance().get("plus", context);
ColumnWithTypeAndName res;
2021-08-23 13:41:20 +00:00
for (size_t i = 0; i < tuple_size; ++i)
{
ColumnWithTypeAndName left{left_elements[i], left_types[i], {}};
ColumnWithTypeAndName right{right_elements[i], right_types[i], {}};
2021-08-25 14:02:04 +00:00
auto elem_multiply = multiply->build(ColumnsWithTypeAndName{left, right});
2021-08-23 13:41:20 +00:00
2021-08-25 14:02:04 +00:00
ColumnWithTypeAndName column;
column.type = elem_multiply->getResultType();
column.column = elem_multiply->execute({left, right}, column.type, input_rows_count);
2021-08-23 13:41:20 +00:00
2021-08-25 14:02:04 +00:00
if (i == 0)
2021-08-23 13:41:20 +00:00
{
2021-08-25 14:02:04 +00:00
res = std::move(column);
2021-08-23 13:41:20 +00:00
}
2021-08-25 14:02:04 +00:00
else
2021-08-23 13:41:20 +00:00
{
2021-08-25 14:02:04 +00:00
auto plus_elem = plus->build({res, column});
auto res_type = plus_elem->getResultType();
res.column = plus_elem->execute({res, column}, res_type, input_rows_count);
res.type = res_type;
2021-08-23 13:41:20 +00:00
}
}
2021-08-25 14:02:04 +00:00
return res.column;
2021-08-23 13:41:20 +00:00
}
};
2021-08-25 14:56:31 +00:00
class FunctionL1Norm : public TupleIFunction
{
public:
static constexpr auto name = "L1Norm";
explicit FunctionL1Norm(ContextPtr context_) : TupleIFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionL1Norm>(context_); }
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 1; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
if (!cur_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
const auto & cur_types = cur_tuple->getElements();
Columns cur_elements;
if (arguments[0].column)
cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
auto abs = FunctionFactory::instance().get("abs", context);
auto plus = FunctionFactory::instance().get("plus", context);
DataTypePtr res_type;
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
ColumnWithTypeAndName cur{cur_elements.empty() ? nullptr : cur_elements[i], cur_types[i], {}};
auto elem_abs = abs->build(ColumnsWithTypeAndName{cur});
if (i == 0)
{
res_type = elem_abs->getResultType();
continue;
}
ColumnWithTypeAndName left_type{res_type, {}};
ColumnWithTypeAndName right_type{elem_abs->getResultType(), {}};
auto plus_elem = plus->build({left_type, right_type});
res_type = plus_elem->getResultType();
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
return res_type;
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto & cur_types = cur_tuple->getElements();
auto cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
auto abs = FunctionFactory::instance().get("abs", context);
auto plus = FunctionFactory::instance().get("plus", context);
ColumnWithTypeAndName res;
for (size_t i = 0; i < tuple_size; ++i)
{
ColumnWithTypeAndName cur{cur_elements[i], cur_types[i], {}};
auto elem_abs = abs->build(ColumnsWithTypeAndName{cur});
ColumnWithTypeAndName column;
column.type = elem_abs->getResultType();
column.column = elem_abs->execute({cur}, column.type, input_rows_count);
if (i == 0)
{
res = std::move(column);
}
else
{
auto plus_elem = plus->build({res, column});
auto res_type = plus_elem->getResultType();
res.column = plus_elem->execute({res, column}, res_type, input_rows_count);
res.type = res_type;
}
}
return res.column;
}
};
2021-08-25 15:44:35 +00:00
class FunctionL2Norm : public TupleIFunction
{
public:
static constexpr auto name = "L2Norm";
explicit FunctionL2Norm(ContextPtr context_) : TupleIFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionL2Norm>(context_); }
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 1; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
if (!cur_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
const auto & cur_types = cur_tuple->getElements();
Columns cur_elements;
if (arguments[0].column)
cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
auto multiply = FunctionFactory::instance().get("multiply", context);
auto plus = FunctionFactory::instance().get("plus", context);
DataTypePtr res_type;
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
ColumnWithTypeAndName cur{cur_elements.empty() ? nullptr : cur_elements[i], cur_types[i], {}};
auto elem_multiply = multiply->build(ColumnsWithTypeAndName{cur, cur});
if (i == 0)
{
res_type = elem_multiply->getResultType();
continue;
}
ColumnWithTypeAndName left_type{res_type, {}};
ColumnWithTypeAndName right_type{elem_multiply->getResultType(), {}};
auto plus_elem = plus->build({left_type, right_type});
res_type = plus_elem->getResultType();
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
auto sqrt = FunctionFactory::instance().get("sqrt", context);
return sqrt->build({ColumnWithTypeAndName{res_type, {}}})->getResultType();
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto & cur_types = cur_tuple->getElements();
auto cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
auto multiply = FunctionFactory::instance().get("multiply", context);
auto plus = FunctionFactory::instance().get("plus", context);
ColumnWithTypeAndName res;
for (size_t i = 0; i < tuple_size; ++i)
{
ColumnWithTypeAndName cur{cur_elements[i], cur_types[i], {}};
auto elem_multiply = multiply->build(ColumnsWithTypeAndName{cur, cur});
ColumnWithTypeAndName column;
column.type = elem_multiply->getResultType();
column.column = elem_multiply->execute({cur, cur}, column.type, input_rows_count);
if (i == 0)
{
res = std::move(column);
}
else
{
auto plus_elem = plus->build({res, column});
auto res_type = plus_elem->getResultType();
res.column = plus_elem->execute({res, column}, res_type, input_rows_count);
res.type = res_type;
}
}
auto sqrt = FunctionFactory::instance().get("sqrt", context);
auto sqrt_elem = sqrt->build({res});
return sqrt_elem->execute({res}, sqrt_elem->getResultType(), input_rows_count);
}
};
2021-08-26 12:34:46 +00:00
class FunctionLinfNorm : public TupleIFunction
{
public:
static constexpr auto name = "LinfNorm";
explicit FunctionLinfNorm(ContextPtr context_) : TupleIFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionLinfNorm>(context_); }
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 1; }
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
if (!cur_tuple)
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Argument 0 of function {} should be tuples, got {}",
getName(), arguments[0].type->getName());
const auto & cur_types = cur_tuple->getElements();
Columns cur_elements;
if (arguments[0].column)
cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_types.size();
if (tuple_size == 0)
return std::make_shared<DataTypeUInt8>();
auto abs = FunctionFactory::instance().get("abs", context);
auto max = FunctionFactory::instance().get("max2", context);
DataTypePtr res_type;
for (size_t i = 0; i < tuple_size; ++i)
{
try
{
ColumnWithTypeAndName cur{cur_elements.empty() ? nullptr : cur_elements[i], cur_types[i], {}};
auto elem_abs = abs->build(ColumnsWithTypeAndName{cur});
if (i == 0)
{
res_type = elem_abs->getResultType();
continue;
}
ColumnWithTypeAndName left_type{res_type, {}};
ColumnWithTypeAndName right_type{elem_abs->getResultType(), {}};
auto max_elem = max->build({left_type, right_type});
res_type = max_elem->getResultType();
}
catch (DB::Exception & e)
{
e.addMessage("While executing function {} for tuple element {}", getName(), i);
throw;
}
}
return res_type;
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
{
const auto * cur_tuple = checkAndGetDataType<DataTypeTuple>(arguments[0].type.get());
const auto & cur_types = cur_tuple->getElements();
auto cur_elements = getTupleElements(*arguments[0].column);
size_t tuple_size = cur_elements.size();
if (tuple_size == 0)
return DataTypeUInt8().createColumnConstWithDefaultValue(input_rows_count);
auto abs = FunctionFactory::instance().get("abs", context);
auto max = FunctionFactory::instance().get("max2", context);
ColumnWithTypeAndName res;
for (size_t i = 0; i < tuple_size; ++i)
{
ColumnWithTypeAndName cur{cur_elements[i], cur_types[i], {}};
auto elem_abs = abs->build(ColumnsWithTypeAndName{cur});
ColumnWithTypeAndName column;
column.type = elem_abs->getResultType();
column.column = elem_abs->execute({cur}, column.type, input_rows_count);
if (i == 0)
{
res = std::move(column);
}
else
{
auto max_elem = max->build({res, column});
auto res_type = max_elem->getResultType();
res.column = max_elem->execute({res, column}, res_type, input_rows_count);
res.type = res_type;
}
}
return res.column;
}
};
void registerVectorFunctions(FunctionFactory & factory)
{
factory.registerFunction<FunctionTuplePlus>();
factory.registerAlias("vectorSum", FunctionTuplePlus::name, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTupleMinus>();
factory.registerAlias("vectorDifference", FunctionTupleMinus::name, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTupleMultiply>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionTupleDivide>();
factory.registerFunction<FunctionTupleNegate>();
2021-08-25 14:02:04 +00:00
//factory.registerFunction<FunctionTupleMultiplyByNumber>();
//factory.registerFunction<FunctionTupleDivideByNumber>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionDotProduct>();
factory.registerAlias("scalarProduct", FunctionDotProduct::name, FunctionFactory::CaseInsensitive);
2021-08-25 14:56:31 +00:00
factory.registerFunction<FunctionL1Norm>();
2021-08-25 15:44:35 +00:00
factory.registerFunction<FunctionL2Norm>();
2021-08-26 12:34:46 +00:00
factory.registerFunction<FunctionLinfNorm>();
2021-08-25 14:56:31 +00:00
/*factory.registerFunction<FunctionL1Distance>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionL1Normalize>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionL2Distance>();
factory.registerFunction<FunctionL2Normalize>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionLinfDistance>();
factory.registerFunction<FunctionLinfNormalize>();
factory.registerFunction<FunctionLpNorm>();
2021-08-23 13:41:20 +00:00
factory.registerFunction<FunctionLpDistance>();
factory.registerFunction<FunctionLpNormalize>();
factory.registerFunction<FunctionCosineDistance>();*/
}
}