net.openhft.chronicle.timeseries.Columns.java Source code

Java tutorial

Introduction

Here is the source code for net.openhft.chronicle.timeseries.Columns.java

Source

/*
 *
 *  *     Copyright (C) 2016  higherfrequencytrading.com
 *  *
 *  *     This program is free software: you can redistribute it and/or modify
 *  *     it under the terms of the GNU Lesser General Public License as published by
 *  *     the Free Software Foundation, either version 3 of the License.
 *  *
 *  *     This program is distributed in the hope that it will be useful,
 *  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  *     GNU Lesser General Public License for more details.
 *  *
 *  *     You should have received a copy of the GNU Lesser General Public License
 *  *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package net.openhft.chronicle.timeseries;

import net.openhft.chronicle.bytes.BytesStore;
import net.openhft.chronicle.bytes.NativeBytesStore;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.random.MersenneTwister;
import org.apache.commons.math3.random.RandomGenerator;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.function.Supplier;

/**
 * Created by peter on 20/02/16.
 */
public enum Columns {
    ;

    static int CHUNK_SIZE_SQRT = 64;
    static int CHUNK_SIZE = CHUNK_SIZE_SQRT * CHUNK_SIZE_SQRT;

    public static void generateBrownian(DoubleColumn col, double start, double end, double sd) {
        long length = col.length();
        double sd2 = sd / Math.sqrt(length);
        NormalDistribution nd = new NormalDistribution(0, sd2 * CHUNK_SIZE);
        int trendLength = Math.toIntExact((length - 1) / CHUNK_SIZE + 2);
        BytesStore trend = NativeBytesStore.lazyNativeBytesStoreWithFixedCapacity(trendLength * 8L);
        double x = start;
        RandomGenerator rand = new MersenneTwister();
        for (int i = 0; i < trendLength - 1; i++) {
            float f = rand.nextFloat();
            trend.writeDouble((long) i << 3, x);
            x += nd.inverseCumulativeProbability(f);
        }
        trend.writeDouble((long) (trendLength - 1) << 3, x);
        double diff = end - x;
        double gradient = diff / (trendLength - 1);
        for (int i = 0; i < trendLength; i++) {
            double y = trend.addAndGetDoubleNotAtomic((long) i << 3, i * gradient);
            //            System.out.println(i + ": "+y);
        }
        int procs = Runtime.getRuntime().availableProcessors();
        int chunksPerTask = (trendLength - 1) / procs + 1;
        ForkJoinPool fjp = ForkJoinPool.commonPool();
        List<ForkJoinTask> tasks = new ArrayList<>(procs);
        for (int i = 0; i < procs; i++) {
            int si = i * chunksPerTask;
            int ei = Math.min(trendLength, si + chunksPerTask);
            tasks.add(fjp.submit(() -> {
                NormalDistribution nd2 = new NormalDistribution(0, sd2);
                RandomGenerator rand2 = new MersenneTwister();
                for (int j = si; j < ei; j++) {
                    generateBrownian(col, (long) j * CHUNK_SIZE, trend.readDouble((long) j << 3),
                            trend.readDouble((long) (j + 1) << 3), nd2, rand2);
                }
            }));
        }
        for (ForkJoinTask task : tasks) {
            task.join();
        }
        trend.release();
    }

    private static void generateBrownian(DoubleColumn col, long first, double start, double end,
            NormalDistribution nd, RandomGenerator rand) {
        double x = start;
        int chunkSize = (int) Math.min(col.length() - first, CHUNK_SIZE);
        for (int i = 0; i < chunkSize; i++) {
            col.set(first + i, x);
            double p = rand.nextFloat() + 0.5 / (1 << 24);
            double v = nd.inverseCumulativeProbability(p);
            x += v;
            assert !Double.isInfinite(x);
        }
        double diff = end - x;
        double gradient = diff / chunkSize;
        for (int i = 0; i < chunkSize; i++) {
            col.add(first + i, i * gradient);
        }
    }

    public static <T> void setAll(LongColumn col, Supplier<T> perThread,
            LongColumnIndexObjectConsumer<T> consumer) {
        long length = col.length();
        int chunks = Math.toIntExact((length - 1) / CHUNK_SIZE + 1);
        ForkJoinPool fjp = ForkJoinPool.commonPool();
        int procs = Runtime.getRuntime().availableProcessors();
        List<ForkJoinTask> tasks = new ArrayList<>(procs);
        int chunksPerTask = (chunks - 1) / procs + 1;
        for (int i = 0; i < procs; i++) {
            int si = i * chunksPerTask;
            int ei = Math.min(chunks, si + chunksPerTask);
            tasks.add(fjp.submit(() -> {
                T t = perThread.get();
                long first = (long) si * CHUNK_SIZE;
                int max = (int) Math.min((ei - si) * CHUNK_SIZE, length - first);
                for (int j = 0; j < max; j++) {
                    consumer.apply(col, first + j, t);
                }
            }));
        }
        for (ForkJoinTask task : tasks) {
            task.join();
        }
    }
}