commit 0606211a1e8e0a5011f0213e982e6d9fac285285
parent 605f11cae7a35fdd65bf207c77837b85008de6dd
Author: dracuxan <[email protected]>
Date: Mon, 27 Apr 2026 16:08:36 +0530
feet: change c-based random number generator to rust based nif
Diffstat:
21 files changed, 439 insertions(+), 56 deletions(-)
diff --git a/lib/genetic.ex b/lib/genetic.ex
@@ -1,12 +1,5 @@
defmodule Genetic do
alias Types.Chromosome
- @on_load :load_nif
- def load_nif do
- path = ~c"./priv/genetic"
- :erlang.load_nif(path, 0)
- end
-
- def xor96, do: 0
def run(problem, opts \\ []) do
population = initialize(&problem.genotype/0, opts)
@@ -58,7 +51,12 @@ defmodule Genetic do
end
def crossover(population, opts \\ []) do
- crossover_fn = Keyword.get(opts, :crossover_type, &Toolbox.Crossover.single_point/3)
+ crossover_fn =
+ Keyword.get(
+ opts,
+ :crossover_type,
+ &Toolbox.Crossover.single_point/3
+ )
population
|> Enum.reduce(
@@ -103,7 +101,13 @@ defmodule Genetic do
end
def reinsertion(parents, offsprings, leftover, opts \\ []) do
- strategy = Keyword.get(opts, :reinsertion_strategy, &Toolbox.Reinsertion.uniform/4)
+ strategy =
+ Keyword.get(
+ opts,
+ :reinsertion_strategy,
+ &Toolbox.Reinsertion.uniform/4
+ )
+
apply(strategy, [parents, offsprings, leftover, opts])
end
diff --git a/lib/genetic/random.ex b/lib/genetic/random.ex
@@ -0,0 +1,7 @@
+defmodule Genetic.Random do
+ use Rustler, otp_app: :genetic, crate: :random
+
+ def xor96, do: error()
+
+ defp error, do: :erlang.nif_error(:nif_not_loaded)
+end
diff --git a/lib/genetic/tree.ex b/lib/genetic/tree.ex
@@ -0,0 +1,7 @@
+defmodule Genetic.Tree do
+ use Rustler, otp_app: :genetic, crate: :tree
+
+ def add(_a, _b), do: error()
+
+ defp error, do: :erlang.nif_error(:nif_not_loaded)
+end
diff --git a/lib/toolbox/crossover.ex b/lib/toolbox/crossover.ex
@@ -31,7 +31,7 @@ defmodule Toolbox.Crossover do
end
def single_point(p1, p2, _opts \\ []) do
- cx_point = rem(Genetic.xor96(), length(p1.genes))
+ cx_point = rem(Genetic.Random.xor96(), length(p1.genes))
{{head1, tail1}, {head2, tail2}} =
{Enum.split(p1.genes, cx_point), Enum.split(p2.genes, cx_point)}
diff --git a/mix.exs b/mix.exs
@@ -1,27 +1,3 @@
-defmodule Mix.Tasks.Compile.Cnif do
- use Mix.Task.Compiler
-
- def run(_args) do
- File.mkdir_p!("priv")
-
- {output, code} =
- System.cmd(
- "gcc",
- [
- "-fpic",
- "-shared",
- "-o",
- "priv/random.so",
- "src/random.c"
- ],
- stderr_to_stdout: true
- )
-
- IO.puts(output)
- if code == 0, do: :ok, else: {:error, []}
- end
-end
-
defmodule Genetic.MixProject do
use Mix.Project
@@ -31,7 +7,7 @@ defmodule Genetic.MixProject do
version: "0.1.0",
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
- compilers: [:cnif] ++ Mix.compilers(),
+ compilers: Mix.compilers(),
deps: deps()
]
end
@@ -51,7 +27,8 @@ defmodule Genetic.MixProject do
{:gnuplot, "~> 1.22"},
{:benchee, "~> 1.5.0"},
{:exprof, "~> 0.2.4"},
- {:alex, "~> 0.3.2"}
+ {:alex, "~> 0.3.2"},
+ {:rustler, "~> 0.31.0"}
]
end
end
diff --git a/mix.lock b/mix.lock
@@ -7,10 +7,13 @@
"exprintf": {:hex, :exprintf, "0.2.1", "b7e895dfb00520cfb7fc1671303b63b37dc3897c59be7cbf1ae62f766a8a0314", [:mix], [], "hexpm", "20a0e8c880be90e56a77fcc82533c5d60c643915c7ce0cc8aa1e06ed6001da28"},
"exprof": {:hex, :exprof, "0.2.4", "13ddc0575a6d24b52e7c6809d2a46e9ad63a4dd179628698cdbb6c1f6e497c98", [:mix], [{:exprintf, "~> 0.2", [hex: :exprintf, repo: "hexpm", optional: false]}], "hexpm", "0884bcb66afc421c75d749156acbb99034cc7db6d3b116c32e36f32551106957"},
"gnuplot": {:hex, :gnuplot, "1.22.270", "541da1d4be2acbcb2a53105a7c2f31d91127811858b522c1a2290ed5844b9624", [:mix], [{:ex_doc, "~> 0.28", [hex: :ex_doc, repo: "hexpm", optional: false]}], "hexpm", "2870982804ac79a93eebf31c07a507a1825bc23c782907da48d653cf970a4d41"},
+ "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
"libgraph": {:hex, :libgraph, "0.16.0", "3936f3eca6ef826e08880230f806bfea13193e49bf153f93edcf0239d4fd1d07", [:mix], [], "hexpm", "41ca92240e8a4138c30a7e06466acc709b0cbb795c643e9e17174a178982d6bf"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.3", "4252d5d4098da7415c390e847c814bad3764c94a814a0b4245176215615e1035", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "953297c02582a33411ac6208f2c6e55f0e870df7f80da724ed613f10e6706afd"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
+ "rustler": {:hex, :rustler, "0.31.0", "7e5eefe61e6e6f8901e5aa3de60073d360c6320d9ec363027b0197297b80c46a", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "99e378459bfb9c3bda6d3548b2b3bc6f9ad97f728f76bdbae7bf5c770a4f8abd"},
"statistex": {:hex, :statistex, "1.1.0", "7fec1eb2f580a0d2c1a05ed27396a084ab064a40cfc84246dbfb0c72a5c761e5", [:mix], [], "hexpm", "f5950ea26ad43246ba2cce54324ac394a4e7408fdcf98b8e230f503a0cba9cf5"},
+ "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
}
diff --git a/native/random/.cargo/config.toml b/native/random/.cargo/config.toml
@@ -0,0 +1,5 @@
+[target.'cfg(target_os = "macos")']
+rustflags = [
+ "-C", "link-arg=-undefined",
+ "-C", "link-arg=dynamic_lookup",
+]
diff --git a/native/random/.gitignore b/native/random/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/native/random/Cargo.lock b/native/random/Cargo.lock
@@ -0,0 +1,149 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "random"
+version = "0.1.0"
+dependencies = [
+ "rustler",
+]
+
+[[package]]
+name = "regex"
+version = "1.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+
+[[package]]
+name = "rustler"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75d458f38f550976d0e4b347ca57241c192019777e46af7af73b27783287088"
+dependencies = [
+ "lazy_static",
+ "rustler_codegen",
+ "rustler_sys",
+]
+
+[[package]]
+name = "rustler_codegen"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbd46408f51c0ca6a68dc36aa4f90e3554960bd1b7cc513e6ff2ccad7dd92aff"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "rustler_sys"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff76ba8524729d7c9db2b3e80f2269d1fdef39b5a60624c33fd794797e69b558"
+dependencies = [
+ "regex",
+ "unreachable",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unreachable"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+dependencies = [
+ "void",
+]
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
diff --git a/native/random/Cargo.toml b/native/random/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "random"
+version = "0.1.0"
+authors = []
+edition = "2021"
+
+[lib]
+name = "random"
+path = "src/lib.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+rustler = "0.31.0"
diff --git a/native/random/README.md b/native/random/README.md
@@ -0,0 +1,20 @@
+# NIF for Elixir.Random
+
+## To build the NIF module:
+
+- Your NIF will now build along with your project.
+
+## To load the NIF:
+
+```elixir
+defmodule Random do
+ use Rustler, otp_app: :genetic, crate: "random"
+
+ # When your NIF is loaded, it will override this function.
+ def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
+end
+```
+
+## Examples
+
+[This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust.
diff --git a/native/random/src/lib.rs b/native/random/src/lib.rs
@@ -0,0 +1,20 @@
+use rustler::NifResult;
+use std::sync::Mutex;
+
+static RNG_STATE: Mutex<(u32, u32, u32)> = Mutex::new((123_456_789, 362_436_069, 52_128_629));
+
+#[rustler::nif]
+fn xor96() -> NifResult<u32> {
+ let mut state = RNG_STATE.lock().unwrap();
+
+ let (ref mut x, ref mut y, ref mut z) = *state;
+
+ let t = *x ^ (*x << 10);
+ *x = *y;
+ *y = *z;
+ *z = (*z ^ (*z >> 26)) ^ (t ^ (t >> 5));
+
+ Ok(*z)
+}
+
+rustler::init!("Elixir.Genetic.Random", [xor96]);
diff --git a/native/tree/.cargo/config.toml b/native/tree/.cargo/config.toml
@@ -0,0 +1,5 @@
+[target.'cfg(target_os = "macos")']
+rustflags = [
+ "-C", "link-arg=-undefined",
+ "-C", "link-arg=dynamic_lookup",
+]
diff --git a/native/tree/.gitignore b/native/tree/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/native/tree/Cargo.lock b/native/tree/Cargo.lock
@@ -0,0 +1,149 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "memchr"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+
+[[package]]
+name = "rustler"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75d458f38f550976d0e4b347ca57241c192019777e46af7af73b27783287088"
+dependencies = [
+ "lazy_static",
+ "rustler_codegen",
+ "rustler_sys",
+]
+
+[[package]]
+name = "rustler_codegen"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbd46408f51c0ca6a68dc36aa4f90e3554960bd1b7cc513e6ff2ccad7dd92aff"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "rustler_sys"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff76ba8524729d7c9db2b3e80f2269d1fdef39b5a60624c33fd794797e69b558"
+dependencies = [
+ "regex",
+ "unreachable",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tree"
+version = "0.1.0"
+dependencies = [
+ "rustler",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unreachable"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+dependencies = [
+ "void",
+]
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
diff --git a/native/tree/Cargo.toml b/native/tree/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "tree"
+version = "0.1.0"
+authors = []
+edition = "2021"
+
+[lib]
+name = "tree"
+path = "src/lib.rs"
+crate-type = ["cdylib"]
+
+[dependencies]
+rustler = "0.31.0"
diff --git a/native/tree/README.md b/native/tree/README.md
@@ -0,0 +1,20 @@
+# NIF for Elixir.Tree
+
+## To build the NIF module:
+
+- Your NIF will now build along with your project.
+
+## To load the NIF:
+
+```elixir
+defmodule Tree do
+ use Rustler, otp_app: :genetic, crate: "tree"
+
+ # When your NIF is loaded, it will override this function.
+ def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
+end
+```
+
+## Examples
+
+[This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust.
diff --git a/native/tree/src/lib.rs b/native/tree/src/lib.rs
@@ -0,0 +1,6 @@
+#[rustler::nif]
+fn add(a: i64, b: i64) -> i64 {
+ a + b
+}
+
+rustler::init!("Elixir.Genetic.Tree", [add]);
diff --git a/scripts/n_queens.exs b/scripts/n_queens.exs
@@ -37,9 +37,9 @@ defmodule NQueens do
def map_queens(soln) do
size = length(soln)
- for i <- 1..size do
+ for i <- 0..(size - 1) do
row_string =
- for j <- 1..size do
+ for j <- 0..(size - 1) do
if(Enum.at(soln, i) == j) do
" Q "
else
diff --git a/scripts/tetris.exs b/scripts/tetris.exs
@@ -44,6 +44,6 @@ defmodule Tetris do
def terminate?(_population, generation), do: generation == 5
end
-TetrisInterface.start_link("/home/dracuxan/elixir/src/genetic/genetic/games/tetris.bin")
+TetrisInterface.start_link("/home/dracuxan/elixir/src/genetic/games/tetris.bin")
soln = Genetic.run(Tetris, population_size: 10)
IO.puts("\nbest: #{inspect(soln)}")
diff --git a/src/random.c b/src/random.c
@@ -1,17 +0,0 @@
-#include <erl_nif.h>
-#include <inttypes.h>
-#include <stdint.h>
-
-static uint32_t x = 123456789, y = 362436069, z = 52128629;
-
-static ERL_NIF_TERM xor96(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
- uint32_t t = (x ^ (x << 10));
- x = y;
- y = z;
- z = (z ^ (z >> 26)) ^ (t ^ (t >> 5));
-
- return enif_make_int(env, z);
-}
-
-static ErlNifFunc nif_funcs[] = {{"xor96", 0, xor96}};
-ERL_NIF_INIT(Elixir.Genetic, nif_funcs, NULL, NULL, NULL, NULL);