Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove const to pass Oracle compiler on Solaris #3294

Merged
merged 6 commits into from
Feb 9, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

2. As promised in new feature 6 of v1.11.6 Sep 2018 (see below in this file), the `datatable.CJ.names` option's default is now `TRUE`. In v1.13.0 it will be removed.

3. v1.12.0 did not compile on Solaris 10 using Oracle Developer Studio 12.6, [#3285](https://github.com/Rdatatable/data.table/issues/3285). Many thanks to Prof Ripley for providing and testing a patch. For future reference and other package developers, a `const` variable should not be passed to OpenMP's `num_threads()` directive otherwise `left operand must be modifiable lvalue` occurs.


### Changes in v1.12.0 (13 Jan 2019)

Expand Down
92 changes: 42 additions & 50 deletions src/froll.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void frollmeanFast(double *x, uint_fast64_t nx, double_ans_t *ans, int k, double
}
if (verbose) Rprintf("%s: NA (or other non-finite) value(s) are present in input, re-running with extra care for NAs\n", __func__);
w = 0.0;
truehasna = 1;
truehasna = true;
}
} else { // early stopping branch when NAs detected in first k obs
if (hasna==-1) { // raise warning
Expand All @@ -69,7 +69,7 @@ void frollmeanFast(double *x, uint_fast64_t nx, double_ans_t *ans, int k, double
}
if (verbose) Rprintf("%s: NA (or other non-finite) value(s) are present in input, skip non-NA attempt and run with extra care for NAs\n", __func__);
w = 0.0;
truehasna = 1;
truehasna = true;
}
}
if (truehasna) {
Expand Down Expand Up @@ -105,34 +105,30 @@ void frollmeanFast(double *x, uint_fast64_t nx, double_ans_t *ans, int k, double

void frollmeanExact(double *x, uint_fast64_t nx, double_ans_t *ans, int k, double fill, bool narm, int hasna, bool verbose) {
if (verbose) Rprintf("%s: running for input length %lu, window %d, hasna %d, narm %d\n", __func__, nx, k, hasna, (int) narm);
for (int i=0; i<k-1; i++) { // fill partial window only
for (int i=0; i<k-1; i++) { // fill partial window only
ans->ans[i] = fill;
}
volatile bool truehasna = hasna>0; // flag to re-run with NA support if NAs detected, volatile to be used from parallel region
bool truehasna = hasna>0; // flag to re-run with NA support if NAs detected
if (!truehasna || !narm) {
const int threads = MIN(getDTthreads(), nx);
#pragma omp parallel num_threads(threads) shared(truehasna)
{
#pragma omp for schedule(static)
for (uint_fast64_t i=k-1; i<nx; i++) { // loop on every observation with complete window, partial already filled in single threaded section
if (narm && truehasna) continue; // if NAs detected no point to continue
long double w = 0.0;
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
w += x[i+j]; // sum of window for particular observation
}
if (R_FINITE((double) w)) { // no need to calc roundoff correction if NAs detected as will re-call all below in truehasna==1
long double res = w / k; // keep results as long double for intermediate processing
long double err = 0.0; // roundoff corrector
for (int j=-k+1; j<=0; j++) { // nested loop on window width
err += x[i+j] - res; // measure difference of obs in sub-loop to calculated fun for obs
}
ans->ans[i] = (double) (res + (err / k)); // adjust calculated rollfun with roundoff correction
} else {
if (!narm) ans->ans[i] = (double) (w / k); // NAs should be propagated
truehasna = 1; // NAs detected for this window, set flag so rest of windows will not be re-run
#pragma omp parallel for num_threads(getDTthreads())
for (uint_fast64_t i=k-1; i<nx; i++) { // loop on every observation with complete window, partial already filled in single threaded section
if (narm && truehasna) continue; // if NAs detected no point to continue
long double w = 0.0;
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
w += x[i+j]; // sum of window for particular observation
}
if (R_FINITE((double) w)) { // no need to calc roundoff correction if NAs detected as will re-call all below in truehasna==1
long double res = w / k; // keep results as long double for intermediate processing
long double err = 0.0; // roundoff corrector
for (int j=-k+1; j<=0; j++) { // nested loop on window width
err += x[i+j] - res; // measure difference of obs in sub-loop to calculated fun for obs
}
ans->ans[i] = (double) (res + (err / k)); // adjust calculated rollfun with roundoff correction
} else {
if (!narm) ans->ans[i] = (double) (w / k); // NAs should be propagated
truehasna = true; // NAs detected for this window, set flag so rest of windows will not be re-run
}
} // end of parallel region
}
if (truehasna) {
if (hasna==-1) { // raise warning
ans->status = 2;
Expand All @@ -145,33 +141,29 @@ void frollmeanExact(double *x, uint_fast64_t nx, double_ans_t *ans, int k, doubl
}
}
if (truehasna && narm) {
const int threads = MIN(getDTthreads(), nx);
#pragma omp parallel num_threads(threads)
{
#pragma omp for schedule(static)
for (uint_fast64_t i=k-1; i<nx; i++) { // loop on every observation with complete window, partial already filled in single threaded section
long double w = 0.0;
int nc = 0; // NA counter within sliding window
for (int j=-k+1; j<=0; j++) { // nested loop on window width
if (ISNAN(x[i+j])) nc++; // increment NA count in current window
else w += x[i+j]; // add observation to current window
#pragma omp parallel for num_threads(getDTthreads())
for (uint_fast64_t i=k-1; i<nx; i++) { // loop on every observation with complete window, partial already filled in single threaded section
long double w = 0.0;
int nc = 0; // NA counter within sliding window
for (int j=-k+1; j<=0; j++) { // nested loop on window width
if (ISNAN(x[i+j])) nc++; // increment NA count in current window
else w += x[i+j]; // add observation to current window
}
long double res = w / k; // keep results as long double for intermediate processing
long double err = 0.0; // roundoff corrector
if (nc == 0) { // no NAs in current window
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
err += x[i+j] - res; // measure roundoff for each obs in window
}
long double res = w / k; // keep results as long double for intermediate processing
long double err = 0.0; // roundoff corrector
if (nc == 0) { // no NAs in current window
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
err += x[i+j] - res; // measure roundoff for each obs in window
}
ans->ans[i] = (double) (res + (err / k)); // adjust calculated fun with roundoff correction
} else if (nc < k) {
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
if (!ISNAN(x[i+j])) err += x[i+j] - res; // measure roundoff for each non-NA obs in window
}
ans->ans[i] = (double) (res + (err / (k - nc))); // adjust calculated fun with roundoff correction
} else { // nc == k
ans->ans[i] = R_NaN; // all values NAs and narm so produce expected values
ans->ans[i] = (double) (res + (err / k)); // adjust calculated fun with roundoff correction
} else if (nc < k) {
for (int j=-k+1; j<=0; j++) { // sub-loop on window width
if (!ISNAN(x[i+j])) err += x[i+j] - res; // measure roundoff for each non-NA obs in window
}
ans->ans[i] = (double) (res + (err / (k - nc))); // adjust calculated fun with roundoff correction
} else { // nc == k
ans->ans[i] = R_NaN; // all values NAs and narm so produce expected values
}
} // end of parallel region
}
}
}
30 changes: 13 additions & 17 deletions src/frollR.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,23 +188,19 @@ SEXP frollfunR(SEXP fun, SEXP obj, SEXP k, SEXP fill, SEXP algo, SEXP align, SEX
else if (ialgo==1) Rprintf("frollfunR: %d column(s) and %d window(s), entering parallel execution, but actually single threaded due to enabled verbose which is not thread safe, 'exact' version of rolling function will compute results in parallel anyway as it does not print with verbose\n", nx, nk);
}
omp_set_nested(1);
const int threads = bverbose ? 1 : MIN(getDTthreads(), nx*nk);
#pragma omp parallel num_threads(threads)
{
#pragma omp for schedule(auto) collapse(2)
for (R_len_t i=0; i<nx; i++) { // loop over multiple columns
for (R_len_t j=0; j<nk; j++) { // loop over multiple windows
switch (sfun) {
case MEAN :
if (!badaptive) frollmean(ialgo, dx[i], inx[i], &dans[i*nk+j], iik[j], ialign, dfill, bnarm, ihasna, bverbose);
else fadaptiverollmean(ialgo, dx[i], inx[i], &dans[i*nk+j], ikl[j], dfill, bnarm, ihasna, bverbose);
break;
//case SUM :
// break;
}
} // end of j-windows loop
} // end of i-columns loop
} // end of omp parallel region
#pragma omp parallel for num_threads(bverbose ? 1 : getDTthreads()) schedule(auto) collapse(2)
for (R_len_t i=0; i<nx; i++) { // loop over multiple columns
for (R_len_t j=0; j<nk; j++) { // loop over multiple windows
switch (sfun) {
case MEAN :
if (!badaptive) frollmean(ialgo, dx[i], inx[i], &dans[i*nk+j], iik[j], ialign, dfill, bnarm, ihasna, bverbose);
else fadaptiverollmean(ialgo, dx[i], inx[i], &dans[i*nk+j], ikl[j], dfill, bnarm, ihasna, bverbose);
break;
//case SUM :
// break;
}
}
}
omp_set_nested(0);
}

Expand Down
Loading