Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions #5

Merged
merged 3 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 30 additions & 34 deletions TheSquid.Numerics.Extensions/PowCachedExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;

namespace TheSquid.Numerics
{
Expand All @@ -16,11 +17,6 @@ public static partial class PowCachedExtension
/// </summary>
private static Dictionary<ValueTuple<BigInteger, int>, ValueTuple<BigInteger, long>> powCache;

/// <summary>
/// Cache access synchronization object.
/// </summary>
private static Object syncObject;

/// <summary>
/// Life time counter for sort items by age.
/// </summary>
Expand All @@ -37,7 +33,6 @@ public static partial class PowCachedExtension
static PowCachedExtension()
{
powCache = new Dictionary<ValueTuple<BigInteger, int>, ValueTuple<BigInteger, long>>();
syncObject = new Object();
itemsLifetime = 0;
}

Expand Down Expand Up @@ -70,26 +65,27 @@ public static BigInteger Pow(this ref BigInteger basement, int exponent)
/// <returns>
/// The result of raising basement to the exponent power.
/// </returns>
[MethodImpl(MethodImplOptions.Synchronized)]
public static BigInteger PowCached(this ref BigInteger basement, int exponent)
{
lock (syncObject)
try
{
try
{
if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2);
return CalculateNewValue(ref basement, exponent);
}
catch (OutOfMemoryException)
{
if (powCache.LongCount() > 0) ShrinkCacheData(0);
return CalculateNewValue(ref basement, exponent);
}
const string negativeExponentMessage = "Negative exponent values are not supported.";
if (exponent < 0) throw new ArgumentOutOfRangeException(negativeExponentMessage);
if (itemsLifetime >= int.MaxValue) ShrinkCacheData(powCache.LongCount() / 2);
return CalculateNewValue(ref basement, exponent);
}
catch (OutOfMemoryException)
{
if (powCache.LongCount() > 0) ShrinkCacheData(0);
return CalculateNewValue(ref basement, exponent);
}
}

/// <summary>
/// Get power result from cache.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryGetValue(ref BigInteger basement, int exponent, out BigInteger power)
{
var key = new ValueTuple<BigInteger, int>(basement, exponent);
Expand All @@ -102,6 +98,7 @@ private static bool TryGetValue(ref BigInteger basement, int exponent, out BigIn
/// <summary>
/// Put power result to cache.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CacheNewValue(ref BigInteger basement, int exponent, BigInteger power)
{
var key = new ValueTuple<BigInteger, int>(basement, exponent);
Expand All @@ -112,6 +109,7 @@ private static void CacheNewValue(ref BigInteger basement, int exponent, BigInte
/// <summary>
/// Calculate new power value.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static BigInteger CalculateNewValue(ref BigInteger basement, int exponent)
{
if (exponent == 0) return 1;
Expand All @@ -136,26 +134,24 @@ private static BigInteger CalculateNewValue(ref BigInteger basement, int exponen
/// <remarks>
/// Associated items count value in the ItemsCount property.
/// </remarks>
[MethodImpl(MethodImplOptions.Synchronized)]
public static void ShrinkCacheData(long itemsInCache)
{
lock (syncObject)
if (itemsInCache == 0)
{
if (powCache.LongCount() == 0) return;
itemsLifetime = 0;
powCache.Clear();
GC.Collect();
GC.WaitForPendingFinalizers();
}
else
{
if (itemsInCache == 0)
{
if (powCache.LongCount() == 0) return;
itemsLifetime = 0;
powCache.Clear();
GC.Collect();
GC.WaitForPendingFinalizers();
}
else
{
itemsLifetime = 0;
powCache = powCache
.OrderBy(p => p.Value.Item2)
.Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue))
.ToDictionary(p => p.Key, p => new ValueTuple<BigInteger, long>(p.Value.Item1, ++itemsLifetime));
}
itemsLifetime = 0;
powCache = powCache
.OrderBy(p => p.Value.Item2)
.Skip((int)Math.Min(powCache.LongCount() - itemsInCache, int.MaxValue))
.ToDictionary(p => p.Key, p => new ValueTuple<BigInteger, long>(p.Value.Item1, ++itemsLifetime));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<LangVersion>7.3</LangVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageTags>BigInteger;Nth;Root;Random;Power;Cache;Numerics;Extension;Math</PackageTags>
<PackageTags>BigInteger;Nth;Root;Random;Next;Power;Cache;Numerics;Extension;Math</PackageTags>
</PropertyGroup>

<PropertyGroup>
Expand Down