From 5dbed62db84ae860d53e3d390f99db2817939e8a Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sat, 30 Nov 2024 20:27:11 -0600 Subject: [PATCH 1/7] Align tad family with new compartment numbering scheme --- src/genModelVars.h | 30 ++++++++++++++++++++++++++++ src/parseCmtProperties.h | 1 - src/parseFunsDosing.h | 42 ++++++++++++++++++++++++++-------------- src/tran.h | 25 +++++++++++++++++++----- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/src/genModelVars.h b/src/genModelVars.h index 2395c2634..01a1ef5c5 100644 --- a/src/genModelVars.h +++ b/src/genModelVars.h @@ -218,6 +218,36 @@ static inline int sortStateVectorsErrHandle(int prop, int pass, int i) { if ((prop & propDur) != 0) { sAppend(&sbt, "'dur(%s)', ", tb.ss.line[tb.di[i]]); } + if ((prop & propTad) != 0) { + sAppend(&sbt, "'tad(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTad0) != 0) { + sAppend(&sbt, "'tad0(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTafd) != 0) { + sAppend(&sbt, "'tafd(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTafd0) != 0) { + sAppend(&sbt, "'tafd0(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTlast) != 0) { + sAppend(&sbt, "'tlast(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTlast0) != 0) { + sAppend(&sbt, "'tlast0(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTfirst) != 0) { + sAppend(&sbt, "'tfirst(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propTfirst0) != 0) { + sAppend(&sbt, "'tfirst0(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propPodo) != 0) { + sAppend(&sbt, "'podo(%s)', ", tb.ss.line[tb.di[i]]); + } + if ((prop & propDose) != 0) { + sAppend(&sbt, "'dose(%s)', ", tb.ss.line[tb.di[i]]); + } // Take off trailing "', sbt.o -= 2; sbt.s[sbt.o] = 0; diff --git a/src/parseCmtProperties.h b/src/parseCmtProperties.h index 8532af61a..d333c043b 100644 --- a/src/parseCmtProperties.h +++ b/src/parseCmtProperties.h @@ -331,7 +331,6 @@ static inline int handleRemainingAssignmentsCalcProps(nodeInfo ni, char *name, i return 0; } - static inline int finalizeLineParam(nodeInfo ni, char *name) { if (nodeHas(param_statement)) { sbDt.o = 0; sbt.o = 0; diff --git a/src/parseFunsDosing.h b/src/parseFunsDosing.h index 118e14885..72e2f51d4 100644 --- a/src/parseFunsDosing.h +++ b/src/parseFunsDosing.h @@ -57,23 +57,37 @@ static inline int handleFunctionTadSingleStateCcode(transFunctions *tf,char *v2) sAppend(&sb, "_%s1(", tf->v); sAppend(&sbDt, "_%s1(", tf->v); if (new_de(v2, 0)){ - if (!strcmp("depot", v2)){ - tb.hasDepot = 1; - aAppendN("_DEPOT_)", 8); - } else if (!strcmp("central", v2)){ - tb.hasCentral = 1; - aAppendN("_CENTRAL_)", 10); - } else { - tb.statei++; - sAppend(&sb, "%d)", tb.de.n); - sAppend(&sbDt, "%d)", tb.de.n); - } + // cannot be lhs statements in tad style assignments + // also cannot be from anywhere + add_de(tf->ni, tf->name, v2, 0, 0); + aProp(tb.de.n); } else { new_or_ith(v2); - sAppend(&sb, "%d)", tb.id); - sAppend(&sbDt, "%d)", tb.id); + aProp(tb.ix); + } + sAppend(&sb, "__DDT%d__)", tb.id); + sAppend(&sbDt, "__DDT%d__)", tb.id); + if (tf->isTad && (tb.dprop[tb.id] & propTad) == 0) { + tb.dprop[tb.id] += propTad; + } else if (tf->isTad0 && (tb.dprop[tb.id] & propTad0) == 0) { + tb.dprop[tb.id] += propTad0; + } else if (tf->isTafd && (tb.dprop[tb.id] & propTafd) == 0) { + tb.dprop[tb.id] += propTafd; + } else if (tf->isTafd0 && (tb.dprop[tb.id] & propTafd0) == 0) { + tb.dprop[tb.id] += propTafd0; + } else if (tf->isTlast && (tb.dprop[tb.id] & propTlast) == 0) { + tb.dprop[tb.id] += propTlast; + } else if (tf->isTlast0 && (tb.dprop[tb.id] & propTlast0) == 0) { + tb.dprop[tb.id] += propTlast0; + } else if (tf->isTfirst && (tb.dprop[tb.id] & propTfirst) == 0) { + tb.dprop[tb.id] += propTfirst; + } else if (tf->isTfirst0 && (tb.dprop[tb.id] & propTfirst0) == 0) { + tb.dprop[tb.id] += propTfirst0; + } else if (tf->isDose && (tb.dprop[tb.id] & propDose) == 0) { + tb.dprop[tb.id] += propDose; + } else if (tf->isPodo && (tb.dprop[tb.id] & propPodo) == 0) { + tb.dprop[tb.id] += propPodo; } - // tad(cmt) return 1; } diff --git a/src/tran.h b/src/tran.h index 7cb1434bc..f4f08775d 100644 --- a/src/tran.h +++ b/src/tran.h @@ -369,10 +369,25 @@ void _rxode2parse_unprotect(void); char *getLine (char *src, int line, int *lloc); -#define prop0 1 -#define propF 2 -#define propAlag 4 -#define propRate 8 -#define propDur 16 +#define prop0 1 +#define propF 2 +#define propAlag 4 +#define propRate 8 +#define propDur 16 +// tad +#define propTad 32 +#define propTad0 64 +// tafd +#define propTafd 128 +#define propTafd0 256 +// tlast +#define propTlast 512 +#define propTlast0 1024 +// tfirst +#define propTfirst 2048 +#define propTfirst0 4096 +// podo and dose +#define propPodo 8192 +#define propDose 16384 #endif // __TRAN_H__ From b3409a821f69abb2ec1231e9fee3be0c0ae6688f Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sat, 30 Nov 2024 22:59:26 -0600 Subject: [PATCH 2/7] Get a bit farther on fixing issue --- src/genModelVars.h | 40 ++++++++++++++++++++------------------- src/parseDdt.h | 2 +- src/parseFunsDosing.h | 7 +++++-- tests/testthat/test-tad.R | 32 +++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 22 deletions(-) diff --git a/src/genModelVars.h b/src/genModelVars.h index 01a1ef5c5..3f7d29821 100644 --- a/src/genModelVars.h +++ b/src/genModelVars.h @@ -105,13 +105,13 @@ static inline void calcNparamsNlhsNslhs(void) { static inline void calcNextra(void) { int offCmt=0,nExtra = 0; - char *buf, buf2[200]; + char *buf=NULL, buf2[200]; for (int i = 0; i < tb.statei; i++){ if (offCmt == 0 && tb.idu[i] == 0){ + buf=tb.ss.line[tb.di[i]]; offCmt = 1; nExtra++; - buf=tb.ss.line[tb.di[i]]; - } else if (offCmt == 1 && tb.idu[i] == 1){ + } else if (offCmt == 1 && tb.idu[i] == 1) { // There is an compartment that doesn't have a derivative if (tb.linCmt == 0){ char *v = rc_dup_str(buf, 0); @@ -203,55 +203,57 @@ static inline int sortStateVectorsErrHandle(int prop, int pass, int i) { if (prop == 0 || pass == 1) { return 1; } + char *buf = NULL; + buf = tb.ss.line[tb.di[i]]; if ((prop & prop0) != 0) { - sAppend(&sbt, "'%s(0)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'%s(0)', ", buf); } if ((prop & propF) != 0) { - sAppend(&sbt, "'f(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'f(%s)', ", buf); } if ((prop & propAlag) != 0) { - sAppend(&sbt, "'alag(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'alag(%s)', ", buf); } if ((prop & propRate) != 0) { - sAppend(&sbt, "'rate(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'rate(%s)', ", buf); } if ((prop & propDur) != 0) { - sAppend(&sbt, "'dur(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'dur(%s)', ", buf); } if ((prop & propTad) != 0) { - sAppend(&sbt, "'tad(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tad(%s)', ", buf); } if ((prop & propTad0) != 0) { - sAppend(&sbt, "'tad0(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tad0(%s)', ", buf); } if ((prop & propTafd) != 0) { - sAppend(&sbt, "'tafd(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tafd(%s)', ", buf); } if ((prop & propTafd0) != 0) { - sAppend(&sbt, "'tafd0(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tafd0(%s)', ", buf); } if ((prop & propTlast) != 0) { - sAppend(&sbt, "'tlast(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tlast(%s)', ", buf); } if ((prop & propTlast0) != 0) { - sAppend(&sbt, "'tlast0(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tlast0(%s)', ", buf); } if ((prop & propTfirst) != 0) { - sAppend(&sbt, "'tfirst(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tfirst(%s)', ", buf); } if ((prop & propTfirst0) != 0) { - sAppend(&sbt, "'tfirst0(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'tfirst0(%s)', ", buf); } if ((prop & propPodo) != 0) { - sAppend(&sbt, "'podo(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'podo(%s)', ", buf); } if ((prop & propDose) != 0) { - sAppend(&sbt, "'dose(%s)', ", tb.ss.line[tb.di[i]]); + sAppend(&sbt, "'dose(%s)', ", buf); } // Take off trailing "', sbt.o -= 2; sbt.s[sbt.o] = 0; - sAppend(&sbt, " present, but d/dt(%s) not defined\n", tb.ss.line[tb.di[i]]); + sAppend(&sbt, " present, but d/dt(%s) not defined\n", buf); return 0; } diff --git a/src/parseDdt.h b/src/parseDdt.h index 5fd6d1adb..295296f95 100644 --- a/src/parseDdt.h +++ b/src/parseDdt.h @@ -40,7 +40,7 @@ static inline int new_de(const char *s, int fromWhere) { static inline int isCmtLhsStatement(nodeInfo ni, char *name, char *v) { int hasLhs = 0; - if (nodeHas(cmt_statement)){ + if (nodeHas(cmt_statement)) { new_or_ith(v); if (tb.lh[tb.ix] || tb.ini[tb.ix]){ hasLhs=1; diff --git a/src/parseFunsDosing.h b/src/parseFunsDosing.h index 72e2f51d4..ae37c2be1 100644 --- a/src/parseFunsDosing.h +++ b/src/parseFunsDosing.h @@ -59,11 +59,14 @@ static inline int handleFunctionTadSingleStateCcode(transFunctions *tf,char *v2) if (new_de(v2, 0)){ // cannot be lhs statements in tad style assignments // also cannot be from anywhere + // temporarily turn off that this is a function + int fn = tb.fn; + tb.fn = 0; add_de(tf->ni, tf->name, v2, 0, 0); - aProp(tb.de.n); + // turn back on that this is a function + tb.fn = fn; } else { new_or_ith(v2); - aProp(tb.ix); } sAppend(&sb, "__DDT%d__)", tb.id); sAppend(&sbDt, "__DDT%d__)", tb.id); diff --git a/tests/testthat/test-tad.R b/tests/testthat/test-tad.R index bbb7ebfb9..36352568f 100644 --- a/tests/testthat/test-tad.R +++ b/tests/testthat/test-tad.R @@ -519,4 +519,36 @@ rxTest({ expect_false(isTRUE(all.equal(x$tad, x$tade))) }) + + test_that("tad parsing", { + + mod2 <- function() { + ini({ + ## Table 3 from Savic 2007 + cl <- 17.2 # (L/hr) + vc <- 45.1 # L + ka <- 0.38 # 1/hr + mtt <- 1.37 # hr + f2 <-0.5 # Fraction of 1st Order portion + n <- 20.1 + }) + model({ + k <- cl/vc + bio <- 1-f2 + ktr = (n+1)/mtt + ## note that lgammafn is the same as lgamma in R. + d/dt(depot1) = exp(log(bio*podo(depot))+ + log(ktr)+n*log(ktr*tad(depot))- + ktr*tad(depot)-lgammafn(n+1))-ka*depot1 + d/dt(depot2) <- -ka*depot2 + f(depot2) <-f2 + d/dt(cen) <- ka*depot1 + ka*depot2-k*cen + }) + } + + mod2 <- mod2() + + mod2$simulationModel + + }) }) From 8e7134ee6ec3a77ea1e28a12f3e51e2356bb6c1b Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sun, 1 Dec 2024 11:30:05 -0600 Subject: [PATCH 3/7] Fix parsing error --- src/parseDdt.h | 5 ++++- src/parseFunsDosing.h | 9 ++++++++- src/parseVars.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/parseDdt.h b/src/parseDdt.h index 295296f95..4b5ee62ce 100644 --- a/src/parseDdt.h +++ b/src/parseDdt.h @@ -73,7 +73,10 @@ static inline int add_deCmtProp(nodeInfo ni, char *name, char *v, int hasLhs, in } static inline int add_deState(nodeInfo ni, char *name, char *v, int hasLhs, int fromWhere) { - new_or_ith(v); + if (new_or_ith(v)) { + addSymbolStr(v); + new_or_ith(v); + } if (((tb.ini[tb.ix] == 1 && tb.ini0[tb.ix] == 0) || (tb.lh[tb.ix] == isLHS || tb.lh[tb.ix] == isLHSparam))){ updateSyntaxCol(); diff --git a/src/parseFunsDosing.h b/src/parseFunsDosing.h index ae37c2be1..d33fc66d6 100644 --- a/src/parseFunsDosing.h +++ b/src/parseFunsDosing.h @@ -60,9 +60,16 @@ static inline int handleFunctionTadSingleStateCcode(transFunctions *tf,char *v2) // cannot be lhs statements in tad style assignments // also cannot be from anywhere // temporarily turn off that this is a function + // This is not a function int fn = tb.fn; tb.fn = 0; - add_de(tf->ni, tf->name, v2, 0, 0); + // this is NOT an assignment + nodeInfo ni2; + niReset(&ni2); + char *name = tf->v; + ni2.assignment = 0; + ni2.ini = 0; + add_de(ni2, name, v2, 0, 0); // turn back on that this is a function tb.fn = fn; } else { diff --git a/src/parseVars.h b/src/parseVars.h index 5689be1b5..97f82cf97 100644 --- a/src/parseVars.h +++ b/src/parseVars.h @@ -115,6 +115,7 @@ static inline int skipReservedVariables(const char *s) { /* new symbol? if no, find it's ith */ static inline int new_or_ith(const char *s) { int i; + tb.ix=-2; if (tb.fn) {tb.ix=-2; return 0;} if (!strcmp("lhs", s)){tb.ix=-1; return 0;} if (assertForbiddenVariables(s) == 0) return 0; From dd7722b28faa469cba43e1c7e8903989e63e5f00 Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sun, 1 Dec 2024 16:46:50 -0600 Subject: [PATCH 4/7] fix linCmt() parsing --- src/genModelVars.h | 2 +- src/parseFunsDosing.h | 34 +++++++++++++++++++--------------- tests/testthat/test-tad.R | 28 ++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/genModelVars.h b/src/genModelVars.h index 3f7d29821..df76543fe 100644 --- a/src/genModelVars.h +++ b/src/genModelVars.h @@ -268,7 +268,7 @@ static inline SEXP sortStateVectors(SEXP ordS) { int cur = tb.didx[i]; int prop = tb.dprop[i]; int pass = 0; - if (tb.linCmt){ + if (tb.linCmt) { if (tb.hasDepotCmt == 1 && !strcmp("depot", tb.ss.line[tb.di[i]])){ pass = 1; } else if ((tb.hasCentralCmt == 1 || tb.hasDepotCmt == 1) && diff --git a/src/parseFunsDosing.h b/src/parseFunsDosing.h index d33fc66d6..01b9700aa 100644 --- a/src/parseFunsDosing.h +++ b/src/parseFunsDosing.h @@ -57,21 +57,25 @@ static inline int handleFunctionTadSingleStateCcode(transFunctions *tf,char *v2) sAppend(&sb, "_%s1(", tf->v); sAppend(&sbDt, "_%s1(", tf->v); if (new_de(v2, 0)){ - // cannot be lhs statements in tad style assignments - // also cannot be from anywhere - // temporarily turn off that this is a function - // This is not a function - int fn = tb.fn; - tb.fn = 0; - // this is NOT an assignment - nodeInfo ni2; - niReset(&ni2); - char *name = tf->v; - ni2.assignment = 0; - ni2.ini = 0; - add_de(ni2, name, v2, 0, 0); - // turn back on that this is a function - tb.fn = fn; + if (!strcmp("depot", v2)) { + tb.hasDepot = 1; + aAppendN("_DEPOT_)", 8); + return 1; + } else if (!strcmp("central", v2)) { + tb.hasCentral = 1; + aAppendN("_CENTRAL_)", 10); + return 1; + } else { + // cannot be lhs statements in tad style assignments + // also cannot be from anywhere + // temporarily turn off that this is a function + // This is not a function + int fn = tb.fn; + tb.fn = 0; + add_de(tf->ni, tf->name, v2, 0, 0); + // turn back on that this is a function + tb.fn = fn; + } } else { new_or_ith(v2); } diff --git a/tests/testthat/test-tad.R b/tests/testthat/test-tad.R index 36352568f..be8ccd3e0 100644 --- a/tests/testthat/test-tad.R +++ b/tests/testthat/test-tad.R @@ -546,9 +546,33 @@ rxTest({ }) } - mod2 <- mod2() + expect_error(mod2()) - mod2$simulationModel + mod2 <- function() { + ini({ + ## Table 3 from Savic 2007 + cl <- 17.2 # (L/hr) + vc <- 45.1 # L + ka <- 0.38 # 1/hr + mtt <- 1.37 # hr + f2 <-0.5 # Fraction of 1st Order portion + n <- 20.1 + }) + model({ + k <- cl/vc + bio <- 1-f2 + ktr = (n+1)/mtt + ## note that lgammafn is the same as lgamma in R. + d/dt(depot1) = exp(log(bio*podo(depot1))+ + log(ktr)+n*log(ktr*tad(depot1))- + ktr*tad(depot1)-lgammafn(n+1))-ka*depot1 + d/dt(depot2) <- -ka*depot2 + f(depot2) <-f2 + d/dt(cen) <- ka*depot1 + ka*depot2-k*cen + }) + } + + mod2 <- mod2() }) }) From df580c61c230ee2e2428a15c126ff3a22b4281af Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sun, 1 Dec 2024 19:53:41 -0600 Subject: [PATCH 5/7] Align cmt defs --- src/codegen.c | 4 ++-- src/parseFunsDosing.h | 8 ++++---- src/tran.c | 2 -- src/tran.h | 2 -- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index e7da220d0..d59e3b275 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -676,8 +676,8 @@ SEXP _rxode2_codegen(SEXP c_file, SEXP prefix, SEXP libname, if (tb.hasKa == 1) { sAppend(&sbOut, "#define _DEPOT_ %d\n", tb.statei); sAppend(&sbOut, "#define _CENTRAL_ %d\n", tb.statei+1); - } else if (tb.hasCentral == 1) { - if (tb.hasDepot){ + } else if (tb.hasCentralCmt == 1) { + if (tb.hasDepotCmt){ fclose(fpIO); _rxode2parse_unprotect(); err_trans("linCmt() does not have 'depot' compartment without a 'ka'"); diff --git a/src/parseFunsDosing.h b/src/parseFunsDosing.h index 01b9700aa..2ad5cfbe8 100644 --- a/src/parseFunsDosing.h +++ b/src/parseFunsDosing.h @@ -57,12 +57,12 @@ static inline int handleFunctionTadSingleStateCcode(transFunctions *tf,char *v2) sAppend(&sb, "_%s1(", tf->v); sAppend(&sbDt, "_%s1(", tf->v); if (new_de(v2, 0)){ - if (!strcmp("depot", v2)) { - tb.hasDepot = 1; + if (tb.linCmt && !strcmp("depot", v2)) { + tb.hasDepotCmt = 1; aAppendN("_DEPOT_)", 8); return 1; - } else if (!strcmp("central", v2)) { - tb.hasCentral = 1; + } else if (tb.linCmt && !strcmp("central", v2)) { + tb.hasCentralCmt = 1; aAppendN("_CENTRAL_)", 10); return 1; } else { diff --git a/src/tran.c b/src/tran.c index abeef91e6..a79055839 100644 --- a/src/tran.c +++ b/src/tran.c @@ -405,8 +405,6 @@ void reset(void) { tb.maxtheta = 0; tb.hasCmt = 0; tb.maxeta = 0; - tb.hasDepot = 0; - tb.hasCentral = 0; tb.hasDepotCmt = 0; tb.hasCentralCmt = 0; tb.hasKa = 0; diff --git a/src/tran.h b/src/tran.h index f4f08775d..743886344 100644 --- a/src/tran.h +++ b/src/tran.h @@ -84,8 +84,6 @@ lhs symbols? int maxtheta; int hasCmt; int maxeta; - int hasDepot; - int hasCentral; int hasDepotCmt; int hasCentralCmt; int hasKa; From 210388ebb138a0885744f2755846fe99d214d290 Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sun, 1 Dec 2024 19:55:45 -0600 Subject: [PATCH 6/7] Add to news --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index eac8ccd00..a4fea9384 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # rxode2 (development version) +- Rework the `tad()` and related functions so they use the same + interface as compartments (this way they do not depend on the order + of compartments); See #815 + - Add `getRxNpars` to api. This allows the development version of `babelmixr2` to better check what model is loaded and unload/reload as necessary. From 4c953c91336c5aa37ec0631b6d71c1a6a2564e2a Mon Sep 17 00:00:00 2001 From: Matthew Fidler Date: Sun, 1 Dec 2024 20:06:25 -0600 Subject: [PATCH 7/7] Add dummyLhs bypass --- NEWS.md | 3 ++- src/genModelVars.h | 2 +- src/parseCmtProperties.h | 9 +++++++++ src/tran.c | 1 + src/tran.h | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index a4fea9384..3febe2b7e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,7 +2,8 @@ - Rework the `tad()` and related functions so they use the same interface as compartments (this way they do not depend on the order - of compartments); See #815 + of compartments); See #815. Also allow dummy variables to ignore + state requirements (for parsing mu-referenced equations). - Add `getRxNpars` to api. This allows the development version of `babelmixr2` to better check what model is loaded and unload/reload diff --git a/src/genModelVars.h b/src/genModelVars.h index df76543fe..60efbbc4f 100644 --- a/src/genModelVars.h +++ b/src/genModelVars.h @@ -200,7 +200,7 @@ static inline SEXP calcIniVals(void) { SEXP orderForderS1(SEXP ordIn); static inline int sortStateVectorsErrHandle(int prop, int pass, int i) { - if (prop == 0 || pass == 1) { + if (prop == 0 || pass == 1 || tb.dummyLhs == 1) { return 1; } char *buf = NULL; diff --git a/src/parseCmtProperties.h b/src/parseCmtProperties.h index d333c043b..7bb3b4549 100644 --- a/src/parseCmtProperties.h +++ b/src/parseCmtProperties.h @@ -183,6 +183,9 @@ static inline int handleRemainingAssignmentsCalcPropComplexAssign(nodeInfo ni, c // New assignment tb.ixL = tb.ix; tb.lh[tb.ix] = isLHS; + if (!strcmp(v, "rxdummyLhs")) { + tb.dummyLhs = 1; + } } else if (tb.ix < 0){ if (!strcmp("rxlin___", v)) { tb.ixL=-1; @@ -216,6 +219,9 @@ static inline int handleRemainingAssignmentsCalcPropComplexAssign(nodeInfo ni, c tb.lh[tb.ix] = isLHSparam; } else { tb.lh[tb.ix] = isLHS; + if (!strcmp(v, "rxdummyLhs")) { + tb.dummyLhs = 1; + } } tb.ixL=-1; } @@ -299,6 +305,9 @@ static inline int handleRemainingAssignmentsCalcPropIni(nodeInfo ni, char *name, /* Rprintf("Duplicate %s; %d %d\n", v, tb.lh[tb.ix], tb.ini0[tb.ix]); */ if (tb.lh[tb.ix] != isLHS){ tb.lh[tb.ix] = isLHS; + if (!strcmp(v, "rxdummyLhs")) { + tb.dummyLhs = 1; + } if (nodeHas(ini0) && tb.ini0[tb.ix] == 1){ sPrint(&_gbuf,"cannot have conditional initial conditions for '%s'",v); updateSyntaxCol(); diff --git a/src/tran.c b/src/tran.c index a79055839..641d33115 100644 --- a/src/tran.c +++ b/src/tran.c @@ -422,6 +422,7 @@ void reset(void) { tb.linExtra = false; tb.nwhile = 0; tb.lvlStr = 0; + tb.dummyLhs = 0; tb.nInd = 0; tb.simflg = 0; tb.nLlik = 0; diff --git a/src/tran.h b/src/tran.h index 743886344..38819f336 100644 --- a/src/tran.h +++ b/src/tran.h @@ -107,6 +107,7 @@ lhs symbols? int lastDdt; int nLlik; int lvlStr; + int dummyLhs; } symtab; extern symtab tb;