FrequencyTrieBuilders.java

1
/*******************************************************************************
2
 * Copyright (C) 2026, Leo Galambos
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 *
11
 * 2. Redistributions in binary form must reproduce the above copyright notice,
12
 *    this list of conditions and the following disclaimer in the documentation
13
 *    and/or other materials provided with the distribution.
14
 *
15
 * 3. Neither the name of the copyright holder nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
 * POSSIBILITY OF SUCH DAMAGE.
30
 ******************************************************************************/
31
package org.egothor.stemmer;
32
33
import java.util.HashSet;
34
import java.util.IdentityHashMap;
35
import java.util.Map;
36
import java.util.Objects;
37
import java.util.Set;
38
import java.util.function.Function;
39
import java.util.function.IntFunction;
40
import java.util.logging.Level;
41
import java.util.logging.Logger;
42
43
import org.egothor.stemmer.trie.CompiledNode;
44
45
/**
46
 * Factory utilities related to {@link FrequencyTrie.Builder}.
47
 *
48
 * <p>
49
 * This helper reconstructs writable builders from compiled read-only tries. The
50
 * reconstruction preserves the semantics and local counts of the compiled trie
51
 * as currently stored, which makes it suitable for subsequent modifications
52
 * followed by recompilation.
53
 *
54
 * <p>
55
 * Reconstruction operates on the compiled form. Therefore, if the compiled trie
56
 * was produced using a reduction mode that merged semantically equivalent
57
 * subtrees, the recreated builder reflects that reduced compiled state rather
58
 * than the exact original unreduced insertion history.
59
 */
60
public final class FrequencyTrieBuilders {
61
62
    /**
63
     * Logger of this class.
64
     */
65
    private static final Logger LOGGER = Logger.getLogger(FrequencyTrieBuilders.class.getName());
66
67
    /**
68
     * Utility class.
69
     */
70
    private FrequencyTrieBuilders() {
71
        throw new AssertionError("No instances.");
72
    }
73
74
    /**
75
     * Reconstructs a new writable builder from a compiled read-only trie.
76
     *
77
     * <p>
78
     * The returned builder contains the same key-local value counts as the supplied
79
     * compiled trie. Callers may continue modifying the returned builder and then
80
     * compile a new {@link FrequencyTrie} instance.
81
     *
82
     * @param source            source compiled trie
83
     * @param arrayFactory      array factory for the reconstructed builder
84
     * @param reductionSettings reduction settings to associate with the new builder
85
     * @param <V>               value type
86
     * @return reconstructed writable builder
87
     * @throws NullPointerException if any argument is {@code null}
88
     */
89
    public static <V> FrequencyTrie.Builder<V> copyOf(final FrequencyTrie<V> source,
90
            final IntFunction<V[]> arrayFactory, final ReductionSettings reductionSettings) {
91
        Objects.requireNonNull(source, "source");
92
        Objects.requireNonNull(arrayFactory, "arrayFactory");
93
        Objects.requireNonNull(reductionSettings, "reductionSettings");
94
95
        final FrequencyTrie.Builder<V> builder = new FrequencyTrie.Builder<>(arrayFactory, reductionSettings,
96
                source.traversalDirection(), source.metadata().caseProcessingMode(),
97
                source.metadata().diacriticProcessingMode());
98
        final StringBuilder keyBuilder = new StringBuilder(64);
99
100 1 1. copyOf : removed call to org/egothor/stemmer/FrequencyTrieBuilders::copyNode → KILLED
        copyNode(source.root(), keyBuilder, builder, source.traversalDirection());
101
102
        LOGGER.log(Level.FINE, "Reconstructed writable builder from compiled trie.");
103 1 1. copyOf : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::copyOf → KILLED
        return builder;
104
    }
105
106
    /**
107
     * Reconstructs a new writable builder from a compiled read-only trie using
108
     * default settings for the supplied reduction mode.
109
     *
110
     * @param source        source compiled trie
111
     * @param arrayFactory  array factory for the reconstructed builder
112
     * @param reductionMode reduction mode to associate with the new builder
113
     * @param <V>           value type
114
     * @return reconstructed writable builder
115
     * @throws NullPointerException if any argument is {@code null}
116
     */
117
    public static <V> FrequencyTrie.Builder<V> copyOf(final FrequencyTrie<V> source,
118
            final IntFunction<V[]> arrayFactory, final ReductionMode reductionMode) {
119
        Objects.requireNonNull(reductionMode, "reductionMode");
120 1 1. copyOf : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::copyOf → KILLED
        return copyOf(source, arrayFactory, ReductionSettings.withDefaults(reductionMode));
121
    }
122
123
    /**
124
     * Reconstructs a compiled trie with every stored value transformed to another
125
     * value type.
126
     *
127
     * <p>
128
     * The method preserves logical keys, local value counts, trie metadata, and the
129
     * supplied reduction settings. It is intended for runtime specialization, such
130
     * as replacing serialized patch-command strings with precompiled patch command
131
     * objects without changing the persisted binary trie format.
132
     * </p>
133
     *
134
     * @param source            source compiled trie
135
     * @param arrayFactory      array factory for mapped values
136
     * @param reductionSettings reduction settings for the mapped trie
137
     * @param valueMapper       value mapping function
138
     * @param <S>               source value type
139
     * @param <T>               target value type
140
     * @return compiled trie containing mapped values
141
     * @throws NullPointerException if any argument is {@code null}
142
     */
143
    public static <S, T> FrequencyTrie<T> mapValues(final FrequencyTrie<S> source,
144
            final IntFunction<T[]> arrayFactory, final ReductionSettings reductionSettings,
145
            final Function<? super S, ? extends T> valueMapper) {
146
        Objects.requireNonNull(source, "source");
147
        Objects.requireNonNull(arrayFactory, "arrayFactory");
148
        Objects.requireNonNull(reductionSettings, "reductionSettings");
149
        Objects.requireNonNull(valueMapper, "valueMapper");
150
151
        final Map<CompiledNode<S>, CompiledNode<T>> cache = new IdentityHashMap<>();
152
        final CompiledNode<T> mappedRoot = mapCompiledNode(source.root(), arrayFactory, valueMapper, cache);
153
        final TrieMetadata metadata = TrieMetadata.forCompilation(source.traversalDirection(), reductionSettings,
154
                source.metadata().diacriticProcessingMode(), source.metadata().caseProcessingMode());
155
156
        LOGGER.log(Level.FINE, "Mapped compiled trie values to a specialized value type.");
157 1 1. mapValues : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapValues → KILLED
        return FrequencyTrie.fromCompiled(arrayFactory, mappedRoot, metadata);
158
    }
159
160
    /**
161
     * Reconstructs a compiled trie with every stored value transformed to another
162
     * value type using default settings for the supplied reduction mode.
163
     *
164
     * @param source        source compiled trie
165
     * @param arrayFactory  array factory for mapped values
166
     * @param reductionMode reduction mode for the mapped trie
167
     * @param valueMapper   value mapping function
168
     * @param <S>           source value type
169
     * @param <T>           target value type
170
     * @return compiled trie containing mapped values
171
     * @throws NullPointerException if any argument is {@code null}
172
     */
173
    public static <S, T> FrequencyTrie<T> mapValues(final FrequencyTrie<S> source,
174
            final IntFunction<T[]> arrayFactory, final ReductionMode reductionMode,
175
            final Function<? super S, ? extends T> valueMapper) {
176
        Objects.requireNonNull(reductionMode, "reductionMode");
177 1 1. mapValues : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapValues → NO_COVERAGE
        return mapValues(source, arrayFactory, ReductionSettings.withDefaults(reductionMode), valueMapper);
178
    }
179
180
    /**
181
     * Computes structural statistics for one compiled trie.
182
     *
183
     * <p>
184
     * Each unique node instance contributes once to storage counts. Root-to-leaf
185
     * path statistics are computed independently with memoized dynamic programming,
186
     * so every logical path through shared reduced subtrees contributes at its
187
     * actual depth.
188
     * </p>
189
     *
190
     * @param trie source compiled trie
191
     * @return structural statistics
192
     * @throws NullPointerException if {@code trie} is {@code null}
193
     */
194
    public static TrieStatistics computeStatistics(final FrequencyTrie<?> trie) {
195
        Objects.requireNonNull(trie, "trie");
196
        final Map<CompiledNode<?>, Boolean> visited = new IdentityHashMap<>();
197
        final Set<Object> distinctValues = new HashSet<>();
198
        final StructuralCounters counters = new StructuralCounters();
199 1 1. computeStatistics : removed call to org/egothor/stemmer/FrequencyTrieBuilders::collectStructuralStats → KILLED
        collectStructuralStats(trie.root(), visited, distinctValues, counters);
200
201
        final Map<CompiledNode<?>, PathSummary> pathCache = new IdentityHashMap<>();
202
        final PathSummary paths = summarizePaths(trie.root(), pathCache);
203 1 1. computeStatistics : negated conditional → KILLED
        final double averageLeafDepth = paths.leafPathCount() == 0L ? 0.0d
204 1 1. computeStatistics : Replaced double division with multiplication → KILLED
                : paths.totalLeafDepth() / (double) paths.leafPathCount();
205 1 1. computeStatistics : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::computeStatistics → KILLED
        return new TrieStatistics(counters.internalNodes, counters.leafNodes, counters.edges,
206
                counters.acceptingLeaves, counters.valueReferences, distinctValues.size(),
207
                paths.leafPathCount(), paths.longestPath(), averageLeafDepth,
208
                counters.denseLookupNodes, counters.denseTableSlots);
209
    }
210
211
    /**
212
     * Recursive depth-first helper that accumulates trie structure counters.
213
     *
214
     * @param node           current node
215
     * @param visited        identity set of already-visited nodes
216
     * @param distinctValues distinct stored values
217
     * @param counters       mutable structural counters
218
     */
219
    private static void collectStructuralStats(final CompiledNode<?> node,
220
            final Map<CompiledNode<?>, Boolean> visited, final Set<Object> distinctValues,
221
            final StructuralCounters counters) {
222 1 1. collectStructuralStats : negated conditional → KILLED
        if (visited.put(node, Boolean.TRUE) != null) {
223
            return;
224
        }
225
        counters.edges = checkedAdd(counters.edges, node.edgeCount(), "edge count");
226
        counters.valueReferences = checkedAdd(counters.valueReferences, node.valueCount(), "value-reference count");
227
        for (final Object value : node.orderedValues()) {
228
            distinctValues.add(value);
229
        }
230 1 1. collectStructuralStats : negated conditional → KILLED
        if (node.isLeaf()) {
231
            counters.leafNodes = checkedAdd(counters.leafNodes, 1L, "leaf-node count");
232 1 1. collectStructuralStats : negated conditional → SURVIVED
            if (node.acceptsRemainingInput()) {
233
                counters.acceptingLeaves = checkedAdd(counters.acceptingLeaves, 1L, "accepting-leaf count");
234
            }
235
        } else {
236
            counters.internalNodes = checkedAdd(counters.internalNodes, 1L, "internal-node count");
237
        }
238 1 1. collectStructuralStats : negated conditional → SURVIVED
        if (node.hasDenseLookup()) {
239
            counters.denseLookupNodes = checkedAdd(counters.denseLookupNodes, 1L, "dense-lookup-node count");
240
            counters.denseTableSlots = checkedAdd(counters.denseTableSlots, node.denseTableLength(),
241
                    "dense-table-slot count");
242
        }
243
        for (final CompiledNode<?> child : node.children()) {
244 1 1. collectStructuralStats : removed call to org/egothor/stemmer/FrequencyTrieBuilders::collectStructuralStats → KILLED
            collectStructuralStats(child, visited, distinctValues, counters);
245
        }
246
    }
247
248
    /**
249
     * Computes all logical root-to-leaf suffix paths below one node.
250
     *
251
     * @param node  current node
252
     * @param cache identity-keyed summaries for shared subtrees
253
     * @return immutable path summary relative to {@code node}
254
     */
255
    private static PathSummary summarizePaths(final CompiledNode<?> node,
256
            final Map<CompiledNode<?>, PathSummary> cache) {
257
        final PathSummary existing = cache.get(node);
258 1 1. summarizePaths : negated conditional → KILLED
        if (existing != null) {
259 1 1. summarizePaths : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::summarizePaths → KILLED
            return existing;
260
        }
261
        final PathSummary result;
262 1 1. summarizePaths : negated conditional → KILLED
        if (node.isLeaf()) {
263
            result = new PathSummary(1L, 0L, 0L);
264
        } else {
265
            long leafPaths = 0L;
266
            long totalDepth = 0L;
267
            long longestPath = 0L;
268
            for (final CompiledNode<?> child : node.children()) {
269
                final PathSummary childSummary = summarizePaths(child, cache);
270
                leafPaths = checkedAdd(leafPaths, childSummary.leafPathCount(), "logical leaf-path count");
271
                totalDepth = checkedAdd(totalDepth,
272
                        checkedAdd(childSummary.totalLeafDepth(), childSummary.leafPathCount(),
273
                                "logical leaf-depth sum"),
274
                        "logical leaf-depth sum");
275
                longestPath = Math.max(longestPath,
276
                        checkedAdd(childSummary.longestPath(), 1L, "longest logical path"));
277
            }
278
            result = new PathSummary(leafPaths, totalDepth, longestPath);
279
        }
280
        cache.put(node, result);
281 1 1. summarizePaths : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::summarizePaths → KILLED
        return result;
282
    }
283
284
    /**
285
     * Adds two structural quantities and converts numeric overflow into a
286
     * diagnostic state failure.
287
     *
288
     * @param left  accumulated quantity
289
     * @param right non-negative quantity to add
290
     * @param label safe diagnostic name of the statistic being calculated
291
     * @return exact sum of {@code left} and {@code right}
292
     * @throws IllegalStateException if the sum exceeds the {@code long} range
293
     */
294
    private static long checkedAdd(final long left, final long right, final String label) {
295
        try {
296 1 1. checkedAdd : replaced long return with 0 for org/egothor/stemmer/FrequencyTrieBuilders::checkedAdd → KILLED
            return Math.addExact(left, right);
297
        } catch (final ArithmeticException exception) {
298
            throw new IllegalStateException("Arithmetic overflow while calculating trie " + label + '.', exception);
299
        }
300
    }
301
302
    /**
303
     * Mutable structural counters confined to one statistics traversal.
304
     *
305
     * <p>
306
     * Instances never escape {@link #computeStatistics(FrequencyTrie)} and are
307
     * therefore neither shared nor required to be thread-safe.
308
     * </p>
309
     */
310
    private static final class StructuralCounters {
311
        private long internalNodes;
312
        private long leafNodes;
313
        private long edges;
314
        private long acceptingLeaves;
315
        private long valueReferences;
316
        private long denseLookupNodes;
317
        private long denseTableSlots;
318
    }
319
320
    /**
321
     * Immutable memoized logical-path summary relative to one compiled node.
322
     *
323
     * @param leafPathCount number of logical paths ending at leaves
324
     * @param totalLeafDepth sum of the relative depths of those paths
325
     * @param longestPath maximum relative path depth
326
     */
327
    private record PathSummary(long leafPathCount, long totalLeafDepth, long longestPath) { }
328
329
    /**
330
     * Copies one compiled node and all reachable descendants into the target
331
     * builder.
332
     *
333
     * @param node               current compiled node
334
     * @param keyBuilder         current key builder
335
     * @param builder            target mutable builder
336
     * @param traversalDirection logical key traversal direction used by the source
337
     * @param <V>                value type
338
     */
339
    private static <V> void copyNode(final CompiledNode<V> node, final StringBuilder keyBuilder,
340
            final FrequencyTrie.Builder<V> builder, final WordTraversalDirection traversalDirection) {
341
        final String logicalKey = traversalDirection.traversalPathToLogicalKey(keyBuilder);
342 2 1. copyNode : changed conditional boundary → KILLED
2. copyNode : negated conditional → KILLED
        for (int valueIndex = 0; valueIndex < node.orderedValues().length; valueIndex++) {
343
            builder.put(logicalKey, node.orderedValues()[valueIndex], node.orderedCounts()[valueIndex]);
344
        }
345
        // Preserve the "accepts remaining input" generalization of a contracted
346
        // leaf: its original member paths were collapsed away and cannot be
347
        // replayed, so reduction alone would not re-derive the accepting flag.
348 1 1. copyNode : negated conditional → KILLED
        if (node.acceptsRemainingInput()) {
349
            builder.markAcceptsRemainingInput(logicalKey);
350
        }
351
        builder.recordCompiledSource(logicalKey, node);
352
353 2 1. copyNode : negated conditional → KILLED
2. copyNode : changed conditional boundary → KILLED
        for (int childIndex = 0; childIndex < node.edgeLabels().length; childIndex++) {
354
            keyBuilder.append(node.edgeLabels()[childIndex]);
355 1 1. copyNode : removed call to org/egothor/stemmer/FrequencyTrieBuilders::copyNode → KILLED
            copyNode(node.children()[childIndex], keyBuilder, builder, traversalDirection);
356 2 1. copyNode : removed call to java/lang/StringBuilder::setLength → KILLED
2. copyNode : Replaced integer subtraction with addition → KILLED
            keyBuilder.setLength(keyBuilder.length() - 1);
357
        }
358
    }
359
360
    /**
361
     * Maps one compiled node graph while preserving canonical sharing and accepting
362
     * leaf semantics.
363
     *
364
     * @param node         source node
365
     * @param arrayFactory target value array factory
366
     * @param valueMapper  value mapper
367
     * @param cache        identity cache for shared compiled nodes
368
     * @param <S>          source value type
369
     * @param <T>          target value type
370
     * @return mapped compiled node
371
     */
372
    private static <S, T> CompiledNode<T> mapCompiledNode(final CompiledNode<S> node,
373
            final IntFunction<T[]> arrayFactory, final Function<? super S, ? extends T> valueMapper,
374
            final Map<CompiledNode<S>, CompiledNode<T>> cache) {
375
        final CompiledNode<T> existing = cache.get(node);
376 1 1. mapCompiledNode : negated conditional → KILLED
        if (existing != null) {
377 1 1. mapCompiledNode : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapCompiledNode → KILLED
            return existing;
378
        }
379
380
        final CompiledNode<S>[] sourceChildren = node.children();
381
        @SuppressWarnings("unchecked")
382
        final CompiledNode<T>[] mappedChildren = new CompiledNode[sourceChildren.length];
383 2 1. mapCompiledNode : changed conditional boundary → KILLED
2. mapCompiledNode : negated conditional → KILLED
        for (int childIndex = 0; childIndex < sourceChildren.length; childIndex++) {
384
            mappedChildren[childIndex] = mapCompiledNode(sourceChildren[childIndex], arrayFactory, valueMapper, cache);
385
        }
386
387
        final S[] sourceValues = node.orderedValues();
388
        final T[] mappedValues = arrayFactory.apply(sourceValues.length);
389 2 1. mapCompiledNode : negated conditional → KILLED
2. mapCompiledNode : changed conditional boundary → KILLED
        for (int valueIndex = 0; valueIndex < sourceValues.length; valueIndex++) {
390
            mappedValues[valueIndex] = valueMapper.apply(sourceValues[valueIndex]);
391
        }
392
393
        final CompiledNode<T> mapped = new CompiledNode<>(node.edgeLabels().clone(), mappedChildren, mappedValues,
394
                node.acceptsRemainingInput(), CompiledNode.DEFAULT_MAX_EXPANDED_INDEX, node.orderedCounts().clone());
395
        cache.put(node, mapped);
396 1 1. mapCompiledNode : replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapCompiledNode → KILLED
        return mapped;
397
    }
398
}

Mutations

100

1.1
Location : copyOf
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldPreserveLocalCountsAndOrdering()]
removed call to org/egothor/stemmer/FrequencyTrieBuilders::copyNode → KILLED

103

1.1
Location : copyOf
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::copyOf → KILLED

120

1.1
Location : copyOf
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructUsingReductionModeShortcut()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::copyOf → KILLED

157

1.1
Location : mapValues
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapValues → KILLED

177

1.1
Location : mapValues
Killed by : none
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapValues → NO_COVERAGE

199

1.1
Location : computeStatistics
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
removed call to org/egothor/stemmer/FrequencyTrieBuilders::collectStructuralStats → KILLED

203

1.1
Location : computeStatistics
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
negated conditional → KILLED

204

1.1
Location : computeStatistics
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
Replaced double division with multiplication → KILLED

205

1.1
Location : computeStatistics
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::computeStatistics → KILLED

222

1.1
Location : collectStructuralStats
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
negated conditional → KILLED

230

1.1
Location : collectStructuralStats
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
negated conditional → KILLED

232

1.1
Location : collectStructuralStats
Killed by : none
negated conditional → SURVIVED
Covering tests

238

1.1
Location : collectStructuralStats
Killed by : none
negated conditional → SURVIVED
Covering tests

244

1.1
Location : collectStructuralStats
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
removed call to org/egothor/stemmer/FrequencyTrieBuilders::collectStructuralStats → KILLED

258

1.1
Location : summarizePaths
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
negated conditional → KILLED

259

1.1
Location : summarizePaths
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::summarizePaths → KILLED

262

1.1
Location : summarizePaths
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
negated conditional → KILLED

281

1.1
Location : summarizePaths
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::summarizePaths → KILLED

296

1.1
Location : checkedAdd
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMeasureLogicalPathsThroughSharedSubtree()]
replaced long return with 0 for org/egothor/stemmer/FrequencyTrieBuilders::checkedAdd → KILLED

342

1.1
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
changed conditional boundary → KILLED

2.2
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
negated conditional → KILLED

348

1.1
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
negated conditional → KILLED

353

1.1
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
negated conditional → KILLED

2.2
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldReconstructEmptyTrie()]
changed conditional boundary → KILLED

355

1.1
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldPreserveLocalCountsAndOrdering()]
removed call to org/egothor/stemmer/FrequencyTrieBuilders::copyNode → KILLED

356

1.1
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldAllowFurtherModificationsWithoutAffectingSourceTrie()]
removed call to java/lang/StringBuilder::setLength → KILLED

2.2
Location : copyNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldAllowFurtherModificationsWithoutAffectingSourceTrie()]
Replaced integer subtraction with addition → KILLED

376

1.1
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
negated conditional → KILLED

377

1.1
Location : mapCompiledNode
Killed by : org.egothor.stemmer.benchmark.generalization.EditCostSensitivityApplicationTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.benchmark.generalization.EditCostSensitivityApplicationTest]/[method:buildCompiledTrieShouldReturnNonNullTrie()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapCompiledNode → KILLED

383

1.1
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
changed conditional boundary → KILLED

2.2
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
negated conditional → KILLED

389

1.1
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
negated conditional → KILLED

2.2
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
changed conditional boundary → KILLED

396

1.1
Location : mapCompiledNode
Killed by : org.egothor.stemmer.FrequencyTrieBuildersTest.[engine:junit-jupiter]/[class:org.egothor.stemmer.FrequencyTrieBuildersTest]/[method:shouldMapValuesWhilePreservingKeysAndCounts()]
replaced return value with null for org/egothor/stemmer/FrequencyTrieBuilders::mapCompiledNode → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1