#pragma once #include #include #include using namespace NYql; using namespace NUdf; namespace { extern const char DigestResourceName[] = "Stat.TDigestResource"; typedef TBoxedResource TDigestResource; typedef TRefCountedPtr TDigestResourcePtr; SIMPLE_UDF_WITH_OPTIONAL_ARGS(TTDigest_Create, TResource(double, TOptional, TOptional), 2) { Y_UNUSED(valueBuilder); const double delta = args[1].GetOrDefault(0.01); const double K = args[2].GetOrDefault(25.0); if (delta == 0 || K / delta < 1) { UdfTerminate((TStringBuilder() << GetPos() << " Invalid combination of delta/K values").data()); } return TUnboxedValuePod(new TDigestResource(delta, K, args[0].Get())); } SIMPLE_STRICT_UDF(TTDigest_AddValue, TResource(TResource, double)) { Y_UNUSED(valueBuilder); TDigestResource::Validate(args[0]); TDigestResource* resource = static_cast(args[0].AsBoxed().Get()); resource->Get()->AddValue(args[1].Get()); return TUnboxedValuePod(resource); } SIMPLE_STRICT_UDF(TTDigest_GetPercentile, double(TResource, double)) { Y_UNUSED(valueBuilder); TDigestResource::Validate(args[0]); return TUnboxedValuePod(static_cast(args[0].AsBoxed().Get())->Get()->GetPercentile(args[1].Get())); } SIMPLE_STRICT_UDF(TTDigest_Serialize, char*(TResource)) { TDigestResource::Validate(args[0]); return valueBuilder->NewString(static_cast(args[0].AsBoxed().Get())->Get()->Serialize()); } SIMPLE_UDF(TTDigest_Deserialize, TResource(char*)) { Y_UNUSED(valueBuilder); return TUnboxedValuePod(new TDigestResource(TString(args[0].AsStringRef()))); } SIMPLE_STRICT_UDF(TTDigest_Merge, TResource(TResource, TResource)) { Y_UNUSED(valueBuilder); TDigestResource::Validate(args[0]); TDigestResource::Validate(args[1]); return TUnboxedValuePod(new TDigestResource(static_cast(args[0].AsBoxed().Get())->Get(), static_cast(args[1].AsBoxed().Get())->Get())); } /* * * TODO: Memory tracking * * * */ SIMPLE_MODULE(TStatModule, TTDigest_Create, TTDigest_AddValue, TTDigest_GetPercentile, TTDigest_Serialize, TTDigest_Deserialize, TTDigest_Merge) }