From c80a8237e1d8a9e384dd5210db36281ff15a4b34 Mon Sep 17 00:00:00 2001 From: Dirzei Date: Mon, 4 May 2026 19:01:16 +0200 Subject: [PATCH] Fix thread-safety and typos --- src/core/config/Settings.java | 5 ++++- src/core/functions/GeneralFunction.java | 9 +++++++-- .../functiongenerators/LegrendePolynomial.java | 13 +++++++++++-- src/parsing/LatexReplacer.java | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/core/config/Settings.java b/src/core/config/Settings.java index 4f7f3766..889e5e59 100644 --- a/src/core/config/Settings.java +++ b/src/core/config/Settings.java @@ -113,7 +113,10 @@ private Settings(){} public static boolean cacheDerivatives = true; /** - * Denotes whether or not to cache Legrende polynomials + * Denotes whether or not to cache Legendre polynomials. + *

Note: The field name "cacheLegrendePolynomials" contains a historical typo + * (correct spelling: "cacheLegendrePolynomials"). The name is kept unchanged for + * API and configuration file compatibility. */ public static boolean cacheLegrendePolynomials = true; diff --git a/src/core/functions/GeneralFunction.java b/src/core/functions/GeneralFunction.java index 5110bb5a..bc62e832 100644 --- a/src/core/functions/GeneralFunction.java +++ b/src/core/functions/GeneralFunction.java @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.Iterator; import java.util.Map; import java.util.function.Function; @@ -52,9 +53,13 @@ public abstract class GeneralFunction implements Evaluable, Differentiable, Simp }; /** - * Caches derivatives with the key corresponding to the {@code varID} of the derivative + * Caches derivatives with the key corresponding to the {@code varID} of the derivative. + *

Thread-Safety: Using {@link java.util.concurrent.ConcurrentHashMap} to allow + * concurrent get() and put() operations without explicit locking. Required for parallel + * Jacobian construction (e.g. {@code IntStream.parallel()} in CMDSolver). + * A plain {@code HashMap} would cause race conditions under concurrent access. */ - protected final Map derivatives = new HashMap<>(); + protected final Map derivatives = new ConcurrentHashMap<>(); /** * Returns a String representation of this {@link GeneralFunction} diff --git a/src/core/tools/functiongenerators/LegrendePolynomial.java b/src/core/tools/functiongenerators/LegrendePolynomial.java index 491b6f51..fca4bdef 100644 --- a/src/core/tools/functiongenerators/LegrendePolynomial.java +++ b/src/core/tools/functiongenerators/LegrendePolynomial.java @@ -10,16 +10,25 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import static java.lang.Math.*; import static core.tools.MiscTools.*; /** - * The methods in {@link LegrendePolynomial} deal with Legrende Polynomials. + * The methods in {@link LegrendePolynomial} deal with + * Legendre Polynomials. + *

Note: The class name "LegrendePolynomial" contains a historical typo + * (correct spelling: "LegendrePolynomial"). The name is kept unchanged for API compatibility. */ public class LegrendePolynomial { - private static final Map cache = new HashMap<>(); + /** + * Thread-safe cache using ConcurrentHashMap. + * A plain HashMap would cause race conditions under concurrent access + * (multiple threads calling makeLegrendePolynomial() simultaneously). + */ + private static final Map cache = new ConcurrentHashMap<>(); private static final String defaultVariable = "\\var"; private static GeneralFunction makeLegrendePolynomial(int n) { diff --git a/src/parsing/LatexReplacer.java b/src/parsing/LatexReplacer.java index ad776fdb..a769c226 100644 --- a/src/parsing/LatexReplacer.java +++ b/src/parsing/LatexReplacer.java @@ -33,7 +33,7 @@ private LatexReplacer(){} put(Pattern.compile("\\\\epsilon" + "(?![\\w.'[^\\x00-\\x7F]])"), "ϵ"); put(Pattern.compile("\\\\varepsilon" + "(?![\\w.'[^\\x00-\\x7F]])"), "ε"); put(Pattern.compile("\\\\Zeta" + "(?![\\w.'[^\\x00-\\x7F]])"), "Ζ"); - put(Pattern.compile("\\\\zeto" + "(?![\\w.'[^\\x00-\\x7F]])"), "ζ"); + put(Pattern.compile("\\\\zeta" + "(?![\\w.'[^\\x00-\\x7F]])"), "ζ"); // Fix: was "\\zeto" (typo) put(Pattern.compile("\\\\Eta" + "(?![\\w.'[^\\x00-\\x7F]])"), "Η"); put(Pattern.compile("\\\\eta" + "(?![\\w.'[^\\x00-\\x7F]])"), "η"); put(Pattern.compile("\\\\Theta" + "(?![\\w.'[^\\x00-\\x7F]])"), "Θ");