From 7864da27017b9c7f006aae14aa84665235d18e0e Mon Sep 17 00:00:00 2001 From: Jordan Wages Date: Sat, 27 Jun 2026 23:49:20 -0500 Subject: [PATCH] Fibonacci and Identity functions --- .../Functions/NumberTheory/Fibonacci.cs | 76 ++++++ .../Functions/NumberTheory/Identity.cs | 228 ++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 src/StandardLibrary/Functions/NumberTheory/Fibonacci.cs create mode 100644 src/StandardLibrary/Functions/NumberTheory/Identity.cs diff --git a/src/StandardLibrary/Functions/NumberTheory/Fibonacci.cs b/src/StandardLibrary/Functions/NumberTheory/Fibonacci.cs new file mode 100644 index 0000000..932aa41 --- /dev/null +++ b/src/StandardLibrary/Functions/NumberTheory/Fibonacci.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions.NumberTheory +{ + /// + public class Fibonacci : FunctionBase, ICodedFunction + { + + /// A pre-computed array of the first 140 numbers of the fibonacci sequence. + private static decimal[] fibonacciSequence = + [0m, 1m, 1m, 2m, 3m, 5m, 8m, 13m, 21m, 34m, 55m, 89m, 144m, 233m, 377m, 610m, + 987m, 1597m, 2584m, 4181m, 6765m, 10946m, 17711m, 28657m, 46368m, 75025m, 121393m, + 196418m, 317811m, 514229m, 832040m, 1346269m, 2178309m, 3524578m, 5702887m, 9227465m, + 14930352m, 24157817m, 39088169m, 63245986m, 102334155m, 165580141m, 267914296m, + 433494437m, 701408733m, 1134903170m, 1836311903m, 2971215073m, 4807526976m, 7778742049m, + 12586269025m, 20365011074m, 32951280099m, 53316291173m, 86267571272m, 139583862445m, + 225851433717m, 365435296162m, 591286729879m, 956722026041m, 1548008755920m, 2504730781961m, + 4052739537881m, 6557470319842m, 10610209857723m, 17167680177565m, 27777890035288m, + 44945570212853m, 72723460248141m, 117669030460994m, 190392490709135m, 308061521170129m, + 498454011879264m, 806515533049393m, 1304969544928657m, 2111485077978050m, 3416454622906707m, + 5527939700884757m, 8944394323791464m, 14472334024676221m, 23416728348467685m, 37889062373143906m, + 61305790721611591m, 99194853094755497m, 160500643816367088m, 259695496911122585m, + 420196140727489673m, 679891637638612258m, 1100087778366101931m, 1779979416004714189m, + 2880067194370816120m, 4660046610375530309m, 7540113804746346429m, 12200160415121876738m, + 19740274219868223167m, 31940434634990099905m, 51680708854858323072m, 83621143489848422977m, + 135301852344706746049m, 218922995834555169026m, 354224848179261915075m, 573147844013817084101m, + 927372692193078999176m, 1500520536206896083277m, 2427893228399975082453m, 3928413764606871165730m, + 6356306993006846248183m, 10284720757613717413913m, 16641027750620563662096m, + 26925748508234281076009m, 43566776258854844738105m, 70492524767089125814114m, + 114059301025943970552219m, 184551825793033096366333m, 298611126818977066918552m, + 483162952612010163284885m, 781774079430987230203437m, 1264937032042997393488322m, + 2046711111473984623691759m, 3311648143516982017180081m, 5358359254990966640871840m, + 8670007398507948658051921m, 14028366653498915298923761m, 22698374052006863956975682m, + 36726740705505779255899443m, 59425114757512643212875125m, 96151855463018422468774568m, + 155576970220531065681649693m, 251728825683549488150424261m, 407305795904080553832073954m, + 659034621587630041982498215m, 1066340417491710595814572169m, 1725375039079340637797070384m, + 2791715456571051233611642553m, 4517090495650391871408712937m, 7308805952221443105020355490m, + 11825896447871834976429068427m, 19134702400093278081449423917m, 30960598847965113057878492344m, + 50095301248058391139327916261m]; + + public string Name + { + get + { + return "fib"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("index", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + + int index = Convert.ToInt32(input); + + if(index <= 0 || index > 140) + { + return FunctionValue.ZERO; + } + + return new FunctionValue(FunctionValueType.Numeric, fibonacciSequence[index]); + }); + } + } +} diff --git a/src/StandardLibrary/Functions/NumberTheory/Identity.cs b/src/StandardLibrary/Functions/NumberTheory/Identity.cs new file mode 100644 index 0000000..9f7b410 --- /dev/null +++ b/src/StandardLibrary/Functions/NumberTheory/Identity.cs @@ -0,0 +1,228 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Text; + +namespace CSMic.StandardLibrary.Functions.NumberTheory +{ + public class IsEven : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "iseven"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + + decimal value = Convert.ToDecimal(input); + + return new FunctionValue(FunctionValueType.Numeric, IsEven.CalculateIsEven(value) ? 1m : 0m); + }); + } + + internal static bool CalculateIsEven(decimal value) + { + return true; + } + } + + public class IsOdd : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "isodd"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + + decimal value = Convert.ToDecimal(input); + + return new FunctionValue(FunctionValueType.Numeric, IsEven.CalculateIsEven(value) ? 0m : 1m); + }); + } + } + + public class IsInt : FunctionBase, ICodedFunction + { + public string Name + { + get + { + return "isint"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + + decimal value = Convert.ToDecimal(input); + + return new FunctionValue(FunctionValueType.Numeric, CalculateIsInt(value) ? 1m : 0m); + }); + } + + internal static bool CalculateIsInt(decimal value) + { + return value == decimal.Truncate(value); + } + } + + public class IsPrime : FunctionBase, ICodedFunction + { + private const int MaxPrimeCacheSize = 4096; + + /// + /// (Immutable) The prime cache lock. Concurrency needs to be enforced here because caching is + /// transparent to library consumers and race conditions could be invisible at run-time. + /// + private static readonly object PrimeCacheLock = new object(); + private static readonly Dictionary PrimeCache = + new Dictionary(); + + private static readonly Queue PrimeCacheOrder = + new Queue(); + + private static readonly bool[] knownPrime = [ + false, false, true, true, false, true, false, true, false, false, + false, true, false, true, false, false, false, true, false, true, + false, false, false, true, false, false, false, false, false, true, + false, true, false, false, false, false, false, true, false, false, + false, true, false, true, false, false, false, true, false, false, + false, false, false, true, false, false, false, false, false, true, + false, true, false, false, false, false, false, true, false, false, + false, true, false, true, false, false, false, false, false, true, + false, false, false, true, false, false, false, false, false, true, + false, false, false, false, false, false, false, true, false, false]; + + public string Name + { + get + { + return "isprime"; + } + } + + public override IEnumerable ExpectedArguments + { + get + { + yield return new FunctionArgument("value", FunctionValue.NUMBER); + } + } + + public FunctionValue Execute(params FunctionArgument[] args) + { + return base.Execute(args, (_args) => + { + var input = _args[0].Value; + + decimal value = Convert.ToDecimal(input); + + return new FunctionValue(FunctionValueType.Numeric, CalculateIsPrime(value) ? 1m : 0m); + }); + } + + internal static bool CalculateIsPrime(decimal value) + { + if (!IsInt.CalculateIsInt(value) || value < 2m) + { + return false; + } + + if (value < knownPrime.Length) + { + return knownPrime[(int)value]; + } + + if (TryGetCachedPrime(value, out bool cached)) + { + return cached; + } + + if (value % 2m == 0m) + { + AddPrimeCache(value, false); + return false; + } + + for (decimal i = 3; i * i <= value; i += 2m) + { + if (value % i == 0m) + { + AddPrimeCache(value, false); + return false; + } + } + + AddPrimeCache(value, true); + return true; + } + + private static bool TryGetCachedPrime(decimal value, out bool result) + { + lock (PrimeCacheLock) + { + return PrimeCache.TryGetValue(value, out result); + } + } + + private static void AddPrimeCache(decimal value, bool result) + { + lock (PrimeCacheLock) + { + if (PrimeCache.ContainsKey(value)) + return; + + while (PrimeCache.Count >= MaxPrimeCacheSize) + { + decimal oldest = PrimeCacheOrder.Dequeue(); + PrimeCache.Remove(oldest); + } + + PrimeCache[value] = result; + PrimeCacheOrder.Enqueue(value); + } + } + } +}