CWTConfig.java
package com.morphiqlabs.wavelet.cwt;
import com.morphiqlabs.wavelet.api.BoundaryMode;
import com.morphiqlabs.wavelet.util.ValidationUtils;
/**
* Configuration for Continuous Wavelet Transform operations.
*
* <p>Provides configuration options for CWT computation including boundary handling,
* FFT acceleration, normalization, and Java 21 optimization features.</p>
*/
public final class CWTConfig {
/**
* Padding strategy for boundary handling.
*/
public enum PaddingStrategy {
/** Zero padding. */
ZERO,
/** Reflect at boundaries. */
REFLECT,
/** Symmetric extension. */
SYMMETRIC,
/** Periodic extension. */
PERIODIC
}
// Configuration fields
private final BoundaryMode boundaryMode;
private final boolean fftEnabled;
private final boolean normalizeAcrossScales;
private final PaddingStrategy paddingStrategy;
private final int fftSize;
private final boolean useScopedValues;
private final boolean useStructuredConcurrency;
private final boolean useStreamGatherers;
private final MemoryPool memoryPool;
// FFT threshold for automatic decision - lowered to show FFT benefits in demos
// Can be overridden via system property: -Dvectorwave.cwt.fft.threshold=<value>
// or environment variable: VECTORWAVE_CWT_FFT_THRESHOLD=<value>
private static final int FFT_THRESHOLD = getFFTThreshold();
private CWTConfig(Builder builder) {
this.boundaryMode = builder.boundaryMode;
this.fftEnabled = builder.fftEnabled;
this.normalizeAcrossScales = builder.normalizeAcrossScales;
this.paddingStrategy = builder.paddingStrategy;
this.fftSize = builder.fftSize;
this.useScopedValues = builder.useScopedValues;
this.useStructuredConcurrency = builder.useStructuredConcurrency;
this.useStreamGatherers = builder.useStreamGatherers;
this.memoryPool = builder.memoryPool;
}
/**
* Determines the FFT threshold from configuration sources.
* Priority order: system property, environment variable, default (64).
*
* @return the FFT threshold to use
*/
private static int getFFTThreshold() {
// Try system property first
String sysProp = System.getProperty("vectorwave.cwt.fft.threshold");
if (sysProp != null) {
try {
int value = Integer.parseInt(sysProp.trim());
if (value > 0) {
return value;
}
} catch (NumberFormatException e) {
// Fall through to next option
}
}
// Try environment variable
String envVar = System.getenv("VECTORWAVE_CWT_FFT_THRESHOLD");
if (envVar != null) {
try {
int value = Integer.parseInt(envVar.trim());
if (value > 0) {
return value;
}
} catch (NumberFormatException e) {
// Fall through to default
}
}
// Default value
return 64;
}
/**
* Creates a default configuration.
*
* @return default CWT configuration
*/
public static CWTConfig defaultConfig() {
return builder().build();
}
/**
* Creates a configuration optimized for Java 21 features.
*
* @return Java 21 optimized configuration
*/
public static CWTConfig optimizedForJava21() {
return builder()
.enableFFT(true)
.normalizeScales(true)
.useScopedValues(true)
.useStructuredConcurrency(true)
.useStreamGatherers(true)
.build();
}
/**
* Creates a configuration for real-time processing.
*
* @return real-time optimized configuration
*/
public static CWTConfig forRealTimeProcessing() {
return builder()
.enableFFT(false) // Direct convolution for low latency
.normalizeScales(true)
.useScopedValues(false) // Avoid overhead
.useStructuredConcurrency(true)
.useStreamGatherers(true) // For efficient streaming
.build();
}
/**
* Creates a configuration for batch processing.
*
* @return batch processing optimized configuration
*/
public static CWTConfig forBatchProcessing() {
return builder()
.enableFFT(true) // FFT for large batches
.normalizeScales(true)
.useScopedValues(true) // Shared context
.useStructuredConcurrency(true) // Parallel processing
.useStreamGatherers(false)
.build();
}
/**
* Creates a new builder.
*
* @return new builder instance
*/
public static Builder builder() {
return new Builder();
}
/**
* Creates a builder from this configuration.
*
* @return builder with this configuration's values
*/
public Builder toBuilder() {
return new Builder()
.boundaryMode(boundaryMode)
.enableFFT(fftEnabled)
.normalizeScales(normalizeAcrossScales)
.paddingStrategy(paddingStrategy)
.fftSize(fftSize)
.useScopedValues(useScopedValues)
.useStructuredConcurrency(useStructuredConcurrency)
.useStreamGatherers(useStreamGatherers)
.memoryPool(memoryPool);
}
/**
* Determines if FFT should be used for given signal size.
*
* @param signalSize size of the signal
* @return true if FFT should be used
*/
public boolean shouldUseFFT(int signalSize) {
if (!fftEnabled) {
return false;
}
// If FFT size is specified, use it as threshold
if (fftSize > 0) {
return signalSize >= fftSize / 2;
}
// Otherwise use default threshold
return signalSize >= FFT_THRESHOLD;
}
/**
* Calculates optimal FFT size for given signal size.
*
* @param signalSize size of the signal
* @return optimal FFT size (next power of 2)
*/
public int getOptimalFFTSize(int signalSize) {
// Find next power of 2
int size = 1;
while (size < signalSize) {
size *= 2;
}
return size;
}
// Getters
/**
* Gets the boundary mode used during convolution.
* @return boundary mode used during convolution
*/
public BoundaryMode getBoundaryMode() {
return boundaryMode;
}
/**
* Checks if FFT acceleration is enabled.
* @return true if FFT acceleration is enabled
*/
public boolean isFFTEnabled() {
return fftEnabled;
}
/**
* Checks if coefficients are normalized across scales.
* @return true if coefficients are normalized across scales
*/
public boolean isNormalizeAcrossScales() {
return normalizeAcrossScales;
}
/**
* Gets the padding strategy for boundaries.
* @return padding strategy for boundaries
*/
public PaddingStrategy getPaddingStrategy() {
return paddingStrategy;
}
/**
* Gets the fixed FFT size.
* @return fixed FFT size (0 means auto)
*/
public int getFFTSize() {
return fftSize;
}
/**
* Checks if scoped values are used.
* @return true if scoped values are used
*/
public boolean isUseScopedValues() {
return useScopedValues;
}
/**
* Checks if structured concurrency is used.
* @return true if structured concurrency is used
*/
public boolean isUseStructuredConcurrency() {
return useStructuredConcurrency;
}
/**
* Checks if stream gatherers are used.
* @return true if stream gatherers are used
*/
public boolean isUseStreamGatherers() {
return useStreamGatherers;
}
/**
* Gets the memory pool in use.
* @return memory pool in use, or null
*/
public MemoryPool getMemoryPool() {
return memoryPool;
}
/**
* Builder for CWT configuration.
*/
public static class Builder {
private BoundaryMode boundaryMode = BoundaryMode.PERIODIC;
private boolean fftEnabled = true;
private boolean normalizeAcrossScales = true;
private PaddingStrategy paddingStrategy = PaddingStrategy.REFLECT;
private int fftSize = 0; // 0 means auto-determine
private boolean useScopedValues = false;
private boolean useStructuredConcurrency = true;
private boolean useStreamGatherers = true;
private MemoryPool memoryPool = null;
private Builder() {}
/**
* Sets boundary handling mode.
* @param mode boundary mode
* @return this builder
*/
public Builder boundaryMode(BoundaryMode mode) {
this.boundaryMode = mode;
return this;
}
/**
* Enables or disables FFT-based convolution.
* @param enable true to use FFT
* @return this builder
*/
public Builder enableFFT(boolean enable) {
this.fftEnabled = enable;
return this;
}
/**
* Normalizes coefficients across scales for fair energy comparison.
* @param normalize true to normalize
* @return this builder
*/
public Builder normalizeScales(boolean normalize) {
this.normalizeAcrossScales = normalize;
return this;
}
/**
* Sets boundary padding strategy.
* @param strategy padding strategy
* @return this builder
*/
public Builder paddingStrategy(PaddingStrategy strategy) {
this.paddingStrategy = strategy;
return this;
}
/**
* Sets fixed FFT size (power of 2) or 0 for auto.
* @param size FFT size (0 or power of 2)
* @return this builder
* @throws IllegalArgumentException if invalid
*/
public Builder fftSize(int size) {
if (size < 0) {
throw new IllegalArgumentException("FFT size must be non-negative");
}
if (size > 0 && !ValidationUtils.isPowerOfTwo(size)) {
throw new IllegalArgumentException("FFT size must be a power of 2 or 0 (auto)");
}
this.fftSize = size;
return this;
}
/**
* Enables use of scoped values to reduce parameter threading overhead.
* @param use true to enable
* @return this builder
*/
public Builder useScopedValues(boolean use) {
this.useScopedValues = use;
return this;
}
/**
* Enables structured concurrency in CWT internals.
* @param use true to enable
* @return this builder
*/
public Builder useStructuredConcurrency(boolean use) {
this.useStructuredConcurrency = use;
return this;
}
/**
* Enables stream gatherers for intra-stage parallelism.
* @param use true to enable
* @return this builder
*/
public Builder useStreamGatherers(boolean use) {
this.useStreamGatherers = use;
return this;
}
/**
* Sets memory pool for coefficient storage.
* @param pool memory pool
* @return this builder
*/
public Builder memoryPool(MemoryPool pool) {
this.memoryPool = pool;
return this;
}
/**
* Builds configuration.
* @return new config instance
*/
public CWTConfig build() {
return new CWTConfig(this);
}
}
}