Implement L2Squared Distance and Norm

This commit is contained in:
Julian Gilyadov 2022-06-28 15:27:53 -04:00
parent 75b8800b5c
commit d0d72e0b5e
No known key found for this signature in database
GPG Key ID: B47E3757FB40EF94
9 changed files with 251 additions and 46 deletions

View File

@ -70,6 +70,33 @@ struct L2Distance
}
};
struct L2SquaredDistance
{
static inline String name = "L2Squared";
struct ConstParams
{
};
template <typename FloatType>
struct State
{
FloatType sum = 0;
};
template <typename ResultType>
static void accumulate(State<ResultType> & state, ResultType x, ResultType y, const ConstParams &)
{
state.sum += (x - y) * (x - y);
}
template <typename ResultType>
static ResultType finalize(const State<ResultType> & state, const ConstParams &)
{
return state.sum;
}
};
struct LpDistance
{
static inline String name = "Lp";
@ -195,12 +222,12 @@ public:
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Arguments of function {} has nested type {}. "
"Support: UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, Float32, Float64.",
getName(), common_type->getName());
getName(),
common_type->getName());
}
}
ColumnPtr
executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
switch (result_type->getTypeId())
{
@ -248,7 +275,8 @@ private:
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Arguments of function {} has nested type {}. "
"Support: UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, Float32, Float64.",
getName(), type_x->getName());
getName(),
type_x->getName());
}
}
@ -273,7 +301,8 @@ private:
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Arguments of function {} has nested type {}. "
"Support: UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, Float32, Float64.",
getName(), type_y->getName());
getName(),
type_y->getName());
}
}
@ -310,7 +339,9 @@ private:
throw Exception(
ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH,
"Arguments of function {} have different array sizes: {} and {}",
getName(), offsets_x[row] - prev_offset, offsets_y[row] - prev_offset);
getName(),
offsets_x[row] - prev_offset,
offsets_y[row] - prev_offset);
}
}
@ -360,7 +391,9 @@ private:
throw Exception(
ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH,
"Arguments of function {} have different array sizes: {} and {}",
getName(), offsets_x[0], offsets_y[row] - prev_offset);
getName(),
offsets_x[0],
offsets_y[row] - prev_offset);
}
prev_offset = offsets_y[row];
}
@ -430,8 +463,8 @@ LpDistance::ConstParams FunctionArrayDistance<LpDistance>::initConstParams(const
/// These functions are used by TupleOrArrayFunction
FunctionPtr createFunctionArrayL1Distance(ContextPtr context_) { return FunctionArrayDistance<L1Distance>::create(context_); }
FunctionPtr createFunctionArrayL2Distance(ContextPtr context_) { return FunctionArrayDistance<L2Distance>::create(context_); }
FunctionPtr createFunctionArrayL2SquaredDistance(ContextPtr context_) { return FunctionArrayDistance<L2SquaredDistance>::create(context_); }
FunctionPtr createFunctionArrayLpDistance(ContextPtr context_) { return FunctionArrayDistance<LpDistance>::create(context_); }
FunctionPtr createFunctionArrayLinfDistance(ContextPtr context_) { return FunctionArrayDistance<LinfDistance>::create(context_); }
FunctionPtr createFunctionArrayCosineDistance(ContextPtr context_) { return FunctionArrayDistance<CosineDistance>::create(context_); }
}

View File

@ -57,6 +57,25 @@ struct L2Norm
}
};
struct L2SquaredNorm
{
static inline String name = "L2Squared";
struct ConstParams {};
template <typename ResultType>
inline static ResultType accumulate(ResultType result, ResultType value, const ConstParams &)
{
return result + value * value;
}
template <typename ResultType>
inline static ResultType finalize(ResultType result, const ConstParams &)
{
return result;
}
};
struct LpNorm
{
@ -265,6 +284,7 @@ LpNorm::ConstParams FunctionArrayNorm<LpNorm>::initConstParams(const ColumnsWith
/// These functions are used by TupleOrArrayFunction
FunctionPtr createFunctionArrayL1Norm(ContextPtr context_) { return FunctionArrayNorm<L1Norm>::create(context_); }
FunctionPtr createFunctionArrayL2Norm(ContextPtr context_) { return FunctionArrayNorm<L2Norm>::create(context_); }
FunctionPtr createFunctionArrayL2SquaredNorm(ContextPtr context_) { return FunctionArrayNorm<L2SquaredNorm>::create(context_); }
FunctionPtr createFunctionArrayLpNorm(ContextPtr context_) { return FunctionArrayNorm<LpNorm>::create(context_); }
FunctionPtr createFunctionArrayLinfNorm(ContextPtr context_) { return FunctionArrayNorm<LinfNorm>::create(context_); }

View File

@ -25,6 +25,7 @@ struct DivideName { static constexpr auto name = "divide"; };
struct L1Label { static constexpr auto name = "1"; };
struct L2Label { static constexpr auto name = "2"; };
struct L2SquaredLabel { static constexpr auto name = "2Squared"; };
struct LinfLabel { static constexpr auto name = "inf"; };
struct LpLabel { static constexpr auto name = "p"; };
@ -625,6 +626,108 @@ public:
};
using FunctionL2Norm = FunctionLNorm<L2Label>;
template <>
class FunctionLNorm<L2SquaredLabel> : public ITupleFunction
{
public:
static constexpr auto name = "L2SquaredNorm";
explicit FunctionLNorm(ContextPtr context_) : ITupleFunction(context_) {}
static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionLNorm>(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 tuple, 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;
}
}
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 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;
}
}
return res.column;
}
};
using FunctionL2SquaredNorm = FunctionLNorm<L2SquaredLabel>;
template <>
class FunctionLNorm<LinfLabel> : public ITupleFunction
{
@ -930,6 +1033,8 @@ using FunctionL1Distance = FunctionLDistance<L1Label>;
using FunctionL2Distance = FunctionLDistance<L2Label>;
using FunctionL2SquaredDistance = FunctionLDistance<L2SquaredLabel>;
using FunctionLinfDistance = FunctionLDistance<LinfLabel>;
using FunctionLpDistance = FunctionLDistance<LpLabel>;
@ -1111,11 +1216,13 @@ private:
extern FunctionPtr createFunctionArrayL1Norm(ContextPtr context_);
extern FunctionPtr createFunctionArrayL2Norm(ContextPtr context_);
extern FunctionPtr createFunctionArrayL2SquaredNorm(ContextPtr context_);
extern FunctionPtr createFunctionArrayLpNorm(ContextPtr context_);
extern FunctionPtr createFunctionArrayLinfNorm(ContextPtr context_);
extern FunctionPtr createFunctionArrayL1Distance(ContextPtr context_);
extern FunctionPtr createFunctionArrayL2Distance(ContextPtr context_);
extern FunctionPtr createFunctionArrayL2SquaredDistance(ContextPtr context_);
extern FunctionPtr createFunctionArrayLpDistance(ContextPtr context_);
extern FunctionPtr createFunctionArrayLinfDistance(ContextPtr context_);
extern FunctionPtr createFunctionArrayCosineDistance(ContextPtr context_);
@ -1136,6 +1243,14 @@ struct L2NormTraits
static constexpr auto CreateArrayFunction = createFunctionArrayL2Norm;
};
struct L2SquaredNormTraits
{
static inline String name = "L2SquaredNorm";
static constexpr auto CreateTupleFunction = FunctionL2SquaredNorm::create;
static constexpr auto CreateArrayFunction = createFunctionArrayL2SquaredNorm;
};
struct LpNormTraits
{
static inline String name = "LpNorm";
@ -1168,6 +1283,14 @@ struct L2DistanceTraits
static constexpr auto CreateArrayFunction = createFunctionArrayL2Distance;
};
struct L2SquaredDistanceTraits
{
static inline String name = "L2SquaredDistance";
static constexpr auto CreateTupleFunction = FunctionL2SquaredDistance::create;
static constexpr auto CreateArrayFunction = createFunctionArrayL2SquaredDistance;
};
struct LpDistanceTraits
{
static inline String name = "LpDistance";
@ -1194,11 +1317,13 @@ struct CosineDistanceTraits
using TupleOrArrayFunctionL1Norm = TupleOrArrayFunction<L1NormTraits>;
using TupleOrArrayFunctionL2Norm = TupleOrArrayFunction<L2NormTraits>;
using TupleOrArrayFunctionL2SquaredNorm = TupleOrArrayFunction<L2SquaredNormTraits>;
using TupleOrArrayFunctionLpNorm = TupleOrArrayFunction<LpNormTraits>;
using TupleOrArrayFunctionLinfNorm = TupleOrArrayFunction<LinfNormTraits>;
using TupleOrArrayFunctionL1Distance = TupleOrArrayFunction<L1DistanceTraits>;
using TupleOrArrayFunctionL2Distance = TupleOrArrayFunction<L2DistanceTraits>;
using TupleOrArrayFunctionL2SquaredDistance = TupleOrArrayFunction<L2SquaredDistanceTraits>;
using TupleOrArrayFunctionLpDistance = TupleOrArrayFunction<LpDistanceTraits>;
using TupleOrArrayFunctionLinfDistance = TupleOrArrayFunction<LinfDistanceTraits>;
using TupleOrArrayFunctionCosineDistance = TupleOrArrayFunction<CosineDistanceTraits>;
@ -1221,21 +1346,25 @@ void registerVectorFunctions(FunctionFactory & factory)
factory.registerFunction<TupleOrArrayFunctionL1Norm>();
factory.registerFunction<TupleOrArrayFunctionL2Norm>();
factory.registerFunction<TupleOrArrayFunctionL2SquaredNorm>();
factory.registerFunction<TupleOrArrayFunctionLinfNorm>();
factory.registerFunction<TupleOrArrayFunctionLpNorm>();
factory.registerAlias("normL1", TupleOrArrayFunctionL1Norm::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("normL2", TupleOrArrayFunctionL2Norm::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("normL2Squared", TupleOrArrayFunctionL2SquaredNorm::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("normLinf", TupleOrArrayFunctionLinfNorm::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("normLp", FunctionLpNorm::name, FunctionFactory::CaseInsensitive);
factory.registerFunction<TupleOrArrayFunctionL1Distance>();
factory.registerFunction<TupleOrArrayFunctionL2Distance>();
factory.registerFunction<TupleOrArrayFunctionL2SquaredDistance>();
factory.registerFunction<TupleOrArrayFunctionLinfDistance>();
factory.registerFunction<TupleOrArrayFunctionLpDistance>();
factory.registerAlias("distanceL1", FunctionL1Distance::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("distanceL2", FunctionL2Distance::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("distanceL2Squared", FunctionL2SquaredDistance::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("distanceLinf", FunctionLinfDistance::name, FunctionFactory::CaseInsensitive);
factory.registerAlias("distanceLp", FunctionLpDistance::name, FunctionFactory::CaseInsensitive);

View File

@ -21,7 +21,9 @@
6
7.1
1.4142135623730951
2
13
169
1.5
-3
2.3
@ -34,8 +36,10 @@
2.0000887587111964
4
2.8284271247461903
8
1
0
0
-4.413254828250501e-8
(0.2,-0.8)
(0.6,0.8)
@ -48,6 +52,7 @@
(NULL,NULL)
\N
\N
\N
(2,4,NULL)
\N
\N

View File

@ -28,7 +28,9 @@ SELECT scalarProduct(tuple(1), tuple(0));
SELECT L1Norm((-1, 2, -3));
SELECT L1Norm((-1, 2.5, -3.6));
SELECT L2Norm((1, 1.0));
SELECT L2SquaredNorm((1, 1.0));
SELECT L2Norm(materialize((-12, 5)));
SELECT L2SquaredNorm(materialize((-12, 5)));
SELECT max2(materialize(1), 1.5);
SELECT min2(-1, -3);
@ -44,8 +46,10 @@ SELECT LpNorm((-1, -2), 11.);
SELECT L1Distance((1, 2, 3), (2, 3, 1));
SELECT L2Distance(materialize((1, 1)), (3, -1));
SELECT L2SquaredDistance(materialize((1, 1)), (3, -1));
SELECT LinfDistance((1, 1), (1, 2));
SELECT L2Distance((5, 5), (5, 5));
SELECT L2SquaredDistance((5, 5), (5, 5));
SELECT LpDistance((1800, 1900), (18, 59), 12) - LpDistance(tuple(-22), tuple(1900), 12.);
SELECT L1Normalize(materialize((1, -4)));
@ -61,6 +65,7 @@ SELECT cosineDistance((1, 0), (0.5, sqrt(3) / 2));
SELECT (NULL, 1) + (1, NULL);
SELECT (NULL, 1) * materialize((1, NULL));
SELECT L2Norm((NULL, 3, 4));
SELECT L2SquaredNorm((NULL, 3, 4));
SELECT 2 * (1, 2, NULL);
SELECT (1, 1.0, NULL) / NULL;
SELECT (1, 1.0, NULL) / materialize(NULL);

View File

@ -1,17 +1,22 @@
6
3.7416573867739413
14
3.2071843327373397
3
0.00258509695694209
\N
\N
nan
0 0 0 0
0 0 0 0 0
12
14
21
7.0710678118654755
9.16515138991168
12.12435565298214
50
84
147
5.917593844525055
8.308858759453505
9.932246380845738
@ -27,21 +32,21 @@ nan
0.020204102886728692
0.11808289631180313
0
1 1 218.74642854227358
1 2 1348.2117786164013
2 1 219.28064210048274
2 2 1347.4008312302617
3 1 214.35251339790725
3 2 1342.8856987845243
1 1 218.74642854227358
1 2 1348.2117786164013
2 1 219.28064210048274
2 2 1347.4008312302617
3 1 214.35251339790725
3 2 1342.8856987845243
1 1 218.74642854227358
1 2 1348.2117786164013
2 1 219.28064210048274
2 2 1347.4008312302617
3 1 214.35251339790725
3 2 1342.8856987845243
1 1 218.74642854227358 47850
1 2 1348.2117786164013 1817675
2 1 219.28064210048274 48084
2 2 1347.4008312302617 1815489
3 1 214.35251339790725 45947
3 2 1342.8856987845243 1803342
1 1 218.74642854227358 47850
1 2 1348.2117786164013 1817675
2 1 219.28064210048274 48084
2 2 1347.4008312302617 1815489
3 1 214.35251339790725 45947
3 2 1342.8856987845243 1803342
1 1 218.74642854227358 47850
1 2 1348.2117786164013 1817675
2 1 219.28064210048274 48084
2 2 1347.4008312302617 1815489
3 1 214.35251339790725 45947
3 2 1342.8856987845243 1803342

View File

@ -1,10 +1,12 @@
SELECT L1Distance([0, 0, 0], [1, 2, 3]);
SELECT L2Distance([1, 2, 3], [0, 0, 0]);
SELECT L2SquaredDistance([1, 2, 3], [0, 0, 0]);
SELECT LpDistance([1, 2, 3], [0, 0, 0], 3.5);
SELECT LinfDistance([1, 2, 3], [0, 0, 0]);
SELECT cosineDistance([1, 2, 3], [3, 5, 7]);
SELECT L2Distance([1, 2, 3], NULL);
SELECT L2SquaredDistance([1, 2, 3], NULL);
SELECT cosineDistance([1, 2, 3], [0, 0, 0]);
-- Overflows
@ -12,6 +14,7 @@ WITH CAST([-547274980, 1790553898, 1981517754, 1908431500, 1352428565, -57341255
SELECT
L1Distance(a,a),
L2Distance(a,a),
L2SquaredDistance(a,a),
LinfDistance(a,a),
cosineDistance(a, a);
@ -27,6 +30,7 @@ CREATE TABLE vec2d (id UInt64, v Array(Float64)) ENGINE = Memory;
INSERT INTO vec1 VALUES (1, [3, 4, 5]), (2, [2, 4, 8]), (3, [7, 7, 7]);
SELECT L1Distance(v, [0, 0, 0]) FROM vec1;
SELECT L2Distance(v, [0, 0, 0]) FROM vec1;
SELECT L2SquaredDistance(v, [0, 0, 0]) FROM vec1;
SELECT LpDistance(v, [0, 0, 0], 3.14) FROM vec1;
SELECT LinfDistance([5, 4, 3], v) FROM vec1;
SELECT cosineDistance([3, 2, 1], v) FROM vec1;
@ -34,16 +38,17 @@ SELECT LinfDistance(v, materialize([0, -2, 0])) FROM vec1;
SELECT cosineDistance(v, materialize([1., 1., 1.])) FROM vec1;
INSERT INTO vec2 VALUES (1, [100, 200, 0]), (2, [888, 777, 666]);
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v) as dist FROM vec1 v1, vec2 v2;
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v), L2SquaredDistance(v1.v, v2.v) as dist FROM vec1 v1, vec2 v2;
INSERT INTO vec2f VALUES (1, [100, 200, 0]), (2, [888, 777, 666]);
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v) as dist FROM vec1 v1, vec2f v2;
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v), L2SquaredDistance(v1.v, v2.v) as dist FROM vec1 v1, vec2f v2;
INSERT INTO vec2d VALUES (1, [100, 200, 0]), (2, [888, 777, 666]);
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v) as dist FROM vec1 v1, vec2d v2;
SELECT v1.id, v2.id, L2Distance(v1.v, v2.v), L2SquaredDistance(v1.v, v2.v) as dist FROM vec1 v1, vec2d v2;
SELECT L1Distance([0, 0], [1]); -- { serverError 190 }
SELECT L2Distance([1, 2], (3,4)); -- { serverError 43 }
SELECT L2SquaredDistance([1, 2], (3,4)); -- { serverError 43 }
SELECT LpDistance([1, 2], [3,4]); -- { serverError 42 }
SELECT LpDistance([1, 2], [3,4], -1.); -- { serverError 69 }
SELECT LpDistance([1, 2], [3,4], 'aaa'); -- { serverError 43 }

View File

@ -1,28 +1,29 @@
6
7.0710678118654755
50
10.882246697870885
2
10803059573 4234902446.7343364 10803059573 4234902446.7343364 3122003357.3280888 2096941042
1 7 5 4.601724723020627 4
2 2 2 2 2
3 9 5.196152422706632 4.506432087111623 3
4 0 0 0 0
10803059573 4234902446.7343364 17934398733356468000 10803059573 4234902446.7343364 3122003357.3280888 2096941042
1 7 5 25 4.601724723020627 4
2 2 2 4 2 2
3 9 5.196152422706632 27 4.506432087111623 3
4 0 0 0 0 0
1 11
2 11
3 11
4 11
1 7 5 4.601724723020627 4
2 2 2 2 2
3 9 5.196152422706632 4.506432087111623 3
4 0 0 0 0
1 7 5 25 4.601724723020627 4
2 2 2 4 2 2
3 9 5.196152422706632 27 4.506432087111623 3
4 0 0 0 0 0
1 11
2 11
3 11
4 11
1 7 5 4.601724723020627 4
2 2 2 2 2
3 9 5.196152422706632 4.506432087111623 3
4 0 0 0 0
1 7 5 25 4.601724723020627 4
2 2 2 4 2 2
3 9 5.196152422706632 27 4.506432087111623 3
4 0 0 0 0 0
1 11
2 11
3 11

View File

@ -1,5 +1,6 @@
SELECT L1Norm([1, 2, 3]);
SELECT L2Norm([3., 4., 5.]);
SELECT L2SquaredNorm([3., 4., 5.]);
SELECT LpNorm([3., 4., 5.], 1.1);
SELECT LinfNorm([0, 0, 2]);
@ -8,6 +9,7 @@ WITH CAST([-547274980, 1790553898, 1981517754, 1908431500, 1352428565, -57341255
SELECT
L1Norm(a),
L2Norm(a),
L2SquaredNorm(a),
LpNorm(a,1),
LpNorm(a,2),
LpNorm(a,3.14),
@ -23,13 +25,13 @@ INSERT INTO vec1 VALUES (1, [3, 4]), (2, [2]), (3, [3, 3, 3]), (4, NULL);
INSERT INTO vec1f VALUES (1, [3, 4]), (2, [2]), (3, [3, 3, 3]), (4, NULL);
INSERT INTO vec1d VALUES (1, [3, 4]), (2, [2]), (3, [3, 3, 3]), (4, NULL);
SELECT id, L1Norm(v), L2Norm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1;
SELECT id, L1Norm(v), L2Norm(v), L2SquaredNorm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1;
SELECT id, L1Norm(materialize([5., 6.])) FROM vec1;
SELECT id, L1Norm(v), L2Norm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1f;
SELECT id, L1Norm(v), L2Norm(v), L2SquaredNorm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1f;
SELECT id, L1Norm(materialize([5., 6.])) FROM vec1f;
SELECT id, L1Norm(v), L2Norm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1d;
SELECT id, L1Norm(v), L2Norm(v), L2SquaredNorm(v), LpNorm(v, 2.7), LinfNorm(v) FROM vec1d;
SELECT id, L1Norm(materialize([5., 6.])) FROM vec1d;
SELECT L1Norm(1, 2); -- { serverError 42 }