org.briljantframework.array.ArrayPrinter.java Source code

Java tutorial

Introduction

Here is the source code for org.briljantframework.array.ArrayPrinter.java

Source

/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Isak Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.briljantframework.array;

import java.io.IOException;
import java.util.StringJoiner;

import org.apache.commons.math3.complex.ComplexFormat;

/**
 * Utility class for (pretty) printing arrays.
 * 
 * @author Isak Karlsson
 */
public final class ArrayPrinter {

    private static int minTruncateSize = 100;
    private static int printSlices = 2;
    private static int visiblePerSlice = 2;
    private static String intFormat = "%d";
    private static String floatFormat = "%.3f";

    public static void setMinimumTruncateSize(int size) {
        minTruncateSize = size;
    }

    public static void setPrintSlices(int rows) {
        printSlices = rows;
    }

    public static void setVisiblePerSlice(int cols) {
        visiblePerSlice = cols;
    }

    public static void print(ComplexArray matrix) {
        try {
            print(System.out, matrix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(Appendable out, ComplexArray matrix) throws IOException {
        print(out, new ComplexToStringArray(matrix), "[", "]");
    }

    public static void print(DoubleArray matrix) {
        try {
            print(System.out, matrix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(DoubleArray x, String start, String end) {
        try {
            print(System.out, new DoubleToStringArray(x, floatFormat), start, end);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(Appendable out, DoubleArray matrix) throws IOException {
        print(out, new DoubleToStringArray(matrix, floatFormat), "[", "]");
    }

    public static void print(BooleanArray matrix) {
        try {
            print(System.out, matrix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(Appendable out, BooleanArray matrix) throws IOException {
        print(out, new LongToStringArray(matrix.asLong(), intFormat), "[", "]");
    }

    public static void print(LongArray matrix) {
        try {
            print(System.out, matrix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(Appendable out, LongArray matrix) throws IOException {
        print(out, new LongToStringArray(matrix, intFormat), "[", "]");
    }

    public static void print(IntArray matrix) {
        try {
            print(System.out, matrix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void print(Appendable out, IntArray matrix) throws IOException {
        print(out, new LongToStringArray(matrix.asLong(), intFormat), "[", "]");
    }

    public static <T> void print(Appendable out, Array<T> array) throws IOException {
        print(out, new ReferenceArrayToStringArray<>(array), "[", "]");
    }

    /**
     * Format the {@link ArrayPrinter.ToStringArray}
     *
     * @param out write resulting string representation to
     * @param arr the ToStringMatrix
     * @throws java.io.IOException if an IO error occurs
     */
    public static void print(Appendable out, ToStringArray arr, String startChar, String endChar)
            throws IOException {
        out.append("array(");
        if (arr.size() == 0) {
            out.append(startChar).append(endChar);
        } else if (arr.size() == 1) {
            out.append(startChar).append(arr.get(0)).append(endChar);
        } else {
            boolean truncate = minTruncateSize < arr.size() && arr.dims() != 1;
            IntArray maxWidth = computeMaxWidth(arr, truncate);
            print(out, arr, startChar, endChar, truncate, arr.dims() + 1 + "array(".length(), maxWidth);
        }
        out.append(")");
    }

    private static IntArray computeMaxWidth(ToStringArray arr, boolean truncate) {
        int lastDim = arr.dims() - 1;
        int maxPerSlice = arr.size(lastDim);
        if (truncate) {
            maxPerSlice = visiblePerSlice < 0 ? maxPerSlice : visiblePerSlice;
        }
        IntArray maxWidth = IntArray.zeros(maxPerSlice);
        return computeMaxWidthRecursive(arr, truncate, maxWidth, maxPerSlice);
    }

    private static IntArray computeMaxWidthRecursive(ToStringArray arr, boolean truncate, IntArray maxWidth,
            int maxPerSlice) {
        if (arr.dims() == 1) {
            for (int i = 0; i < arr.size(); i++) {
                int index = i % maxPerSlice;
                int currentMax = maxWidth.get(index);
                int current = arr.get(i).length();
                if (current > currentMax) {
                    maxWidth.set(index, current);
                }
                if (i >= maxPerSlice) {
                    int left = arr.size() - i - 1;
                    if (left > maxPerSlice) {
                        i += left - maxPerSlice - 1;
                    }
                }
            }
        } else {
            int len = arr.size(0);
            for (int i = 0; i < len; i++) {
                computeMaxWidthRecursive(arr.select(i), truncate, maxWidth, maxPerSlice);
                int max = len;
                if (truncate) {
                    max = printSlices < 0 ? len : printSlices;
                }
                if (i >= max) {
                    int left = len - i - 1;
                    if (left > max) {
                        i += left - max - 1;
                    }
                }
            }
        }

        return maxWidth;
    }

    /**
     * Format the {@link org.briljantframework.array.ArrayPrinter.ToStringArray}
     *
     * @param sb write resulting string representation to
     * @param arr the ToStringMatrix
     * @throws java.io.IOException if an IO error occurs
     */
    public static void print(Appendable sb, ToStringArray arr, String startChar, String endChar, boolean truncate,
            int dims, IntArray maxWidth) throws IOException {
        if (arr.size() == 0) {
            sb.append(startChar).append(arr.get(0)).append(endChar);
            return;
        }
        if (arr.dims() == 1) {
            StringJoiner joiner = new StringJoiner(", ", startChar, endChar);
            int max = arr.size();
            if (truncate) {
                max = visiblePerSlice < 0 ? arr.size() : visiblePerSlice;
            }
            for (int i = 0; i < arr.size(); i++) {
                String value = pad(arr.get(i), maxWidth.get(i % max));
                joiner.add(value);
                if (i >= max) {
                    int left = arr.size() - i - 1;
                    if (left > max) {
                        i += left - max - 1;
                        joiner.add("...");
                    }
                }
            }
            sb.append(joiner.toString());
        } else {
            int len = arr.size(0);
            sb.append("[");
            print(sb, arr.select(0), startChar, endChar, truncate, dims, maxWidth);
            for (int i = 1; i < len; i++) {
                if (arr.dims() > 2) {
                    sb.append(",\n\n");
                } else {
                    sb.append(",\n");
                }
                for (int j = 0; j < dims - arr.dims(); j++) {
                    sb.append(" ");
                }
                print(sb, arr.select(i), startChar, endChar, truncate, dims, maxWidth);
                int max = len;
                if (truncate) {
                    max = printSlices < 0 ? len : printSlices;
                }
                if (i >= max) {
                    int left = len - i - 1;
                    if (left > max) {
                        i += left - max - 1;
                        sb.append(",\n");
                        for (int j = 0; j < dims - arr.dims(); j++) {
                            sb.append(" ");
                        }
                        sb.append("...");
                    }
                }
            }
            sb.append("]");
        }
    }

    private static String pad(String value, int pad) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < pad - value.length(); i++) {
            builder.append(" ");
        }
        return builder.append(value).toString();
    }

    public static void setFloatFormat(String floatFormat) {
        ArrayPrinter.floatFormat = floatFormat;
    }

    public static void setIntFormat(String intFormat) {
        ArrayPrinter.intFormat = intFormat;
    }

    /**
     * Interface for converting arrays to string representations.
     * 
     * @author Isak Karlsson
     */
    public interface ToStringArray {

        String get(int i);

        int dims();

        int vectors(int i);

        ToStringArray getVector(int dim, int index);

        ToStringArray select(int dim);

        int size(int dim);

        int size();

        String type();
    }

    private static class DoubleToStringArray implements ToStringArray {

        private final String formatString;
        private final DoubleArray array;

        public DoubleToStringArray(DoubleArray array, String formatString) {
            this.array = array;
            this.formatString = formatString;
        }

        @Override
        public String get(int i) {
            return String.format(formatString, array.get(i));
        }

        @Override
        public int dims() {
            return array.dims();
        }

        @Override
        public int vectors(int i) {
            return array.vectors(i);
        }

        @Override
        public ToStringArray getVector(int dim, int index) {
            return new DoubleToStringArray(array.getVector(dim, index), formatString);
        }

        @Override
        public ToStringArray select(int dim) {
            return new DoubleToStringArray(array.select(dim), formatString);
        }

        @Override
        public int size(int dim) {
            return array.size(dim);
        }

        @Override
        public int size() {
            return array.size();
        }

        @Override
        public String type() {
            return "double";
        }
    }

    private static class LongToStringArray implements ToStringArray {

        private final String formatString;
        private final LongArray array;

        public LongToStringArray(LongArray array, String formatString) {
            this.array = array;
            this.formatString = formatString;
        }

        @Override
        public String get(int i) {
            return String.format(formatString, array.get(i));
        }

        @Override
        public int dims() {
            return array.dims();
        }

        @Override
        public int vectors(int i) {
            return array.vectors(i);
        }

        @Override
        public ToStringArray getVector(int dim, int index) {
            return new LongToStringArray(array.getVector(dim, index), formatString);
        }

        @Override
        public ToStringArray select(int dim) {
            return new LongToStringArray(array.select(dim), formatString);
        }

        @Override
        public int size(int dim) {
            return array.size(dim);
        }

        @Override
        public int size() {
            return array.size();
        }

        @Override
        public String type() {
            return "int";
        }
    }

    private static class ComplexToStringArray implements ToStringArray {

        private final ComplexFormat COMPLEX_FORMAT = new ComplexFormat();

        private final ComplexArray array;

        public ComplexToStringArray(ComplexArray array) {
            this.array = array;
        }

        @Override
        public String get(int i) {
            return COMPLEX_FORMAT.format(array.get(i));
        }

        @Override
        public int dims() {
            return array.dims();
        }

        @Override
        public int vectors(int i) {
            return array.vectors(i);
        }

        @Override
        public ToStringArray getVector(int dim, int index) {
            return new ComplexToStringArray(array.getVector(dim, index));
        }

        @Override
        public ToStringArray select(int dim) {
            return new ComplexToStringArray(array.select(dim));
        }

        @Override
        public int size(int dim) {
            return array.size(dim);
        }

        @Override
        public int size() {
            return array.size();
        }

        @Override
        public String type() {
            return "complex";
        }
    }

    private static class ReferenceArrayToStringArray<T> implements ToStringArray {

        private final Array<T> array;

        public ReferenceArrayToStringArray(Array<T> array) {
            this.array = array;
        }

        @Override
        public String get(int i) {
            T value = array.get(i);
            return value == null ? "null" : value.toString();
        }

        @Override
        public int dims() {
            return array.dims();
        }

        @Override
        public int vectors(int i) {
            return array.vectors(i);
        }

        @Override
        public ToStringArray getVector(int dim, int index) {
            return new ReferenceArrayToStringArray<>(array.getVector(dim, index));
        }

        @Override
        public ToStringArray select(int dim) {
            return new ReferenceArrayToStringArray<>(array.select(dim));
        }

        @Override
        public int size(int dim) {
            return array.size(dim);
        }

        @Override
        public int size() {
            return array.size();
        }

        @Override
        public String type() {
            return "object";
        }
    }
}