| 172 |  | } | 
| 173 |  |  | 
| 174 |  | static int | 
| 175 | < | rmx_load_ascii(RMATRIX *rm, FILE *fp) | 
| 175 | > | rmx_load_ascii(double *drp, const RMATRIX *rm, FILE *fp) | 
| 176 |  | { | 
| 177 | < | int     i, j, k; | 
| 177 | > | int     j, k; | 
| 178 |  |  | 
| 179 | < | if (!rmx_prepare(rm)) | 
| 180 | < | return(0); | 
| 181 | < | for (i = 0; i < rm->nrows; i++) | 
| 182 | < | for (j = 0; j < rm->ncols; j++) { | 
| 183 | < | double  *dp = rmx_lval(rm,i,j); | 
| 184 | < | for (k = 0; k < rm->ncomp; k++) | 
| 185 | < | if (fscanf(fp, "%lf", &dp[k]) != 1) | 
| 186 | < | return(0); | 
| 187 | < | } | 
| 179 | > | for (j = 0; j < rm->ncols; j++) | 
| 180 | > | for (k = rm->ncomp; k-- > 0; ) | 
| 181 | > | if (fscanf(fp, "%lf", drp++) != 1) | 
| 182 | > | return(0); | 
| 183 |  | return(1); | 
| 184 |  | } | 
| 185 |  |  | 
| 186 |  | static int | 
| 187 | < | rmx_load_float(RMATRIX *rm, FILE *fp) | 
| 187 | > | rmx_load_float(double *drp, const RMATRIX *rm, FILE *fp) | 
| 188 |  | { | 
| 189 | < | int     i, j, k; | 
| 189 | > | int     j, k; | 
| 190 |  | float   val[100]; | 
| 191 |  |  | 
| 192 |  | if (rm->ncomp > 100) { | 
| 193 |  | fputs("Unsupported # components in rmx_load_float()\n", stderr); | 
| 194 |  | exit(1); | 
| 195 |  | } | 
| 196 | < | if (!rmx_prepare(rm)) | 
| 202 | < | return(0); | 
| 203 | < | for (i = 0; i < rm->nrows; i++) | 
| 204 | < | for (j = 0; j < rm->ncols; j++) { | 
| 205 | < | double  *dp = rmx_lval(rm,i,j); | 
| 196 | > | for (j = 0; j < rm->ncols; j++) { | 
| 197 |  | if (getbinary(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) | 
| 198 | < | return(0); | 
| 198 | > | return(0); | 
| 199 |  | if (rm->swapin) | 
| 200 | < | swap32((char *)val, rm->ncomp); | 
| 201 | < | for (k = rm->ncomp; k--; ) | 
| 202 | < | dp[k] = val[k]; | 
| 203 | < | } | 
| 200 | > | swap32((char *)val, rm->ncomp); | 
| 201 | > | for (k = 0; k < rm->ncomp; k++) | 
| 202 | > | *drp++ = val[k]; | 
| 203 | > | } | 
| 204 |  | return(1); | 
| 205 |  | } | 
| 206 |  |  | 
| 207 |  | static int | 
| 208 | < | rmx_load_double(RMATRIX *rm, FILE *fp) | 
| 208 | > | rmx_load_double(double *drp, const RMATRIX *rm, FILE *fp) | 
| 209 |  | { | 
| 210 | < | int     i; | 
| 220 | < | #ifdef MAP_FILE | 
| 221 | < | long    pos;            /* map memory for file > 1MB if possible */ | 
| 222 | < | if (!rm->swapin && array_size(rm) >= 1L<<20 && | 
| 223 | < | (pos = ftell(fp)) >= 0 && !(pos % sizeof(double))) { | 
| 224 | < | rm->mapped = mmap(NULL, array_size(rm)+pos, PROT_READ|PROT_WRITE, | 
| 225 | < | MAP_PRIVATE, fileno(fp), 0); | 
| 226 | < | if (rm->mapped != MAP_FAILED) { | 
| 227 | < | rm->mtx = (double *)rm->mapped + pos/sizeof(double); | 
| 228 | < | return(1); | 
| 229 | < | }               /* else fall back on reading into memory */ | 
| 230 | < | rm->mapped = NULL; | 
| 231 | < | } | 
| 232 | < | #endif | 
| 233 | < | if (!rmx_prepare(rm)) | 
| 210 | > | if (getbinary(drp, sizeof(*drp)*rm->ncomp, rm->ncols, fp) != rm->ncols) | 
| 211 |  | return(0); | 
| 212 | < | for (i = 0; i < rm->nrows; i++) { | 
| 213 | < | if (getbinary(rmx_lval(rm,i,0), sizeof(double)*rm->ncomp, | 
| 237 | < | rm->ncols, fp) != rm->ncols) | 
| 238 | < | return(0); | 
| 239 | < | if (rm->swapin) | 
| 240 | < | swap64((char *)rmx_lval(rm,i,0), rm->ncols*rm->ncomp); | 
| 241 | < | } | 
| 212 | > | if (rm->swapin) | 
| 213 | > | swap64((char *)drp, rm->ncols*rm->ncomp); | 
| 214 |  | return(1); | 
| 215 |  | } | 
| 216 |  |  | 
| 217 |  | static int | 
| 218 | < | rmx_load_rgbe(RMATRIX *rm, FILE *fp) | 
| 218 | > | rmx_load_rgbe(double *drp, const RMATRIX *rm, FILE *fp) | 
| 219 |  | { | 
| 220 | < | COLOR   *scan = (COLOR *)malloc(sizeof(COLOR)*rm->ncols); | 
| 221 | < | int     i, j; | 
| 220 | > | COLR    *scan; | 
| 221 | > | COLOR   col; | 
| 222 | > | int     j; | 
| 223 |  |  | 
| 224 | + | if (rm->ncomp != 3) | 
| 225 | + | return(0); | 
| 226 | + | scan = (COLR *)tempbuffer(sizeof(COLR)*rm->ncols); | 
| 227 |  | if (!scan) | 
| 228 |  | return(0); | 
| 229 | < | if (!rmx_prepare(rm)) { | 
| 254 | < | free(scan); | 
| 229 | > | if (freadcolrs(scan, rm->ncols, fp) < 0) | 
| 230 |  | return(0); | 
| 231 | + | for (j = 0; j < rm->ncols; j++) { | 
| 232 | + | colr_color(col, scan[j]); | 
| 233 | + | *drp++ = colval(col,RED); | 
| 234 | + | *drp++ = colval(col,GRN); | 
| 235 | + | *drp++ = colval(col,BLU); | 
| 236 |  | } | 
| 257 | – | for (i = 0; i < rm->nrows; i++) { | 
| 258 | – | double      *dp = rmx_lval(rm,i,0); | 
| 259 | – | if (freadscan(scan, rm->ncols, fp) < 0) { | 
| 260 | – | free(scan); | 
| 261 | – | return(0); | 
| 262 | – | } | 
| 263 | – | for (j = 0; j < rm->ncols; j++, dp += 3) { | 
| 264 | – | dp[0] = colval(scan[j],RED); | 
| 265 | – | dp[1] = colval(scan[j],GRN); | 
| 266 | – | dp[2] = colval(scan[j],BLU); | 
| 267 | – | } | 
| 268 | – | } | 
| 269 | – | free(scan); | 
| 237 |  | return(1); | 
| 238 |  | } | 
| 239 |  |  | 
| 240 |  | static int | 
| 241 | < | rmx_load_spec(RMATRIX *rm, FILE *fp) | 
| 241 | > | rmx_load_spec(double *drp, const RMATRIX *rm, FILE *fp) | 
| 242 |  | { | 
| 243 |  | uby8    *scan; | 
| 244 |  | SCOLOR  scol; | 
| 245 | < | int     i, j, k; | 
| 245 | > | int     j, k; | 
| 246 |  |  | 
| 247 | < | if (rm->ncomp < 3) | 
| 247 | > | if ((rm->ncomp < 3) | (rm->ncomp > MAXCSAMP)) | 
| 248 |  | return(0); | 
| 249 | < | scan = (uby8 *)malloc((rm->ncomp+1)*rm->ncols); | 
| 249 | > | scan = (uby8 *)tempbuffer((rm->ncomp+1)*rm->ncols); | 
| 250 |  | if (!scan) | 
| 251 |  | return(0); | 
| 252 | < | if (!rmx_prepare(rm)) { | 
| 286 | < | free(scan); | 
| 252 | > | if (freadscolrs(scan, rm->ncomp, rm->ncols, fp) < 0) | 
| 253 |  | return(0); | 
| 254 | + | for (j = 0; j < rm->ncols; j++) { | 
| 255 | + | scolr2scolor(scol, scan+j*(rm->ncomp+1), rm->ncomp); | 
| 256 | + | for (k = 0; k < rm->ncomp; k++) | 
| 257 | + | *drp++ = scol[k]; | 
| 258 |  | } | 
| 289 | – | for (i = 0; i < rm->nrows; i++) { | 
| 290 | – | double      *dp = rmx_lval(rm,i,0); | 
| 291 | – | if (freadscolrs(scan, rm->ncomp, rm->ncols, fp) < 0) { | 
| 292 | – | free(scan); | 
| 293 | – | return(0); | 
| 294 | – | } | 
| 295 | – | for (j = 0; j < rm->ncols; j++) { | 
| 296 | – | scolr2scolor(scol, scan+j*(rm->ncomp+1), rm->ncomp); | 
| 297 | – | for (k = 0; k < rm->ncomp; k++) | 
| 298 | – | *dp++ = scol[k]; | 
| 299 | – | } | 
| 300 | – | } | 
| 301 | – | free(scan); | 
| 259 |  | return(1); | 
| 260 |  | } | 
| 261 |  |  | 
| 303 |  | return(1); | 
| 304 |  | } | 
| 305 |  |  | 
| 306 | < | /* Allocate & load post-header data from stream given type set in rm->dtype */ | 
| 306 | > | /* Load next row as double (cannot be XML) */ | 
| 307 |  | int | 
| 308 | < | rmx_load_data(RMATRIX *rm, FILE *fp) | 
| 308 | > | rmx_load_row(double *drp, const RMATRIX *rm, FILE *fp) | 
| 309 |  | { | 
| 310 |  | switch (rm->dtype) { | 
| 311 |  | case DTascii: | 
| 312 | < | SET_FILE_TEXT(fp); | 
| 356 | < | return(rmx_load_ascii(rm, fp)); | 
| 312 | > | return(rmx_load_ascii(drp, rm, fp)); | 
| 313 |  | case DTfloat: | 
| 314 | < | return(rmx_load_float(rm, fp)); | 
| 314 | > | return(rmx_load_float(drp, rm, fp)); | 
| 315 |  | case DTdouble: | 
| 316 | < | return(rmx_load_double(rm, fp)); | 
| 316 | > | return(rmx_load_double(drp, rm, fp)); | 
| 317 |  | case DTrgbe: | 
| 318 |  | case DTxyze: | 
| 319 | < | return(rmx_load_rgbe(rm, fp)); | 
| 319 | > | return(rmx_load_rgbe(drp, rm, fp)); | 
| 320 |  | case DTspec: | 
| 321 | < | return(rmx_load_spec(rm, fp)); | 
| 321 | > | return(rmx_load_spec(drp, rm, fp)); | 
| 322 |  | default: | 
| 323 | < | fputs("Unsupported data type in rmx_loaddata()\n", stderr); | 
| 323 | > | fputs("Unsupported data type in rmx_load_row()\n", stderr); | 
| 324 |  | } | 
| 325 |  | return(0); | 
| 326 |  | } | 
| 327 |  |  | 
| 328 | + | /* Allocate & load post-header data from stream given type set in rm->dtype */ | 
| 329 | + | int | 
| 330 | + | rmx_load_data(RMATRIX *rm, FILE *fp) | 
| 331 | + | { | 
| 332 | + | int     i; | 
| 333 | + | #ifdef MAP_FILE | 
| 334 | + | long    pos;            /* map memory for file > 1MB if possible */ | 
| 335 | + | if ((rm->dtype == DTdouble) & !rm->swapin && array_size(rm) >= 1L<<20 && | 
| 336 | + | (pos = ftell(fp)) >= 0 && !(pos % sizeof(double))) { | 
| 337 | + | rm->mapped = mmap(NULL, array_size(rm)+pos, PROT_READ|PROT_WRITE, | 
| 338 | + | MAP_PRIVATE, fileno(fp), 0); | 
| 339 | + | if (rm->mapped != MAP_FAILED) { | 
| 340 | + | rm->mtx = (double *)rm->mapped + pos/sizeof(double); | 
| 341 | + | return(1); | 
| 342 | + | }               /* else fall back on reading into memory */ | 
| 343 | + | rm->mapped = NULL; | 
| 344 | + | } | 
| 345 | + | #endif | 
| 346 | + | if (!rmx_prepare(rm)) { /* need in-core matrix array */ | 
| 347 | + | fprintf(stderr, "Cannot allocate %g MByte matrix array\n", | 
| 348 | + | (1./(1L<<20))*(double)array_size(rm)); | 
| 349 | + | return(0); | 
| 350 | + | } | 
| 351 | + | if (rm->dtype == DTascii) | 
| 352 | + | SET_FILE_TEXT(fp); | 
| 353 | + | for (i = 0; i < rm->nrows; i++) | 
| 354 | + | if (!rmx_load_row(rmx_lval(rm,i,0), rm, fp)) | 
| 355 | + | return(0); | 
| 356 | + | return(1); | 
| 357 | + | } | 
| 358 | + |  | 
| 359 |  | /* Load matrix from supported file type */ | 
| 360 |  | RMATRIX * | 
| 361 |  | rmx_load(const char *inspec, RMPref rmp) | 
| 486 |  | static int | 
| 487 |  | rmx_write_double(const RMATRIX *rm, FILE *fp) | 
| 488 |  | { | 
| 489 | < | int     i; | 
| 490 | < |  | 
| 504 | < | for (i = 0; i < rm->nrows; i++) | 
| 505 | < | if (putbinary(rmx_val(rm,i,0), sizeof(double)*rm->ncomp, | 
| 506 | < | rm->ncols, fp) != rm->ncols) | 
| 507 | < | return(0); | 
| 508 | < | return(1); | 
| 489 | > | return(putbinary(rm->mtx, sizeof(rm->mtx[0])*rm->ncomp, | 
| 490 | > | rm->nrows*rm->ncols, fp) == rm->nrows*rm->ncols); | 
| 491 |  | } | 
| 492 |  |  | 
| 493 |  | static int | 
| 569 |  | #ifdef getc_unlocked | 
| 570 |  | flockfile(fp); | 
| 571 |  | #endif | 
| 572 | < | /* complete header */ | 
| 591 | < | if (rm->info) | 
| 572 | > | if (rm->info)                           /* complete header */ | 
| 573 |  | fputs(rm->info, fp); | 
| 574 |  | if (dtype == DTfromHeader) | 
| 575 |  | dtype = rm->dtype; | 
| 585 |  | else if (rm->cexp[GRN] != 1.f) | 
| 586 |  | fputexpos(rm->cexp[GRN], fp); | 
| 587 |  | if ((dtype != DTrgbe) & (dtype != DTxyze)) { | 
| 588 | < | if (dtype == DTspec) { | 
| 608 | < | if (rm->ncomp < 3) | 
| 609 | < | return(0);      /* bad # components */ | 
| 610 | < | fputwlsplit(rm->wlpart, fp); | 
| 611 | < | } else { | 
| 588 | > | if (dtype != DTspec) { | 
| 589 |  | fprintf(fp, "NROWS=%d\n", rm->nrows); | 
| 590 |  | fprintf(fp, "NCOLS=%d\n", rm->ncols); | 
| 591 | < | } | 
| 591 | > | } else if (rm->ncomp < 3) | 
| 592 | > | return(0);              /* bad # components */ | 
| 593 |  | fputncomp(rm->ncomp, fp); | 
| 594 | + | if (dtype == DTspec || (rm->ncomp > 3 && | 
| 595 | + | memcmp(rm->wlpart, WLPART, sizeof(WLPART)))) | 
| 596 | + | fputwlsplit(rm->wlpart, fp); | 
| 597 |  | } else if ((rm->ncomp != 3) & (rm->ncomp != 1)) | 
| 598 |  | return(0);                      /* wrong # components */ | 
| 599 |  | if ((dtype == DTfloat) | (dtype == DTdouble)) | 
| 600 |  | fputendian(fp);                 /* important to record */ | 
| 601 |  | fputformat(cm_fmt_id[dtype], fp); | 
| 602 | < | fputc('\n', fp); | 
| 602 | > | fputc('\n', fp);                        /* end of header */ | 
| 603 |  | switch (dtype) {                        /* write data */ | 
| 604 |  | case DTascii: | 
| 605 |  | ok = rmx_write_ascii(rm, fp); |