From 5b0d820de7a4105169d6210764d5b58fd16959e7 Mon Sep 17 00:00:00 2001 From: Vladyslav Shtabovenko Date: Sat, 12 Feb 2022 23:36:40 +0100 Subject: [PATCH] Replaced ToString-based caching function with the standard Hash (thanks to J. Park aka j824h for reporting issue #151) --- FeynCalc/Shared/CacheManagement.m | 97 +++++++++++++++++++------------ Tests/Dirac/DiracTrick.test | 11 +++- 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/FeynCalc/Shared/CacheManagement.m b/FeynCalc/Shared/CacheManagement.m index b1e940c1c..fb6b486c4 100755 --- a/FeynCalc/Shared/CacheManagement.m +++ b/FeynCalc/Shared/CacheManagement.m @@ -6,9 +6,9 @@ (* This software is covered by the GNU General Public License 3. - Copyright (C) 1990-2020 Rolf Mertig - Copyright (C) 1997-2020 Frederik Orellana - Copyright (C) 2014-2020 Vladyslav Shtabovenko + Copyright (C) 1990-2021 Rolf Mertig + Copyright (C) 1997-2021 Frederik Orellana + Copyright (C) 2014-2021 Vladyslav Shtabovenko *) (* :Summary: Functions for managing memoization in FeynCalc *) @@ -16,40 +16,41 @@ (* ------------------------------------------------------------------------ *) FCUseCache::usage= -"FCUseCache[func,{arg1,...},{opt1...}] evaluates \ -func[arg1,...,opt1,...] and caches the result such that the \ -next evaluation of same expressions occurs almost immediately. \ -This caching also takes into account DownValues and global variables \ -that enter into evaluation of func. For example, ExpandScalarProduct \ -can't be naively cached, because it's result depends on the DownValues \ -of Pair and ScalarProduct, which may be changed multiple times during \ -the session by setting and erasing values of scalar products. With \ -FCUseCache, however, caching will work properly, as FCUseCache knows \ -the dependence on ExpandScalarProduct on those DownValues. \ -\ -For all this to work, a function should be explicitly whitelisted in FCUseCache."; +"FCUseCache[func,{arg1,...},{opt1...}] evaluates func[arg1,...,opt1,...] and +caches the result such that the next evaluation of same expressions occurs +almost immediately. This caching also takes into account DownValues and global +variables that enter into evaluation of func. + +For example, ExpandScalarProduct can't be naively cached, because its result +depends on the DownValues of Pair and ScalarProduct, which may be changed +multiple times during the session by setting and erasing values of scalar +products. With FCUseCache, however, caching will work properly, as FCUseCache +knows the dependence on ExpandScalarProduct on those DownValues. For all this +to work, a function should be explicitly white-listed in FCUseCache."; FCShowCache::usage = -"FCShowCache[func] shows existing cached values for the function func, that \ -were introduced by FCUseCache"; +"FCShowCache[func] shows existing cached values for the function func, that +were introduced by FCUseCache."; FCClearCache::usage = -"FCClearCache[func] removes existing cached values for the function func, that \ -were introduced by FCUseCache"; +"FCClearCache[func] removes existing cached values for the function func that +were introduced by FCUseCache. + +To remove all existing cache values use FCClearCache[All]."; FCUseCache::blacklist= -"The function `1` is not whitelisted for FCUseCache. Evaluation aborted!" +"The function `1` is not whitelisted for FCUseCache. Evaluation aborted!"; + +FCUseCache::fail= +"Error! FCUseCache has encountered a fatal problem and must abort the computation. \ +The problem reads: `1`"; -Begin["`Package`"] +Begin["`Package`"]; End[] (* ------------------------------------------------------------------------ *) -Begin["`CacheManagement`Private`"] - - -SetAttributes[cachedToString, HoldAll] - +Begin["`CacheManagement`Private`"]; whiteListNames = { ExpandScalarProduct, @@ -57,16 +58,24 @@ FCFastContract, FeynCalc`NPointTo4Point`Private`getDet, FeynCalc`SimplifyPolyLog`Private`simplifyArgument, - FeynCalc`FCApart`Private`pfracRaw + FeynCalc`FCApart`Private`pfracRaw, + FeynCalc`Package`momentumRoutingDenner }; +standardSetAssociation = {}; + +If[ $VersionNumber >= 10. , + standardSetAssociation = Association[{}]; +]; + FCUseCache[fcFunc_, args_List, opts_List: {}] := - Block[{fullOpts, cachedHead,depArgs, standardSet}, + Block[{fullOpts, cachedHead,depArgs, standardSet, savedStandardSet}, fullOpts = Sort[Flatten[Join[opts, FilterRules[Options[fcFunc], Except[opts]]]]]; cachedHead=ToExpression["cacheFunc"<>ToString[fcFunc]]; If[ MemberQ[whiteListNames,fcFunc], - cachedHead[arg_, cargs_String, ops_] := + + cachedHead[arg_, cargs_, ops_] := MemSet[cachedHead[arg, cargs, ops], fcFunc[Sequence @@ arg, ops]], Message[FCUseCache::blacklist,fcFunc]; Abort[] @@ -80,21 +89,35 @@ Which[ fcFunc === ExpandScalarProduct, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], fcFunc === PairContract, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], fcFunc === FCFastContract, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], fcFunc === FeynCalc`NPointTo4Point`Private`getDet, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], fcFunc === FeynCalc`SimplifyPolyLog`Private`simplifyArgument, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], fcFunc === FeynCalc`FCApart`Private`pfracRaw, - depArgs = cachedToString[standardSet], + depArgs = Hash[standardSet], + fcFunc === FeynCalc`Package`momentumRoutingDenner, + depArgs = Hash[standardSet], True, Message[FCUseCache::blacklist,fcFunc]; Abort[] ]; + + If[ $VersionNumber >= 10. , + savedStandardSet = Key[depArgs][standardSetAssociation]; + If[ MissingQ[savedStandardSet], + standardSetAssociation = Append[standardSetAssociation,{depArgs -> standardSet}], + If[ savedStandardSet=!=standardSet, + Message[FCUseCache::fail,"Hash collision detected."]; + Abort[] + ]; + ]; + ]; + cachedHead[args,depArgs,fullOpts] ]; @@ -105,8 +128,8 @@ With[{i = ToExpression["cacheFunc" <> ToString[fcFunc]]},DownValues[i] = {};]; -cachedToString[x_] := - cachedToString[x] = ToString[x]; +FCClearCache[All]:= + FCClearCache /@ whiteListNames; FCPrint[1,"CacheManagement.m loaded"]; diff --git a/Tests/Dirac/DiracTrick.test b/Tests/Dirac/DiracTrick.test index b9bab9615..54f8480d1 100644 --- a/Tests/Dirac/DiracTrick.test +++ b/Tests/Dirac/DiracTrick.test @@ -1129,7 +1129,16 @@ Momentum[p1, D], 0, 1] + Spinor[Momentum[p3, D], m, 1].GAD[Lor4].GSD[p3].GAD[Lor {"fcstDiracTrickCoreProperties-ID122", "FCSetDiracGammaScheme[\"NDR\"]\n DiracTrick[GAD[mu].(cc1 + cc2 GA[5]).(GSD[p] + m).GAD[rho], FCE -> True]", "cc1 GAD[mu].(m + GSD[p]).GAD[rho] + cc2 GAD[mu].(-m + GSD[p]).GAD[rho].GA[5]"}, {"fcstDiracTrickCoreProperties-ID123", -"DiracTrick[GAD[mu].DiracGamma[ExplicitLorentzIndex[i, D], D].GAD[mu]]", "(2 - D) DiracGamma[ExplicitLorentzIndex[i, D], D]"} +"DiracTrick[GAD[mu].DiracGamma[ExplicitLorentzIndex[i, D], D].GAD[mu]]", "(2 - D) DiracGamma[ExplicitLorentzIndex[i, D], D]"}, +{"fcstDiracTrickCoreProperties-ID124", +"FCClearScalarProducts[]; SP[p1, p2] = s2; +SP[p1, p3] = s3; DiracTrick[ +DiracGamma[Momentum[p2 + p3]] . DiracGamma[Momentum[p1]] . +DiracGamma[Momentum[p2 + p3]], FCE -> True]", "2*(s2 + s3)*GS[p2 + p3] - GS[p1]*(SP[p2, p2] + 2*SP[p2, p3] + SP[p3, p3])"}, +{"fcstDiracTrickCoreProperties-ID125", +"FCClearScalarProducts[]; DiracTrick[ +DiracGamma[Momentum[p2 + p3]] . DiracGamma[Momentum[p1]] . +DiracGamma[Momentum[p2 + p3]], FCE -> True]", "2*GS[p2 + p3]*SP[p1, p2 + p3] - GS[p1]*(SP[p2, p2] + 2*SP[p2, p3] + SP[p3, p3])"} }); Tests`Dirac`fcstDiracTrick = {