This is an automated email from the ASF dual-hosted git repository. haonan pushed a commit to branch remove_jitpack in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 1259117678278a781d0ac5c236d111a5ef3e2f7e Author: HTHou <[email protected]> AuthorDate: Wed Aug 7 23:50:50 2024 +0800 copyed and modified code from lt_downsampling_java8 --- .../apache/iotdb/library/dprofile/util/Area.java | 62 ++++++++++++ .../apache/iotdb/library/dprofile/util/Bucket.java | 85 ++++++++++++++++ .../library/dprofile/util/LTThreeBuckets.java | 57 +++++++++++ .../library/dprofile/util/OnePassBucketizer.java | 68 +++++++++++++ .../library/dprofile/util/SlidingCollector.java | 111 +++++++++++++++++++++ .../iotdb/library/dprofile/util/Triangle.java | 59 +++++++++++ 6 files changed, 442 insertions(+) diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Area.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Area.java new file mode 100644 index 00000000000..10023a6294d --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Area.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Arrays; +import java.util.List; + +import static java.lang.Math.abs; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +class Area<T extends Pair<Long, Double>> { + private final T generator; + private final double value; + + private Area(T generator, double value) { + this.generator = generator; + this.value = value; + } + + static <U extends Pair<Long, Double>> Area<U> ofTriangle( + Pair<Long, Double> a, U b, Pair<Long, Double> c) { + // area of a triangle = |[Ax(By - Cy) + Bx(Cy - Ay) + Cx(Ay - By)] / 2| + List<Double> addends = + Arrays.asList( + a.getLeft() * (b.getRight() - c.getRight()), + b.getLeft() * (c.getRight() - a.getRight()), + c.getLeft() * (a.getRight() - b.getRight())); + double sum = addends.stream().reduce(0d, Double::sum); + double value = abs(sum / 2); + return new Area<>(b, value); + } + + T getGenerator() { + return generator; + } + + public double getValue() { + return value; + } +} diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Bucket.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Bucket.java new file mode 100644 index 00000000000..caa640707cc --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Bucket.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import static java.util.stream.Collectors.toList; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +class Bucket<T extends Pair<Long, Double>> { + private final List<T> data; + private final T first; + private final T last; + private final Pair<Long, Double> center; + private final T result; + + private Bucket(List<T> data, T first, T last, Pair<Long, Double> center, T result) { + this.data = data; + this.first = first; + this.last = last; + this.center = center; + this.result = result; + } + + static <U extends Pair<Long, Double>> Bucket<U> of(List<U> us) { + U first = us.get(0); + U last = us.get(us.size() - 1); + Pair<Long, Double> center = centerBetween(first, last); + return new Bucket<>(us, first, last, center, first); + } + + static <U extends Pair<Long, Double>> Bucket<U> of(U u) { + return new Bucket<>(Collections.singletonList(u), u, u, u, u); + } + + T getResult() { + return result; + } + + T getFirst() { + return first; + } + + T getLast() { + return last; + } + + Pair<Long, Double> getCenter() { + return center; + } + + <U> List<U> map(Function<T, U> mapper) { + return data.stream().map(mapper).collect(toList()); + } + + static Pair<Long, Double> centerBetween(Pair<Long, Double> a, Pair<Long, Double> b) { + Pair<Long, Double> vector = Pair.of(b.getLeft() - a.getLeft(), b.getRight() - a.getRight()); + Pair<Long, Double> halfVector = Pair.of(vector.getLeft() / 2, vector.getRight() / 2); + return Pair.of(a.getLeft() + halfVector.getLeft(), a.getRight() + halfVector.getRight()); + } +} diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/LTThreeBuckets.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/LTThreeBuckets.java new file mode 100644 index 00000000000..f63cc2b74c1 --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/LTThreeBuckets.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +public final class LTThreeBuckets { + + public static List<Pair<Long, Double>> sorted( + List<Pair<Long, Double>> input, int desiredBuckets) { + return sorted(input, input.size(), desiredBuckets); + } + + public static List<Pair<Long, Double>> sorted( + List<Pair<Long, Double>> input, int inputSize, int desiredBuckets) { + List<Pair<Long, Double>> results = new ArrayList<>(); + + OnePassBucketizer.bucketize(input, inputSize, desiredBuckets).stream() + .collect(new SlidingCollector<>(3, 1)) + .stream() + .map(Triangle::of) + .forEach( + triangle -> { + if (results.isEmpty()) results.add(triangle.getFirst()); + + results.add(triangle.getResult()); + + if (results.size() == desiredBuckets + 1) results.add(triangle.getLast()); + }); + + return results; + } +} diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/OnePassBucketizer.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/OnePassBucketizer.java new file mode 100644 index 00000000000..1c5eddca379 --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/OnePassBucketizer.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +class OnePassBucketizer { + + static List<Bucket<Pair<Long, Double>>> bucketize( + List<Pair<Long, Double>> input, int inputSize, int desiredBuckets) { + int middleSize = inputSize - 2; + int bucketSize = middleSize / desiredBuckets; + int remainingElements = middleSize % desiredBuckets; + + if (bucketSize == 0) + throw new IllegalArgumentException( + "Can't produce " + + desiredBuckets + + " buckets from an input series of " + + (middleSize + 2) + + " elements"); + + List<Bucket<Pair<Long, Double>>> buckets = new ArrayList<>(); + + // Add first point as the only point in the first bucket + buckets.add(Bucket.of(input.get(0))); + + List<Pair<Long, Double>> rest = input.subList(1, input.size() - 1); + + // Add middle buckets. + // When inputSize is not a multiple of desiredBuckets, remaining elements are equally + // distributed on the first buckets. + while (buckets.size() < desiredBuckets + 1) { + int size = buckets.size() <= remainingElements ? bucketSize + 1 : bucketSize; + buckets.add(Bucket.of(rest.subList(0, size))); + rest = rest.subList(size, rest.size()); + } + + // Add last point as the only point in the last bucket + buckets.add(Bucket.of(input.get(input.size() - 1))); + + return buckets; + } +} diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/SlidingCollector.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/SlidingCollector.java new file mode 100644 index 00000000000..c369fb1d81a --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/SlidingCollector.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Queue; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collector; + +import static java.lang.Integer.max; +import static java.util.stream.Collectors.toList; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +public class SlidingCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> { + + private final int size; + private final int step; + private final int window; + private final Queue<T> buffer = new ArrayDeque<>(); + private int totalIn = 0; + + public SlidingCollector(int size, int step) { + this.size = size; + this.step = step; + this.window = max(size, step); + } + + @Override + public Supplier<List<List<T>>> supplier() { + return ArrayList::new; + } + + @Override + public BiConsumer<List<List<T>>, T> accumulator() { + return (lists, t) -> { + buffer.offer(t); + ++totalIn; + if (buffer.size() == window) { + dumpCurrent(lists); + shiftBy(step); + } + }; + } + + @Override + public Function<List<List<T>>, List<List<T>>> finisher() { + return lists -> { + if (!buffer.isEmpty()) { + final int totalOut = estimateTotalOut(); + if (totalOut > lists.size()) { + dumpCurrent(lists); + } + } + return lists; + }; + } + + private int estimateTotalOut() { + return max(0, (totalIn + step - size - 1) / step) + 1; + } + + private void dumpCurrent(List<List<T>> lists) { + final List<T> batch = buffer.stream().limit(size).collect(toList()); + lists.add(batch); + } + + private void shiftBy(int by) { + for (int i = 0; i < by; i++) { + buffer.remove(); + } + } + + @Override + public BinaryOperator<List<List<T>>> combiner() { + return (l1, l2) -> { + throw new UnsupportedOperationException("Combining not possible"); + }; + } + + @Override + public Set<Characteristics> characteristics() { + return EnumSet.noneOf(Characteristics.class); + } +} diff --git a/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Triangle.java b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Triangle.java new file mode 100644 index 00000000000..6f9400a5264 --- /dev/null +++ b/library-udf/src/main/java/org/apache/iotdb/library/dprofile/util/Triangle.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.library.dprofile.util; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.List; + +import static java.util.Comparator.comparing; + +/** + * this class is copied and modified from <a + * href="https://github.com/ggalmazor/lt_downsampling_java8">...</a> project + */ +class Triangle<T extends Pair<Long, Double>> { + private final Bucket<T> left, center, right; + + private Triangle(Bucket<T> left, Bucket<T> center, Bucket<T> right) { + this.left = left; + this.center = center; + this.right = right; + } + + static <U extends Pair<Long, Double>> Triangle<U> of(List<Bucket<U>> buckets) { + return new Triangle<>(buckets.get(0), buckets.get(1), buckets.get(2)); + } + + T getFirst() { + return left.getFirst(); + } + + T getLast() { + return right.getLast(); + } + + T getResult() { + return center.map(b -> Area.ofTriangle(left.getResult(), b, right.getCenter())).stream() + .max(comparing(Area::getValue)) + .orElseThrow(() -> new RuntimeException("Can't obtain max area triangle")) + .getGenerator(); + } +}
