001    /*
002     * Copyright (c) 1998-2014 ChemAxon Ltd. All Rights Reserved.
003     *
004     * This software is the confidential and proprietary information of
005     * ChemAxon. You shall not disclose such Confidential Information
006     * and shall use it only in accordance with the terms of the agreements
007     * you entered into with ChemAxon.
008     *
009     */
010    package com.chemaxon.overlap.bruteforce;
011    
012    import com.chemaxon.overlap.concurrent.ResultHandler;
013    import com.chemaxon.overlap.unguarded.UnguardedDissimilarityCalculator;
014    import com.google.common.base.Function;
015    import com.google.common.collect.ImmutableList;
016    import java.util.List;
017    
018    /**
019     * Full matrix calculator for unguarded paged storage.
020     *
021     * @author Gabor Imre
022     */
023    final class FullMatrix {
024    
025        /**
026         * No constructor exposed for utility classes.
027         */
028        private FullMatrix() {
029        }
030    
031        /**
032         * Calculator function.
033         *
034         * <p>
035         * Function to calculate the dissimilarity vectors for a set of query structures.</p>
036         *
037         * @param <T> Type of unguarded descriptors
038         *
039         */
040        static class Calc<T> implements Function<ImmutableList<T>, double[][]> {
041    
042            /**
043             * List of queries.
044             */
045            private final List<T> queries;
046    
047            /**
048             * Comparator of dissimilarity values.
049             */
050            private final UnguardedDissimilarityCalculator<T> calc;
051    
052            /**
053             * Construct.
054             *
055             * @param queries List of queries
056             * @param calc Calculator of dissimilarity
057             */
058            public Calc(List<T> queries, UnguardedDissimilarityCalculator<T> calc) {
059                if (queries.isEmpty()) {
060                    throw new IllegalArgumentException("No query specified");
061                }
062                this.queries = queries;
063                this.calc = calc;
064            }
065    
066            @Override
067            public double[][] apply(ImmutableList<T> targets) {
068                if (targets.isEmpty()) {
069                    throw new IllegalArgumentException("No targets specified");
070                }
071    
072                // Be consistent with semantics of "dissimilarity vectors for each queries"
073                // First (outer) index: query
074                // Second (inner) index: input target
075                final double[][] ret = new double[this.queries.size()][targets.size()];
076    
077                for (int qi = 0; qi < this.queries.size(); qi++) {
078                    final T qd = this.queries.get(qi);
079    
080                    for (int ti = 0; ti < targets.size(); ti++) {
081                        final T td = targets.get(ti);
082    
083                        ret[qi][ti] = this.calc.dissimilarity(td, qd);
084                    }
085    
086                }
087    
088                return ret;
089            }
090        }
091    
092        /**
093         * Report dissimilarity vectors.
094         *
095         * <p>
096         * Note that according to the {@link ResultHandler} API contracts results are expected to be reported in correct
097         * ordering.</p>
098         */
099        static class Report<T> implements ResultHandler<ImmutableList<T>, double[][]> {
100    
101            /**
102             * Final full dissimilarity matrix.
103             *
104             * <p>
105             * Indexing: [query][target]</p>
106             */
107            private final double[][] res;
108    
109            /**
110             * Next target ID.
111             */
112            private int nextTarget = 0;
113    
114            /**
115             * Construct.
116             *
117             * @param res Full allocated dissimilarity matrix.
118             */
119            Report(double[][] res) {
120                this.res = res;
121            }
122    
123    
124            @Override
125            public long result(int sourceIndex, ImmutableList<T> s, double[][] t) {
126                // Note that t is indexed as [query][target page]
127                final int pagesize = t[0].length;
128                for (int qi = 0; qi < t.length; qi++) {
129                    //for (int ri = 0; ri < pagesize; ri++) {
130                    //    this.res[qi][this.nextTarget + ri] = t[qi][ri];
131                    //}
132                    System.arraycopy(t[qi], 0, this.res[qi], this.nextTarget, pagesize);
133                }
134                this.nextTarget += pagesize;
135                return (long) pagesize * t.length;
136            }
137        }
138    }