From d68d05f1159bc9aadea5f6f5d9d4c0361a2059e5 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 6 Mar 2023 20:42:41 -0500 Subject: [PATCH 01/16] Dummy Function, add docs --- source/dutils/math/package.d | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/dutils/math/package.d b/source/dutils/math/package.d index aa6266b..825cc2c 100644 --- a/source/dutils/math/package.d +++ b/source/dutils/math/package.d @@ -10,12 +10,12 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .*/ -/** Copyright: 2022, Ruby The Roobster*/ -/**Author: Ruby The Roobster, */ -/**Date: January 19, 2022*/ -/** License: GPL-3.0**/ +/** Copyright: 2022-2023, Ruby The Roobster*/ +/**Author: Ruby The Roobster, */ +/**Date: March 6, 2023*/ +/** License: GPL-3.0*/ -///Dutils math library +/// Dutils math library module dutils.math; version(DLL) @@ -31,3 +31,5 @@ else import dutils.math.core; /// Implements complex numbers for the math library. import dutils.math.number; +/// Implements Summations +import dutils.math.summation; From 48e8971dc2223d20199f8b316c72cfcdade63f60 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 6 Mar 2023 21:04:03 -0500 Subject: [PATCH 02/16] Add precision, some headway --- source/dutils/math/summation.d | 90 ++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 source/dutils/math/summation.d diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d new file mode 100644 index 0000000..010858d --- /dev/null +++ b/source/dutils/math/summation.d @@ -0,0 +1,90 @@ +/*This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see .*/ +/** Copyright: 2022-2023, Ruby The Roobster*/ +/**Author: Ruby The Roobster, */ +/**Date: March 6, 2023*/ +/** License: GPL-3.0*/ + +/** Implements Summation Operator*/ +module dutils.math.summation; + +version(DLL) +{ + export: +} +else +{ + public: +} + +/// Definitions file +import dutils.math.def; + +private import dutils.math.core; +private import dutils.math.number; + +/********************************************************* + * Implements Summation + * + * Params: + * op = + * The arguments to be passed in. These are: + * A registered function, with its input + * specified n (the index), and whatever + * parameters from the function the operator was + * called in; The intial value of the index (real); + * and the maximum value of the index (real). + * + * Returns: + * A dstring containing the serialized value of the + * sum of the function about the index. + */ +dstring summation(dstring[] op) @safe +{ + dstring ret; + dstring func; // Store the function here. + assert(op.length == 3); + Number index = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); + dstring temp = ""d; + for(size_t i = 0; i < op[1].length; ++i) // Get the lower value of index first, it's easiest. + temp ~= op[1][i]; + index.fromDstring(temp); + + temp = ""d; + dstring[] paramTypes; + + static foreach(type; typel) // OH NO NOT THIS AGAIN + { + mixin(type ~ "[] temp" ~ type ~ ";"); + } + for(size_t i = 0; i < op[0].length; ++ i) // Get the values of the function paramaters + the index. + { + } + return ret; +} + +/// The precision to be used while doing the summation. +private size_t precision = 18; + +/*************************** + * Sets the precision. + * + * Params: + * prec = + * The new precision. + */ +void setPrecision(in size_t prec) @safe nothrow @nogc +{ + precision = prec; +} + From b3d6679b16bc94f464f249d79f05c6d6fb516b66 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Mon, 6 Mar 2023 21:29:23 -0500 Subject: [PATCH 03/16] Final commit of the day: Make some more headway --- source/dutils/math/summation.d | 42 ++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index 010858d..6124881 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -27,6 +27,9 @@ else public: } + +/// TODO: ADD RIEMANN SUMS WHEN DONE + /// Definitions file import dutils.math.def; @@ -43,7 +46,9 @@ private import dutils.math.number; * specified n (the index), and whatever * parameters from the function the operator was * called in; The intial value of the index (real); - * and the maximum value of the index (real). + * and the maximum value of the index (real); + * the types of the paramaters of the function, + * separated by commas. * * Returns: * A dstring containing the serialized value of the @@ -62,14 +67,47 @@ dstring summation(dstring[] op) @safe temp = ""d; dstring[] paramTypes; + dstring[] paramValues; static foreach(type; typel) // OH NO NOT THIS AGAIN { mixin(type ~ "[] temp" ~ type ~ ";"); } - for(size_t i = 0; i < op[0].length; ++ i) // Get the values of the function paramaters + the index. + size_t i; + for(i = 0; op[0][i] != d('('); ++i) // Get function name. + temp ~= op[0][i]; + + dstring temp2; + ++i; + for(; op[0][i] != d(')'); ++i) // Get the values of the function parameters. + { + if(op[0][i] == d(',')) + { + paramValues ~= temp2; + temp2 = ""d; + continue; + } + temp2 ~= op[0][i]; + } + + paramValues ~= temp2; // This last is cut off in the loop. + temp2 = ""d; + i += 2; + temp ~= "("d; + for(; op[0][i] != d(')'); ++i) // Get the function parameter types { + if(op[0][i] == d(',')) + { + paramTypes ~= temp2; + temp ~= d(','); + temp2 = ""d; + continue; + } + temp2 ~= op[0][i]; } + paramTypes ~= temp2; + temp ~= ")"d; + temp2 = ""d; return ret; } From 8cc85740db54377b6f500bba6ecd85f2e9918ca2 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 8 Mar 2023 21:21:08 -0500 Subject: [PATCH 04/16] Add operator comparison --- source/dutils/math/number.d | 59 +++++++++++++++++++++++++++++++++- source/dutils/math/summation.d | 6 ++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/source/dutils/math/number.d b/source/dutils/math/number.d index 976e5e5..9947723 100644 --- a/source/dutils/math/number.d +++ b/source/dutils/math/number.d @@ -270,7 +270,7 @@ class Number : Mtype!NumberContainer * op = * The operator to apply. * rhs = - * THe right hand side of the expression. + * The right hand side of the expression. * Returns: * The result of the expression. */ @@ -295,6 +295,21 @@ class Number : Mtype!NumberContainer { return (this.contained == rhs.contained); } + + /******************************************* + * Compare the magnitude (currently only + * the real part) of two numbers. + * + * Params: + * rhs = + * The number to compare `this` to. + * Returns: + * Whether the result of the comparison is true. + */ + bool opCmp(string op)(in Number rhs) pure const @safe nothrow @nogc + { + mixin("return (this.contained " ~ op ~ "rhs.contained);"); + } } /// @@ -517,6 +532,48 @@ struct NumberContainer return ((this.val == rhs.val) && (this.ival == rhs.ival)) && ((this.pow10 == rhs.pow10) && (this.precision == rhs.precision)); } + + /******************************************** + * Compare two Numbers. + * TODO: Once exponentiation has been added, + * use magnitude. + * + * Params + * rhs = + * The Number to compare to. + * Returns: + * The value of the comparison + */ + bool opCmp(string op)(in NumberContainer rhs) pure @safe nothrow const @nogc + { + auto a = this.val; + auto b = rhs.val; + + if(rhs.pow10 < 0) + { + a *= BigInt(10)^^(-rhs.pow10); + b *= BigInt(10)^^(-rhs.pow10); + } + else + { + a *= BigInt(10)^^rhs.pow10; + b *= BigInt(10)^^rhs.pow10; + } + + if(this.pow10 < 0) + { + a *= BigInt(10)^^(-this.pow10); + b *= BigInt(10)^^(-this.pow10); + } + else + { + a *= BigInt(10)^^this.pow10; + b *= BigInt(10)^^this.pow10; + } + + mixin("return a " ~ op ~ " b;"); + } + package: BigInt val; BigInt ival; diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index 6124881..a0ed6ec 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -68,6 +68,7 @@ dstring summation(dstring[] op) @safe temp = ""d; dstring[] paramTypes; dstring[] paramValues; + size_t[][dstring] typeIndices; static foreach(type; typel) // OH NO NOT THIS AGAIN { @@ -94,6 +95,7 @@ dstring summation(dstring[] op) @safe temp2 = ""d; i += 2; temp ~= "("d; + size_t j = 0; for(; op[0][i] != d(')'); ++i) // Get the function parameter types { if(op[0][i] == d(',')) @@ -101,6 +103,8 @@ dstring summation(dstring[] op) @safe paramTypes ~= temp2; temp ~= d(','); temp2 = ""d; + typeIndices[temp2] ~= j; + ++j; continue; } temp2 ~= op[0][i]; @@ -108,6 +112,8 @@ dstring summation(dstring[] op) @safe paramTypes ~= temp2; temp ~= ")"d; temp2 = ""d; + typeIndices[temp2] ~= j; + ++j; return ret; } From 63a890ea941a9a95f85c56a88f33be25976cd04a Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 8 Mar 2023 21:34:14 -0500 Subject: [PATCH 05/16] Add dummy loop and fix some simple, but stupid bugs --- source/dutils/math/number.d | 10 +++++----- source/dutils/math/summation.d | 14 +++++++++++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/source/dutils/math/number.d b/source/dutils/math/number.d index 9947723..df28920 100644 --- a/source/dutils/math/number.d +++ b/source/dutils/math/number.d @@ -306,9 +306,9 @@ class Number : Mtype!NumberContainer * Returns: * Whether the result of the comparison is true. */ - bool opCmp(string op)(in Number rhs) pure const @safe nothrow @nogc + bool opCmp(string op)(in Number rhs) pure const @safe nothrow { - mixin("return (this.contained " ~ op ~ "rhs.contained);"); + return this.contained.opCmp!op(rhs.contained); } } @@ -544,10 +544,10 @@ struct NumberContainer * Returns: * The value of the comparison */ - bool opCmp(string op)(in NumberContainer rhs) pure @safe nothrow const @nogc + bool opCmp(string op)(in NumberContainer rhs) pure @safe nothrow const { - auto a = this.val; - auto b = rhs.val; + BigInt a = this.val; + BigInt b = rhs.val; if(rhs.pow10 < 0) { diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index a0ed6ec..1786cb6 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -111,9 +111,21 @@ dstring summation(dstring[] op) @safe } paramTypes ~= temp2; temp ~= ")"d; - temp2 = ""d; typeIndices[temp2] ~= j; ++j; + temp2 = ""d; + + Number upperindex = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); + for( i = 0; i < op[2].length; ++i) // Get the upper index + temp2 ~= op[2][i]; + upperindex.fromDstring(temp2); + auto one = new Number(NumberContainer(BigInt(1), BigInt(0), 0, precision)); + + // Set up for repeated function calls + + for(; index.opCmp!"<="(upperindex); index.applyOp("+", one)) // Main loop + { + } return ret; } From c1caec1a9d18f26f9d93fb470a3cb1214a4068a9 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 14 Mar 2023 17:48:03 -0400 Subject: [PATCH 06/16] Make some headway in adding constants to the verification function, there si a bug though --- source/dutils/math/core.d | 87 ++++++++++++++++++++++++++++++++-- source/dutils/math/summation.d | 36 +++++++++++--- 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 9fe174d..b060ac5 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -98,7 +98,7 @@ bool removeFunction(in dstring name, in dstring func) @safe /******************************************* * Validates a function. - * + * TODO: CONSTANTS * Params: * func = * The function name and parameters. @@ -169,9 +169,84 @@ bool validateFunction(in dstring func, in dstring def) @trusted do { tempNum = ""d; + dstring val3; + dstring val; switch(def[i]) { - case d('('): + case d('%'): //Constants + debug import std.stdio; + if(isOperand && !isOp) + return false; + isOperand = true; + ++i; + do + { + val ~= def[i]; + ++i; + if(i == def.length) + return false; + } + while(def[i] != d('(')); + ++i; + do + { + val3 ~= def[i]; + ++i; + if(i == def.length) + return false; + } + while(def[i] != d(')')); + ++i; + + static foreach(type; typel) + { + mixin(type ~ " " ~ type ~ "painConstant = new " ~ type ~ "();"); + } + + static foreach(type; typel) + { + if(type == val) + { + try + { + mixin(type ~ "painConstant.fromDstring(val3);"); + } + catch(Exception e) + { + return false; + } + goto endf; + } + } + endf: + debug "here".writeln; + if(isOp) + { + static foreach(type; typel) + { + if(currOperand == type) + { + static foreach(type2; typel) + { + if(type2 == val) + { + mixin("if(!" ~ type ~ "painConstant.applyOp(currOp, " ~ type2 ~ "painConstant)) + { + return false; + }"); + goto endf2; + } + } + } + } + endf2: + isOp = false; + currOperand = val; + } + if(def[i] != d('%')) + return false; + break; + case d('('): ++indentation; ++i; break; @@ -445,10 +520,10 @@ bool validateFunction(in dstring func, in dstring def) @trusted do { tempstr ~= def[i]; - if(((def[i] != d('x')) && (def[i] != d('\\'))) && (def[i] != d('(') && def[i] != d(' '))) + if(((def[i] != d('x')) && (def[i] != d('\\'))) && (def[i] != d('(') && def[i] != d(' ')) && def[i] != d('%')) ++i; } - while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' '))); + while((def[i] != d('x') && def[i] != d('\\')) && (def[i] != d('(') && def[i] != d(' ')) && def[i] != d('%')); /+if(def[i] != d('(')) // Operators+/ currOp = tempstr.idup; @@ -525,6 +600,10 @@ bool validateFunction(in dstring func, in dstring def) @trusted def = "x1*x2"d; func = "(Number,Number)(Number)"d; assert(registerFunction("f"d, func, def)); + + // Issue 16 + def = "x1*x2*%Number(5+0i)%"d; + assert(validateFunction(func, def)); //Functions within functions were too hard to implement, so we removed them. //def = "x1* f(x1,x2)(Number)"d; //assert(validateFunction(func, def)); diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index 1786cb6..7862fa6 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -79,13 +79,19 @@ dstring summation(dstring[] op) @safe temp ~= op[0][i]; dstring temp2; + size_t n_index; + size_t k = 0; ++i; for(; op[0][i] != d(')'); ++i) // Get the values of the function parameters. { if(op[0][i] == d(',')) { - paramValues ~= temp2; + if(temp2 != "n") + paramValues ~= temp2; + else + n_index = k; temp2 = ""d; + ++k; continue; } temp2 ~= op[0][i]; @@ -100,11 +106,14 @@ dstring summation(dstring[] op) @safe { if(op[0][i] == d(',')) { - paramTypes ~= temp2; - temp ~= d(','); - temp2 = ""d; - typeIndices[temp2] ~= j; - ++j; + if(j != n_index) + { + paramTypes ~= temp2; + temp ~= d(','); + typeIndices[temp2] ~= j; + ++j; + temp2 = ""d; + } continue; } temp2 ~= op[0][i]; @@ -121,7 +130,20 @@ dstring summation(dstring[] op) @safe upperindex.fromDstring(temp2); auto one = new Number(NumberContainer(BigInt(1), BigInt(0), 0, precision)); - // Set up for repeated function calls + // Set up for repeated function calls (intialize temporary variables) + + static foreach(type; typel) + { + if(type in typeIndices) + { + foreach(ind; typeIndices[type]) + { + mixin("temp" ~ type ~ ".length++;"); + mixin("temp" ~ type ~ "[$-1] = new " ~ type ~ "();"); + mixin("temp" ~ type ~ "[$-1].fromDstring(paramValues[ind]);"); + } + } + } for(; index.opCmp!"<="(upperindex); index.applyOp("+", one)) // Main loop { From 62767f78d8f5555db8a277372cf1ca504c40d5ef Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 14 Mar 2023 18:11:56 -0400 Subject: [PATCH 07/16] Fixed the bug: forgetting to increment i at the end of the case --- source/dutils/math/core.d | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index b060ac5..f71034d 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -220,6 +220,9 @@ bool validateFunction(in dstring func, in dstring def) @trusted } endf: debug "here".writeln; + debug currOp.writeln; + debug currOperand.writeln; + debug val.writeln; if(isOp) { static foreach(type; typel) @@ -243,8 +246,13 @@ bool validateFunction(in dstring func, in dstring def) @trusted isOp = false; currOperand = val; } + debug def[i].writeln; if(def[i] != d('%')) + { return false; + } + ++i; + debug "test".writeln; break; case d('('): ++indentation; From 3198322b567d428960ef7254fd0a9afef83a11e8 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Sun, 19 Mar 2023 19:18:26 -0400 Subject: [PATCH 08/16] Implemented constants in function execution, getting a range violation --- source/dutils/math/core.d | 81 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index f71034d..677a371 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -98,7 +98,7 @@ bool removeFunction(in dstring name, in dstring func) @safe /******************************************* * Validates a function. - * TODO: CONSTANTS + * * Params: * func = * The function name and parameters. @@ -666,7 +666,7 @@ import std.typecons : Tuple; /*********************************************************** * Executes a function. - * + * TODO: Constants * * Params: * func = @@ -698,6 +698,17 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg { switch(funcList[func][i]) { + case d('%'): + do + { + parens[indentation][parenNum[indentation]] ~= funcList[func][i]; + ++i; + if(i >= funcList[func].length) + break; + } + while(funcList[func][i] != d(')')); + parens[indentation][parenNum[indentation]] ~= ")"d; + break; case d('('): ++indentation; if(indentation !in parens) @@ -762,10 +773,65 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg bool firstOperand = false; for(size_t i = 0; i < parens[key][key2].length; i++) { - //Get to work executing the function. + // Get to work executing the function. switch(parens[key][key2][i]) { - case d('('): //Parentheses, also known as a pain in the ass. + case d('%'): // Constants (Issue #16) + dstring tempType = ""d; + ++i; + do + { + tempType ~= parens[key][key2][i]; + ++i; + } + while(parens[key][key2][i] != d('(')); + + dstring val = ""d; + ++i; + do + { + val ~= parens[key][key2][i]; + ++i; + } + while(parens[key][key2][i] != d(')')); + ++i; + + if(!firstOperand) + { + firstOperand = true; + static foreach(type; typel) + { + if(type == tempType) + { + mixin("temp" ~ type ~ "[key][key2] = new " ~ type ~ "();"); + mixin("temp" ~ type ~ "[key][key2].fromDstring(val);"); + } + } + currType = tempType; + } + else + { + bool c; + static foreach(type2; typel) + { + if(type2 == tempType) + { + mixin(type2 ~ " constant = new " ~ type2 ~ "();"); + constant.fromDstring(val); + static foreach(type; typel) + { + if(type == currType) + { + mixin("c = temp" ~ type ~ "[key][key2].applyOp(currOp, constant);"); + } + } + } + } + assert(c); + currOp = ""d; + } + break; + case d('('): // Parentheses, also known as a pain in the ass. static foreach(type; typel) { mixin("if(temp" ~ type ~ "[key+1][currParen] !is null) @@ -928,4 +994,11 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg assert(registerFunction("ree"d, func, def)); i = executeFunction!(Number, Number, Number, Number, Number)("ree(Number,Number,Number,Number)(Number)"d, b); assert(i.toDstring == "6+0i"d, cast(char[])i.toDstring.dup); + assert(removeFunction("ree"d, func)); + + // Issue 16 + def ~= "+%Number(5+0i)%"d; + assert(registerFunction("ree"d, func, def)); + i = executeFunction!(Number, Number, Number, Number, Number)("ree(Number,Number,Number,Number)(Number)"d, b); + assert(i.toDstring == "11+0i"d, cast(char[])i.toDstring.dup); } From 80687ad174aa76f8ecee6f6678e26f8bd8131b24 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Sun, 19 Mar 2023 20:56:07 -0400 Subject: [PATCH 09/16] Fixed one bug, but there is yet another to contend with --- source/dutils/math/core.d | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 677a371..20a21da 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -698,7 +698,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg { switch(funcList[func][i]) { - case d('%'): + case d('%'): // Bug-free do { parens[indentation][parenNum[indentation]] ~= funcList[func][i]; @@ -707,7 +707,8 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg break; } while(funcList[func][i] != d(')')); - parens[indentation][parenNum[indentation]] ~= ")"d; + parens[indentation][parenNum[indentation]] ~= ")%"d; + ++i; break; case d('('): ++indentation; @@ -762,6 +763,21 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg } foreach(ref key; keys2) key.sort!"b > a"; + + debug + { + foreach(key; parens.keys) + { + ("key: " ~ key.to!string).writeln; + foreach_reverse(key2; parens[key].keys) + { + ("key2: " ~ key2.to!string).writeln; + parens[key][key2].writeln; + writeln(); + } + } + } + foreach_reverse(key; keys) { debug import std.stdio; @@ -777,6 +793,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg switch(parens[key][key2][i]) { case d('%'): // Constants (Issue #16) + debug "bruh".writeln; dstring tempType = ""d; ++i; do @@ -830,6 +847,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg assert(c); currOp = ""d; } + debug parens[key][key2].writeln; break; case d('('): // Parentheses, also known as a pain in the ass. static foreach(type; typel) @@ -997,6 +1015,8 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg assert(removeFunction("ree"d, func)); // Issue 16 + debug import std.stdio; + debug "bug".writeln; def ~= "+%Number(5+0i)%"d; assert(registerFunction("ree"d, func, def)); i = executeFunction!(Number, Number, Number, Number, Number)("ree(Number,Number,Number,Number)(Number)"d, b); From fc32b6456b2b92853a6d2f3c9eefce007fbb69f8 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 21 Mar 2023 22:43:12 -0400 Subject: [PATCH 10/16] It works, I forgot to exclude % signs from operators --- source/dutils/math/core.d | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 20a21da..f262217 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -694,6 +694,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg size_t indentation = 0; size_t[size_t] parenNum; parenNum[0] = 0; + bool bruhx = false; for(size_t i = 0; i < funcList[func].length; ++i) // Organize the function into parentheses groups. { switch(funcList[func][i]) @@ -748,6 +749,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg default: if(funcList[func][i-1] == d(')')) parens[indentation][parenNum[indentation]] ~= "()"d; + debug funcList[func][i].writeln; parens[indentation][parenNum[indentation]] ~= funcList[func][i]; } } @@ -781,12 +783,12 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg foreach_reverse(key; keys) { debug import std.stdio; - size_t currParen = 0; foreach(key2; keys2[key]) { dstring currOp = ""d; dstring currType = ""d; bool firstOperand = false; + size_t currParen = 0; for(size_t i = 0; i < parens[key][key2].length; i++) { // Get to work executing the function. @@ -850,9 +852,13 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg debug parens[key][key2].writeln; break; case d('('): // Parentheses, also known as a pain in the ass. + debug currParen.writeln; + debug writeln(key+1); + debug parens[key][key2][i+1].writeln; static foreach(type; typel) { - mixin("if(temp" ~ type ~ "[key+1][currParen] !is null) + mixin(" + if(temp" ~ type ~ "[key+1][currParen] !is null) { currType = type; if(!firstOperand) @@ -948,7 +954,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg break; } while(parens[key][key2][i] != d('\\') && parens[key][key2][i] != d('x') && parens[key][key2][i] - != d('(')); + != d('(') && parens[key][key2][i] != d('%')); --i; } } From 4c7383dcd09229a407b747cec10cd8df659c8794 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Tue, 21 Mar 2023 22:44:45 -0400 Subject: [PATCH 11/16] remove debug output --- source/dutils/math/core.d | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index f262217..04b4c6c 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -219,10 +219,7 @@ bool validateFunction(in dstring func, in dstring def) @trusted } } endf: - debug "here".writeln; - debug currOp.writeln; - debug currOperand.writeln; - debug val.writeln; + if(isOp) { static foreach(type; typel) @@ -246,13 +243,13 @@ bool validateFunction(in dstring func, in dstring def) @trusted isOp = false; currOperand = val; } - debug def[i].writeln; + if(def[i] != d('%')) { return false; } ++i; - debug "test".writeln; + break; case d('('): ++indentation; @@ -749,7 +746,6 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg default: if(funcList[func][i-1] == d(')')) parens[indentation][parenNum[indentation]] ~= "()"d; - debug funcList[func][i].writeln; parens[indentation][parenNum[indentation]] ~= funcList[func][i]; } } @@ -766,19 +762,6 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg foreach(ref key; keys2) key.sort!"b > a"; - debug - { - foreach(key; parens.keys) - { - ("key: " ~ key.to!string).writeln; - foreach_reverse(key2; parens[key].keys) - { - ("key2: " ~ key2.to!string).writeln; - parens[key][key2].writeln; - writeln(); - } - } - } foreach_reverse(key; keys) { @@ -795,7 +778,6 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg switch(parens[key][key2][i]) { case d('%'): // Constants (Issue #16) - debug "bruh".writeln; dstring tempType = ""d; ++i; do @@ -849,12 +831,8 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg assert(c); currOp = ""d; } - debug parens[key][key2].writeln; break; case d('('): // Parentheses, also known as a pain in the ass. - debug currParen.writeln; - debug writeln(key+1); - debug parens[key][key2][i+1].writeln; static foreach(type; typel) { mixin(" @@ -1021,8 +999,7 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg assert(removeFunction("ree"d, func)); // Issue 16 - debug import std.stdio; - debug "bug".writeln; + def ~= "+%Number(5+0i)%"d; assert(registerFunction("ree"d, func, def)); i = executeFunction!(Number, Number, Number, Number, Number)("ree(Number,Number,Number,Number)(Number)"d, b); From 7dfce9f3b676d2f0e731631b085d145a1ae0bec9 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Thu, 23 Mar 2023 22:20:15 -0400 Subject: [PATCH 12/16] Implement main loop and make an adjustment to the definition of an operator --- source/dutils/math/def.d | 5 ++- source/dutils/math/summation.d | 69 ++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/source/dutils/math/def.d b/source/dutils/math/def.d index 229177b..6f952aa 100644 --- a/source/dutils/math/def.d +++ b/source/dutils/math/def.d @@ -70,12 +70,13 @@ abstract class Mtype(T) if(__traits(hasMember, T, "precision")) } /// Define an Operator as used by dutils.math. -alias Operator = dstring function(dstring[]) @safe; +alias Operator = void*; /* In reality this is casted to dstring function (T ...)(dstring[]) @safe, but there is no set value for T, it depends on the template +paramater of executeFunction*/ /// Container for the list of all operators. struct Oplist { - Operator opIndex(dstring op) pure @safe const shared + auto opIndex(dstring op) pure @safe const shared { return this.ops[op]; } diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index 7862fa6..c392923 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -38,7 +38,7 @@ private import dutils.math.number; /********************************************************* * Implements Summation - * + * TODO: FIX DOCS * Params: * op = * The arguments to be passed in. These are: @@ -54,7 +54,7 @@ private import dutils.math.number; * A dstring containing the serialized value of the * sum of the function about the index. */ -dstring summation(dstring[] op) @safe +dstring summation(T ...)(dstring[] op) @safe { dstring ret; dstring func; // Store the function here. @@ -70,10 +70,7 @@ dstring summation(dstring[] op) @safe dstring[] paramValues; size_t[][dstring] typeIndices; - static foreach(type; typel) // OH NO NOT THIS AGAIN - { - mixin(type ~ "[] temp" ~ type ~ ";"); - } + Tuple!T args; size_t i; for(i = 0; op[0][i] != d('('); ++i) // Get function name. temp ~= op[0][i]; @@ -89,7 +86,10 @@ dstring summation(dstring[] op) @safe if(temp2 != "n") paramValues ~= temp2; else + { n_index = k; + paramValues ~= ""d; + } temp2 = ""d; ++k; continue; @@ -109,19 +109,28 @@ dstring summation(dstring[] op) @safe if(j != n_index) { paramTypes ~= temp2; - temp ~= d(','); typeIndices[temp2] ~= j; - ++j; - temp2 = ""d; } + else + { + paramTypes ~= "Number"d; + typeIndices["Number"d] ~= j; + } + temp ~= d(','); + ++j; + temp2 = ""d; continue; } temp2 ~= op[0][i]; } paramTypes ~= temp2; - temp ~= ")"d; + temp ~= ")("d; typeIndices[temp2] ~= j; ++j; + i +=2; + for(; op[0][i] != d(')'); ++i) + ret ~= op[0][i]; + temp ~= ")"d; temp2 = ""d; Number upperindex = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); @@ -131,24 +140,52 @@ dstring summation(dstring[] op) @safe auto one = new Number(NumberContainer(BigInt(1), BigInt(0), 0, precision)); // Set up for repeated function calls (intialize temporary variables) - + size_t indo = 0; + static foreach(type; typel) { if(type in typeIndices) { foreach(ind; typeIndices[type]) { - mixin("temp" ~ type ~ ".length++;"); - mixin("temp" ~ type ~ "[$-1] = new " ~ type ~ "();"); - mixin("temp" ~ type ~ "[$-1].fromDstring(paramValues[ind]);"); + mixin("args[ind] = new " ~ type ~ "();"); + if(paramValues[ind] != ""d) + mixin("args[ind].fromDstring(paramValues[ind]);"); + else + { + mixin("args[ind] = new " ~ type ~ "(index.val);"); // n + indo = ind; + } + } + } + } + + // return type + static foreach(type; typel) + { + mixin(type ~ " ret" ~ type ~ " = new " ~ type ~ "();"); + } + + coco: for(; index.opCmp!"<="(upperindex); args[indo].applyOp("+", one)) // Main loop + { + static foreach(type; typel) + { + if(type == ret) + { + mixin("ret" ~ type ~ " = executeFunction(args);"); + continue coco; } } } - for(; index.opCmp!"<="(upperindex); index.applyOp("+", one)) // Main loop + static foreach(type; typel) { + if(type == ret) + { + mixin("return ret" ~ type ~ ".toDstring;"); + } } - return ret; + assert(0); } /// The precision to be used while doing the summation. From b0ce1618d8dcf611d3357ee2c429935ed0272cf9 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 3 May 2023 19:34:47 -0400 Subject: [PATCH 13/16] Fix some bugs, begin to write unittest, new bug discovered. --- source/dutils/math/def.d | 33 ++++++++---------------------- source/dutils/math/summation.d | 37 ++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/source/dutils/math/def.d b/source/dutils/math/def.d index 6f952aa..896d39d 100644 --- a/source/dutils/math/def.d +++ b/source/dutils/math/def.d @@ -69,31 +69,11 @@ abstract class Mtype(T) if(__traits(hasMember, T, "precision")) T contained; } -/// Define an Operator as used by dutils.math. -alias Operator = void*; /* In reality this is casted to dstring function (T ...)(dstring[]) @safe, but there is no set value for T, it depends on the template -paramater of executeFunction*/ +/// Trying to workaround it being impossible to have varying template params. +package import std.variant; -/// Container for the list of all operators. -struct Oplist -{ - auto opIndex(dstring op) pure @safe const shared - { - return this.ops[op]; - } - auto opBinaryRight(string op)(dstring key) pure @safe const shared if(op == "in" || op == "!in") - { - mixin("return key " ~ op ~ " ops;"); - } - auto keys() @safe - { - return this.ops.keys; - } - package: - Operator[dstring] ops; -} - -/// The list of all operators. -package shared Oplist opList; +/// The list of all operators +package shared Variant[dstring] opList; /// Container for the function list. struct Funclist @@ -120,4 +100,7 @@ package shared Funclist funcList; package import dutils.math.number; // I'm not sure why this line is here, but I'm too scared to touch it. /// The list of all types, that has to be kept here and continously updated. -enum dstring[] typel = ["Number"]; // Too bad that complete modular programming is impossible in D. +enum dstring[] typel = ["Number"d]; // Too bad that complete modular programming is impossible in D. + +/// The list of all types, that has to be kept here and continously updated (string version): +enum string[] typels = ["Number"]; diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index c392923..d1725cb 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -35,6 +35,7 @@ import dutils.math.def; private import dutils.math.core; private import dutils.math.number; +private import std.typecons : Tuple; /********************************************************* * Implements Summation @@ -56,6 +57,7 @@ private import dutils.math.number; */ dstring summation(T ...)(dstring[] op) @safe { + debug import std.stdio; dstring ret; dstring func; // Store the function here. assert(op.length == 3); @@ -128,9 +130,12 @@ dstring summation(T ...)(dstring[] op) @safe typeIndices[temp2] ~= j; ++j; i +=2; + + for(; op[0][i] != d(')'); ++i) ret ~= op[0][i]; temp ~= ")"d; + func = temp; temp2 = ""d; Number upperindex = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); @@ -146,9 +151,10 @@ dstring summation(T ...)(dstring[] op) @safe { if(type in typeIndices) { - foreach(ind; typeIndices[type]) + static foreach(ind; 0 .. args.fieldNames.length) { mixin("args[ind] = new " ~ type ~ "();"); + debug paramValues[ind].writeln; if(paramValues[ind] != ""d) mixin("args[ind].fromDstring(paramValues[ind]);"); else @@ -166,14 +172,20 @@ dstring summation(T ...)(dstring[] op) @safe mixin(type ~ " ret" ~ type ~ " = new " ~ type ~ "();"); } - coco: for(; index.opCmp!"<="(upperindex); args[indo].applyOp("+", one)) // Main loop + static foreach(indo2; 0 .. args.fieldNames.length) { - static foreach(type; typel) + if(indo == indo2) { - if(type == ret) + coco: for(; index.opCmp!"<="(upperindex); args[indo2].applyOp("+", one)) // Main loop { - mixin("ret" ~ type ~ " = executeFunction(args);"); - continue coco; + static foreach(type; typels) + { + if(type == cast(string)ret) + { + mixin("ret" ~ type ~ " = executeFunction!(" ~ typeof(args).stringof[7 .. $-1] ~ ")(func, args);"); + continue coco; + } + } } } } @@ -188,6 +200,19 @@ dstring summation(T ...)(dstring[] op) @safe assert(0); } +/// +unittest +{ + // We want to make sure that the sum of the first n integers is equal to n(n+1)/2. + dstring funcname = "(Number)(Number)"d; + dstring funcbody = "x1"d; + assert(registerFunction("f1"d, funcname, funcbody)); + funcbody = "x1*(x1+%Number(1+0i)%)/%Number(2+0i)%"d; + assert(registerFunction("f2"d, funcname, funcbody)); + + auto sum = summation!(Number)(["f1(n)(Number)(Number)"d, "1+0i"d, "100+0i"d]); +} + /// The precision to be used while doing the summation. private size_t precision = 18; From 7c85f8c46c196ed530072bc24ef4de22fd9b855f Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Wed, 3 May 2023 19:43:28 -0400 Subject: [PATCH 14/16] Bug fixed, but the main loop hangs. --- source/dutils/math/def.d | 2 +- source/dutils/math/summation.d | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/dutils/math/def.d b/source/dutils/math/def.d index 896d39d..fda193c 100644 --- a/source/dutils/math/def.d +++ b/source/dutils/math/def.d @@ -65,7 +65,7 @@ abstract class Mtype(T) if(__traits(hasMember, T, "precision")) { this.contained = num; } - protected: + package: T contained; } diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d index d1725cb..9510ff9 100644 --- a/source/dutils/math/summation.d +++ b/source/dutils/math/summation.d @@ -154,9 +154,13 @@ dstring summation(T ...)(dstring[] op) @safe static foreach(ind; 0 .. args.fieldNames.length) { mixin("args[ind] = new " ~ type ~ "();"); - debug paramValues[ind].writeln; - if(paramValues[ind] != ""d) - mixin("args[ind].fromDstring(paramValues[ind]);"); + if(paramValues[ind] != "" && paramValues[ind] != "n"d) + args[ind].fromDstring(paramValues[ind]); + else if(paramValues[ind] == "n"d) + { + args[ind] = new Number(); + args[ind].contained = index.val; + } else { mixin("args[ind] = new " ~ type ~ "(index.val);"); // n @@ -176,7 +180,7 @@ dstring summation(T ...)(dstring[] op) @safe { if(indo == indo2) { - coco: for(; index.opCmp!"<="(upperindex); args[indo2].applyOp("+", one)) // Main loop + coco: for(; index.opCmp!"<="(upperindex); args[indo2].applyOp("+", one)) // Main loopv (HANGS LOL) { static foreach(type; typels) { From f4400d61da3c49d9471d452596de02848b5930c7 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Sun, 16 Jul 2023 16:45:55 -0400 Subject: [PATCH 15/16] Discarding summations, as they are too hard to impliment. Will implement logarithms instead. --- source/dutils/math/core.d | 2 - source/dutils/math/package.d | 2 - source/dutils/math/summation.d | 234 --------------------------------- 3 files changed, 238 deletions(-) delete mode 100644 source/dutils/math/summation.d diff --git a/source/dutils/math/core.d b/source/dutils/math/core.d index 04b4c6c..b486085 100644 --- a/source/dutils/math/core.d +++ b/source/dutils/math/core.d @@ -921,8 +921,6 @@ Return executeFunction(Return, Mtypes...)(in dstring func, in Tuple!(Mtypes) arg --i; currOp = ""d; break; - case d('\\'): //Operators, such as derivatives, sums, and integrals. - break; default: //Type specific operators. do { diff --git a/source/dutils/math/package.d b/source/dutils/math/package.d index 825cc2c..c41e552 100644 --- a/source/dutils/math/package.d +++ b/source/dutils/math/package.d @@ -31,5 +31,3 @@ else import dutils.math.core; /// Implements complex numbers for the math library. import dutils.math.number; -/// Implements Summations -import dutils.math.summation; diff --git a/source/dutils/math/summation.d b/source/dutils/math/summation.d deleted file mode 100644 index 9510ff9..0000000 --- a/source/dutils/math/summation.d +++ /dev/null @@ -1,234 +0,0 @@ -/*This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see .*/ -/** Copyright: 2022-2023, Ruby The Roobster*/ -/**Author: Ruby The Roobster, */ -/**Date: March 6, 2023*/ -/** License: GPL-3.0*/ - -/** Implements Summation Operator*/ -module dutils.math.summation; - -version(DLL) -{ - export: -} -else -{ - public: -} - - -/// TODO: ADD RIEMANN SUMS WHEN DONE - -/// Definitions file -import dutils.math.def; - -private import dutils.math.core; -private import dutils.math.number; -private import std.typecons : Tuple; - -/********************************************************* - * Implements Summation - * TODO: FIX DOCS - * Params: - * op = - * The arguments to be passed in. These are: - * A registered function, with its input - * specified n (the index), and whatever - * parameters from the function the operator was - * called in; The intial value of the index (real); - * and the maximum value of the index (real); - * the types of the paramaters of the function, - * separated by commas. - * - * Returns: - * A dstring containing the serialized value of the - * sum of the function about the index. - */ -dstring summation(T ...)(dstring[] op) @safe -{ - debug import std.stdio; - dstring ret; - dstring func; // Store the function here. - assert(op.length == 3); - Number index = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); - dstring temp = ""d; - for(size_t i = 0; i < op[1].length; ++i) // Get the lower value of index first, it's easiest. - temp ~= op[1][i]; - index.fromDstring(temp); - - temp = ""d; - dstring[] paramTypes; - dstring[] paramValues; - size_t[][dstring] typeIndices; - - Tuple!T args; - size_t i; - for(i = 0; op[0][i] != d('('); ++i) // Get function name. - temp ~= op[0][i]; - - dstring temp2; - size_t n_index; - size_t k = 0; - ++i; - for(; op[0][i] != d(')'); ++i) // Get the values of the function parameters. - { - if(op[0][i] == d(',')) - { - if(temp2 != "n") - paramValues ~= temp2; - else - { - n_index = k; - paramValues ~= ""d; - } - temp2 = ""d; - ++k; - continue; - } - temp2 ~= op[0][i]; - } - - paramValues ~= temp2; // This last is cut off in the loop. - temp2 = ""d; - i += 2; - temp ~= "("d; - size_t j = 0; - for(; op[0][i] != d(')'); ++i) // Get the function parameter types - { - if(op[0][i] == d(',')) - { - if(j != n_index) - { - paramTypes ~= temp2; - typeIndices[temp2] ~= j; - } - else - { - paramTypes ~= "Number"d; - typeIndices["Number"d] ~= j; - } - temp ~= d(','); - ++j; - temp2 = ""d; - continue; - } - temp2 ~= op[0][i]; - } - paramTypes ~= temp2; - temp ~= ")("d; - typeIndices[temp2] ~= j; - ++j; - i +=2; - - - for(; op[0][i] != d(')'); ++i) - ret ~= op[0][i]; - temp ~= ")"d; - func = temp; - temp2 = ""d; - - Number upperindex = new Number(NumberContainer(BigInt(0), BigInt(0), 0, precision)); - for( i = 0; i < op[2].length; ++i) // Get the upper index - temp2 ~= op[2][i]; - upperindex.fromDstring(temp2); - auto one = new Number(NumberContainer(BigInt(1), BigInt(0), 0, precision)); - - // Set up for repeated function calls (intialize temporary variables) - size_t indo = 0; - - static foreach(type; typel) - { - if(type in typeIndices) - { - static foreach(ind; 0 .. args.fieldNames.length) - { - mixin("args[ind] = new " ~ type ~ "();"); - if(paramValues[ind] != "" && paramValues[ind] != "n"d) - args[ind].fromDstring(paramValues[ind]); - else if(paramValues[ind] == "n"d) - { - args[ind] = new Number(); - args[ind].contained = index.val; - } - else - { - mixin("args[ind] = new " ~ type ~ "(index.val);"); // n - indo = ind; - } - } - } - } - - // return type - static foreach(type; typel) - { - mixin(type ~ " ret" ~ type ~ " = new " ~ type ~ "();"); - } - - static foreach(indo2; 0 .. args.fieldNames.length) - { - if(indo == indo2) - { - coco: for(; index.opCmp!"<="(upperindex); args[indo2].applyOp("+", one)) // Main loopv (HANGS LOL) - { - static foreach(type; typels) - { - if(type == cast(string)ret) - { - mixin("ret" ~ type ~ " = executeFunction!(" ~ typeof(args).stringof[7 .. $-1] ~ ")(func, args);"); - continue coco; - } - } - } - } - } - - static foreach(type; typel) - { - if(type == ret) - { - mixin("return ret" ~ type ~ ".toDstring;"); - } - } - assert(0); -} - -/// -unittest -{ - // We want to make sure that the sum of the first n integers is equal to n(n+1)/2. - dstring funcname = "(Number)(Number)"d; - dstring funcbody = "x1"d; - assert(registerFunction("f1"d, funcname, funcbody)); - funcbody = "x1*(x1+%Number(1+0i)%)/%Number(2+0i)%"d; - assert(registerFunction("f2"d, funcname, funcbody)); - - auto sum = summation!(Number)(["f1(n)(Number)(Number)"d, "1+0i"d, "100+0i"d]); -} - -/// The precision to be used while doing the summation. -private size_t precision = 18; - -/*************************** - * Sets the precision. - * - * Params: - * prec = - * The new precision. - */ -void setPrecision(in size_t prec) @safe nothrow @nogc -{ - precision = prec; -} - From 4e8a4a76011b9e450a1d22eca3e8fe35545656f6 Mon Sep 17 00:00:00 2001 From: RubyTheRoobster Date: Sun, 16 Jul 2023 19:01:20 -0400 Subject: [PATCH 16/16] Make headway with the logarithm, rework opList --- source/dutils/math/def.d | 52 +++++++++++++++++++++++++++++++++--- source/dutils/math/number.d | 3 +++ source/dutils/math/package.d | 2 ++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/source/dutils/math/def.d b/source/dutils/math/def.d index fda193c..d4dd86d 100644 --- a/source/dutils/math/def.d +++ b/source/dutils/math/def.d @@ -72,8 +72,54 @@ abstract class Mtype(T) if(__traits(hasMember, T, "precision")) /// Trying to workaround it being impossible to have varying template params. package import std.variant; -/// The list of all operators -package shared Variant[dstring] opList; +package struct _variant +{ + Variant var; + dstring hash; +} + +/// Container for the operator list: +struct OpList +{ + Variant opIndex(dstring hash) + { + Variant ret = false; + foreach(op; ops) + { + if(op.hash == hash) + return op.var; + } + return ret; + } + bool opBinaryRight(string op)(inout(dchar)[] key) @trusted if(op == "in" || op == "!in") + { + static if(op == "in") + const k = true; + else + const k = false; + foreach(op; ops) + { + if(op.hash == cast(dstring)key) + return k; + } + return !k; + } + auto keys() const @trusted @property + { + dstring[] _keys; + foreach(op; ops) + { + _keys ~= op.hash; + } + return _keys; + } + package: + _variant[] ops; +} + +/// The list of all special functions/operators. +package OpList opList; + /// Container for the function list. struct Funclist @@ -86,7 +132,7 @@ struct Funclist { mixin("return cast(dstring)key " ~ op ~ " funcs;"); } - auto keys() + auto keys() pure nothrow @safe { return this.funcs.keys; } diff --git a/source/dutils/math/number.d b/source/dutils/math/number.d index df28920..cbf3bea 100644 --- a/source/dutils/math/number.d +++ b/source/dutils/math/number.d @@ -583,3 +583,6 @@ struct NumberContainer int pow10; ulong precision; } + + + diff --git a/source/dutils/math/package.d b/source/dutils/math/package.d index c41e552..67b1247 100644 --- a/source/dutils/math/package.d +++ b/source/dutils/math/package.d @@ -31,3 +31,5 @@ else import dutils.math.core; /// Implements complex numbers for the math library. import dutils.math.number; +/// Implements logarithms +import dutils.math.log;