Prime engine: generation, primality, factorization











up vote
0
down vote

favorite












I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



Interfaces



public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}


Implementation



public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;

public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}

private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;

if (IsPrime(low))
{
_primeCollection.Add(low);
}

if (IsPrime(high))
{
_primeCollection.Add(high);
}

_indexFactor += 1;
_maxChecked = high;
}

private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}

public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}

private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}

private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}

private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}

private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}

public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}

public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;

while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}

if (value != 1)
{
yield return value;
}
}

public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}









share|improve this question
























  • The two first interfaces are identical - a copy/paste mistake?
    – t3chb0t
    5 mins ago















up vote
0
down vote

favorite












I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



Interfaces



public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}


Implementation



public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;

public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}

private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;

if (IsPrime(low))
{
_primeCollection.Add(low);
}

if (IsPrime(high))
{
_primeCollection.Add(high);
}

_indexFactor += 1;
_maxChecked = high;
}

private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}

public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}

private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}

private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}

private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}

private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}

public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}

public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;

while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}

if (value != 1)
{
yield return value;
}
}

public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}









share|improve this question
























  • The two first interfaces are identical - a copy/paste mistake?
    – t3chb0t
    5 mins ago













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



Interfaces



public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}


Implementation



public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;

public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}

private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;

if (IsPrime(low))
{
_primeCollection.Add(low);
}

if (IsPrime(high))
{
_primeCollection.Add(high);
}

_indexFactor += 1;
_maxChecked = high;
}

private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}

public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}

private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}

private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}

private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}

private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}

public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}

public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;

while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}

if (value != 1)
{
yield return value;
}
}

public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}









share|improve this question















I've just written my first C# class, so I'm looking for some feedback before I go and write more code. The goal of the code is to provide a Singleton-like class to deal with common operations on the set of prime numbers that I will need to complete projecteuler.net problems.



I'm interested in feedback for all aspects of the implementation (short of the actual prime generation algorithms, the 6*i +/- 1 method was used solely for its simplicity).



I'm also interested in feedback about how the interfaces are split up. I split these up into slices of functionality in an attempt to allow future implementation changes. I am planning to use DI (e.g. SimpleInjector) to bind the singleton instance to each of the interfaces, but I'm seriously starting to doubt this pattern.



I'm less interested in feedback about the selections of methods, I just chose a relatively minimal subset of methods that I know that I will need at some point - more methods will probably be added as needed.



Interfaces



public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeGenerator
{
IEnumerable<long> PrimesUntilValue(long value);
IEnumerable<long> PrimesUntilCount(int count);
}

public interface IPrimeFactorizer
{
IEnumerable<long> PrimeFactors(long value);
IEnumerable<long> UniquePrimeFactors(long value);
}


Implementation



public class PrimeEngine: IPrimeGenerator, IPrimeChecker, IPrimeFactorizer
{
private readonly ICollection<long> _primeCollection;
private long _indexFactor;
private long _maxChecked;

public PrimeEngine()
{
_primeCollection = new Collection<long> {2, 3};
_indexFactor = 1;
_maxChecked = 3;
}

private void CheckNextPossiblePrimeDoublet()
{
var low = 6 * _indexFactor - 1;
var high = low + 2;

if (IsPrime(low))
{
_primeCollection.Add(low);
}

if (IsPrime(high))
{
_primeCollection.Add(high);
}

_indexFactor += 1;
_maxChecked = high;
}

private IEnumerable<long> GetPossibleSmallerPrimeFactors(long value)
{
FillPrimesUntilRoot(value);
return PrimesUntilRoot(value);
}

public bool IsPrime(long value)
{
var primePool = GetPossibleSmallerPrimeFactors(value);
return primePool.All(prime => value % prime != 0);
}

private void FillPrimesUntilValue(long value)
{
while (_maxChecked < value)
{
CheckNextPossiblePrimeDoublet();
}
}

private void FillPrimesUntilCount(int count)
{
while (_primeCollection.Count < count)
{
CheckNextPossiblePrimeDoublet();
}
}

private static long FloorOfRoot(long value)
{
return (long) Math.Floor(Math.Sqrt(value));
}

private void FillPrimesUntilRoot(long value)
{
FillPrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimesUntilValue(long value)
{
FillPrimesUntilValue(value);
return _primeCollection.TakeWhile(prime => prime <= value);
}

public IEnumerable<long> PrimesUntilCount(int count)
{
FillPrimesUntilCount(count);
return _primeCollection.Take(count);
}

public IEnumerable<long> PrimesUntilRoot(long value)
{
return PrimesUntilValue(FloorOfRoot(value));
}

public IEnumerable<long> PrimeFactors(long value)
{
FillPrimesUntilRoot(value);
foreach (var prime in PrimesUntilRoot(value))
{
if (prime > value) break;

while (value % prime == 0)
{
yield return prime;
value /= prime;
}
}

if (value != 1)
{
yield return value;
}
}

public IEnumerable<long> UniquePrimeFactors(long value)
{
return PrimeFactors(value).Distinct();
}
}






c# beginner primes






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 4 mins ago









t3chb0t

33.7k744108




33.7k744108










asked 4 hours ago









Jared Goguen

777312




777312












  • The two first interfaces are identical - a copy/paste mistake?
    – t3chb0t
    5 mins ago


















  • The two first interfaces are identical - a copy/paste mistake?
    – t3chb0t
    5 mins ago
















The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
5 mins ago




The two first interfaces are identical - a copy/paste mistake?
– t3chb0t
5 mins ago















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208424%2fprime-engine-generation-primality-factorization%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208424%2fprime-engine-generation-primality-factorization%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin