8 |
|
* G.Ward |
9 |
|
*/ |
10 |
|
|
11 |
+ |
#ifndef _WIN32 |
12 |
+ |
#include <unistd.h> |
13 |
+ |
#include <sys/wait.h> |
14 |
+ |
#include <sys/mman.h> |
15 |
+ |
#endif |
16 |
|
#define _USE_MATH_DEFINES |
17 |
|
#include <stdio.h> |
18 |
|
#include <stdlib.h> |
100 |
|
#else |
101 |
|
int pctcull = 90; |
102 |
|
#endif |
103 |
+ |
/* number of processes to run */ |
104 |
+ |
int nprocs = 1; |
105 |
+ |
/* number of children (-1 in child) */ |
106 |
+ |
int nchild = 0; |
107 |
+ |
|
108 |
|
/* sampling order (set by data density) */ |
109 |
|
int samp_order = 0; |
110 |
|
|
655 |
|
} |
656 |
|
#endif |
657 |
|
|
658 |
< |
/* Compute (and insert) migration along directed edge */ |
658 |
> |
/* Create a new migration holder (sharing memory for multiprocessing) */ |
659 |
|
static MIGRATION * |
660 |
< |
make_migration(RBFNODE *from_rbf, RBFNODE *to_rbf, int creat_only) |
660 |
> |
new_migration(RBFNODE *from_rbf, RBFNODE *to_rbf) |
661 |
|
{ |
662 |
+ |
size_t memlen = sizeof(MIGRATION) + |
663 |
+ |
sizeof(float)*(from_rbf->nrbf*to_rbf->nrbf - 1); |
664 |
+ |
MIGRATION *newmig; |
665 |
+ |
#ifdef _WIN32 |
666 |
+ |
newmig = (MIGRATION *)malloc(memlen); |
667 |
+ |
#else |
668 |
+ |
if (nprocs <= 1) { /* single process? */ |
669 |
+ |
newmig = (MIGRATION *)malloc(memlen); |
670 |
+ |
} else { /* else need to share memory */ |
671 |
+ |
newmig = (MIGRATION *)mmap(NULL, memlen, PROT_READ|PROT_WRITE, |
672 |
+ |
MAP_ANON|MAP_SHARED, -1, 0); |
673 |
+ |
if ((void *)newmig == MAP_FAILED) |
674 |
+ |
newmig = NULL; |
675 |
+ |
} |
676 |
+ |
#endif |
677 |
+ |
if (newmig == NULL) { |
678 |
+ |
fprintf(stderr, "%s: cannot allocate new migration\n", progname); |
679 |
+ |
exit(1); |
680 |
+ |
} |
681 |
+ |
newmig->rbfv[0] = from_rbf; |
682 |
+ |
newmig->rbfv[1] = to_rbf; |
683 |
+ |
/* insert in edge lists */ |
684 |
+ |
newmig->enxt[0] = from_rbf->ejl; |
685 |
+ |
from_rbf->ejl = newmig; |
686 |
+ |
newmig->enxt[1] = to_rbf->ejl; |
687 |
+ |
to_rbf->ejl = newmig; |
688 |
+ |
newmig->next = mig_list; /* push onto global list */ |
689 |
+ |
return(mig_list = newmig); |
690 |
+ |
} |
691 |
+ |
|
692 |
+ |
#ifdef _WIN32 |
693 |
+ |
#define await_children(n) (void)(n) |
694 |
+ |
#define run_subprocess() 0 |
695 |
+ |
#define end_subprocess() (void)0 |
696 |
+ |
#else |
697 |
+ |
|
698 |
+ |
/* Wait for the specified number of child processes to complete */ |
699 |
+ |
static void |
700 |
+ |
await_children(int n) |
701 |
+ |
{ |
702 |
+ |
if (n > nchild) |
703 |
+ |
n = nchild; |
704 |
+ |
while (n-- > 0) { |
705 |
+ |
int status; |
706 |
+ |
if (wait(&status) < 0) { |
707 |
+ |
fprintf(stderr, "%s: missing child(ren)!\n", progname); |
708 |
+ |
nchild = 0; |
709 |
+ |
break; |
710 |
+ |
} |
711 |
+ |
--nchild; |
712 |
+ |
if (status) { |
713 |
+ |
if ((status = WEXITSTATUS(status))) |
714 |
+ |
exit(status); |
715 |
+ |
fprintf(stderr, "%s: subprocess died\n", progname); |
716 |
+ |
exit(1); |
717 |
+ |
} |
718 |
+ |
} |
719 |
+ |
} |
720 |
+ |
|
721 |
+ |
/* Start child process if multiprocessing selected */ |
722 |
+ |
static pid_t |
723 |
+ |
run_subprocess(void) |
724 |
+ |
{ |
725 |
+ |
int status; |
726 |
+ |
pid_t pid; |
727 |
+ |
|
728 |
+ |
if (nprocs <= 1) /* any children requested? */ |
729 |
+ |
return(0); |
730 |
+ |
await_children(nchild + 1 - nprocs); /* free up child process */ |
731 |
+ |
if ((pid = fork())) { |
732 |
+ |
if (pid < 0) { |
733 |
+ |
fprintf(stderr, "%s: cannot fork subprocess\n", |
734 |
+ |
progname); |
735 |
+ |
exit(1); |
736 |
+ |
} |
737 |
+ |
++nchild; /* subprocess started */ |
738 |
+ |
return(pid); |
739 |
+ |
} |
740 |
+ |
nchild = -1; |
741 |
+ |
return(0); /* put child to work */ |
742 |
+ |
} |
743 |
+ |
|
744 |
+ |
/* If we are in subprocess, call exit */ |
745 |
+ |
#define end_subprocess() if (nchild < 0) _exit(0); else |
746 |
+ |
|
747 |
+ |
#endif /* ! _WIN32 */ |
748 |
+ |
|
749 |
+ |
/* Compute and insert migration along directed edge (may fork child) */ |
750 |
+ |
static MIGRATION * |
751 |
+ |
create_migration(RBFNODE *from_rbf, RBFNODE *to_rbf) |
752 |
+ |
{ |
753 |
|
const double end_thresh = 0.02/(from_rbf->nrbf*to_rbf->nrbf); |
754 |
|
float *pmtx; |
755 |
|
MIGRATION *newmig; |
760 |
|
for (newmig = from_rbf->ejl; newmig != NULL; |
761 |
|
newmig = nextedge(from_rbf,newmig)) |
762 |
|
if (newmig->rbfv[1] == to_rbf) |
763 |
< |
return(creat_only ? (MIGRATION *)NULL : newmig); |
763 |
> |
return(NULL); |
764 |
|
/* else allocate */ |
765 |
+ |
newmig = new_migration(from_rbf, to_rbf); |
766 |
+ |
if (run_subprocess()) |
767 |
+ |
return(newmig); /* child continues */ |
768 |
|
pmtx = price_routes(from_rbf, to_rbf); |
665 |
– |
newmig = (MIGRATION *)malloc(sizeof(MIGRATION) + sizeof(float) * |
666 |
– |
(from_rbf->nrbf*to_rbf->nrbf - 1)); |
769 |
|
src_rem = (double *)malloc(sizeof(double)*from_rbf->nrbf); |
770 |
|
dst_rem = (double *)malloc(sizeof(double)*to_rbf->nrbf); |
771 |
< |
if ((newmig == NULL) | (src_rem == NULL) | (dst_rem == NULL)) { |
772 |
< |
fputs("Out of memory in make_migration()\n", stderr); |
771 |
> |
if ((src_rem == NULL) | (dst_rem == NULL)) { |
772 |
> |
fputs("Out of memory in create_migration()\n", stderr); |
773 |
|
exit(1); |
774 |
|
} |
775 |
|
#ifdef DEBUG |
776 |
< |
{ |
777 |
< |
fprintf(stderr, "Building path from (theta,phi) %s ", |
778 |
< |
thetaphi(from_rbf->invec)); |
779 |
< |
fprintf(stderr, "to %s", thetaphi(to_rbf->invec)); |
678 |
< |
} |
776 |
> |
fprintf(stderr, "Building path from (theta,phi) %s ", |
777 |
> |
thetaphi(from_rbf->invec)); |
778 |
> |
fprintf(stderr, "to %s", thetaphi(to_rbf->invec)); |
779 |
> |
/* if (nchild) */ fputc('\n', stderr); |
780 |
|
#endif |
680 |
– |
newmig->next = NULL; |
681 |
– |
newmig->rbfv[0] = from_rbf; |
682 |
– |
newmig->rbfv[1] = to_rbf; |
683 |
– |
newmig->enxt[0] = newmig->enxt[1] = NULL; |
684 |
– |
memset(newmig->mtx, 0, sizeof(float)*from_rbf->nrbf*to_rbf->nrbf); |
781 |
|
/* starting quantities */ |
782 |
+ |
memset(newmig->mtx, 0, sizeof(float)*from_rbf->nrbf*to_rbf->nrbf); |
783 |
|
for (i = from_rbf->nrbf; i--; ) |
784 |
|
src_rem[i] = rbf_volume(&from_rbf->rbfa[i]) / from_rbf->vtotal; |
785 |
|
for (i = to_rbf->nrbf; i--; ) |
788 |
|
while (total_rem > end_thresh) { |
789 |
|
total_rem -= migration_step(newmig, src_rem, dst_rem, pmtx); |
790 |
|
#ifdef DEBUG |
791 |
< |
/* fputc('.', stderr); */ |
792 |
< |
fprintf(stderr, "\n%.9f remaining...", total_rem); |
791 |
> |
if (!nchild) |
792 |
> |
/* fputc('.', stderr); */ |
793 |
> |
fprintf(stderr, "%.9f remaining...\r", total_rem); |
794 |
|
#endif |
795 |
|
} |
796 |
|
#ifdef DEBUG |
797 |
< |
fputs("done.\n", stderr); |
797 |
> |
if (!nchild) fputs("done.\n", stderr); |
798 |
|
#endif |
799 |
|
|
800 |
|
free(pmtx); /* free working arrays */ |
808 |
|
for (j = to_rbf->nrbf; j--; ) |
809 |
|
newmig->mtx[mtx_ndx(newmig,i,j)] *= nf; |
810 |
|
} |
811 |
< |
/* insert in edge lists */ |
812 |
< |
newmig->enxt[0] = from_rbf->ejl; |
715 |
< |
from_rbf->ejl = newmig; |
716 |
< |
newmig->enxt[1] = to_rbf->ejl; |
717 |
< |
to_rbf->ejl = newmig; |
718 |
< |
newmig->next = mig_list; |
719 |
< |
return(mig_list = newmig); |
811 |
> |
end_subprocess(); /* exit here if subprocess */ |
812 |
> |
return(newmig); |
813 |
|
} |
814 |
|
|
815 |
|
/* Get triangle surface orientation (unnormalized) */ |
937 |
|
tvert[0] = find_chull_vert(edge->rbfv[0], edge->rbfv[1]); |
938 |
|
if (tvert[0] != NULL) { |
939 |
|
if (tvert[0] > edge->rbfv[0]) |
940 |
< |
ej0 = make_migration(edge->rbfv[0], tvert[0], 1); |
940 |
> |
ej0 = create_migration(edge->rbfv[0], tvert[0]); |
941 |
|
else |
942 |
< |
ej0 = make_migration(tvert[0], edge->rbfv[0], 1); |
942 |
> |
ej0 = create_migration(tvert[0], edge->rbfv[0]); |
943 |
|
if (tvert[0] > edge->rbfv[1]) |
944 |
< |
ej1 = make_migration(edge->rbfv[1], tvert[0], 1); |
944 |
> |
ej1 = create_migration(edge->rbfv[1], tvert[0]); |
945 |
|
else |
946 |
< |
ej1 = make_migration(tvert[0], edge->rbfv[1], 1); |
946 |
> |
ej1 = create_migration(tvert[0], edge->rbfv[1]); |
947 |
|
mesh_from_edge(ej0); |
948 |
|
mesh_from_edge(ej1); |
949 |
|
} |
951 |
|
tvert[1] = find_chull_vert(edge->rbfv[1], edge->rbfv[0]); |
952 |
|
if (tvert[1] != NULL) { |
953 |
|
if (tvert[1] > edge->rbfv[0]) |
954 |
< |
ej0 = make_migration(edge->rbfv[0], tvert[1], 1); |
954 |
> |
ej0 = create_migration(edge->rbfv[0], tvert[1]); |
955 |
|
else |
956 |
< |
ej0 = make_migration(tvert[1], edge->rbfv[0], 1); |
956 |
> |
ej0 = create_migration(tvert[1], edge->rbfv[0]); |
957 |
|
if (tvert[1] > edge->rbfv[1]) |
958 |
< |
ej1 = make_migration(edge->rbfv[1], tvert[1], 1); |
958 |
> |
ej1 = create_migration(edge->rbfv[1], tvert[1]); |
959 |
|
else |
960 |
< |
ej1 = make_migration(tvert[1], edge->rbfv[1], 1); |
960 |
> |
ej1 = create_migration(tvert[1], edge->rbfv[1]); |
961 |
|
mesh_from_edge(ej0); |
962 |
|
mesh_from_edge(ej1); |
963 |
|
} |
1071 |
|
if (single_plane_incident) { |
1072 |
|
for (rbf0 = dsf_list; rbf0 != NULL; rbf0 = rbf0->next) |
1073 |
|
if (rbf0->next != NULL) |
1074 |
< |
make_migration(rbf0, rbf0->next, 1); |
1074 |
> |
create_migration(rbf0, rbf0->next); |
1075 |
> |
await_children(nchild); |
1076 |
|
return; |
1077 |
|
} |
1078 |
|
/* start w/ shortest edge */ |
1092 |
|
} |
1093 |
|
/* build mesh from this edge */ |
1094 |
|
if (shrt_edj[0] < shrt_edj[1]) |
1095 |
< |
mesh_from_edge(make_migration(shrt_edj[0], shrt_edj[1], 0)); |
1095 |
> |
mesh_from_edge(create_migration(shrt_edj[0], shrt_edj[1])); |
1096 |
|
else |
1097 |
< |
mesh_from_edge(make_migration(shrt_edj[1], shrt_edj[0], 0)); |
1097 |
> |
mesh_from_edge(create_migration(shrt_edj[1], shrt_edj[0])); |
1098 |
> |
/* complete migrations */ |
1099 |
> |
await_children(nchild); |
1100 |
|
/* draw edge list into grid */ |
1101 |
|
draw_edges(); |
1102 |
|
} |
1484 |
|
fflush(stdout); |
1485 |
|
ofp = popen(cmd, "w"); |
1486 |
|
if (ofp == NULL) { |
1487 |
< |
fputs("Cannot create pipe for rttree_reduce\n", stderr); |
1487 |
> |
fprintf(stderr, "%s: cannot create pipe to rttree_reduce\n", |
1488 |
> |
progname); |
1489 |
|
exit(1); |
1490 |
|
} |
1491 |
|
} else |
1512 |
|
} |
1513 |
|
if (pctcull >= 0) { /* finish output */ |
1514 |
|
if (pclose(ofp)) { |
1515 |
< |
fprintf(stderr, "Error running '%s'\n", cmd); |
1515 |
> |
fprintf(stderr, "%s: error running '%s'\n", |
1516 |
> |
progname, cmd); |
1517 |
|
exit(1); |
1518 |
|
} |
1519 |
|
} else { |
1544 |
|
fflush(stdout); |
1545 |
|
ofp = popen(cmd, "w"); |
1546 |
|
if (ofp == NULL) { |
1547 |
< |
fputs("Cannot create pipe for rttree_reduce\n", stderr); |
1547 |
> |
fprintf(stderr, "%s: cannot create pipe to rttree_reduce\n", |
1548 |
> |
progname); |
1549 |
|
exit(1); |
1550 |
|
} |
1551 |
|
} else |
1573 |
|
} |
1574 |
|
if (pctcull >= 0) { /* finish output */ |
1575 |
|
if (pclose(ofp)) { |
1576 |
< |
fprintf(stderr, "Error running '%s'\n", cmd); |
1576 |
> |
fprintf(stderr, "%s: error running '%s'\n", |
1577 |
> |
progname, cmd); |
1578 |
|
exit(1); |
1579 |
|
} |
1580 |
|
} else |
1590 |
|
double bsdf; |
1591 |
|
int i; |
1592 |
|
|
1593 |
< |
progname = argv[0]; |
1594 |
< |
if (argc > 2 && !strcmp(argv[1], "-t")) { |
1595 |
< |
pctcull = atoi(argv[2]); |
1593 |
> |
progname = argv[0]; /* get options */ |
1594 |
> |
while (argc > 2 && argv[1][0] == '-') { |
1595 |
> |
switch (argv[1][1]) { |
1596 |
> |
case 'n': |
1597 |
> |
nprocs = atoi(argv[2]); |
1598 |
> |
break; |
1599 |
> |
case 't': |
1600 |
> |
pctcull = atoi(argv[2]); |
1601 |
> |
break; |
1602 |
> |
default: |
1603 |
> |
goto userr; |
1604 |
> |
} |
1605 |
|
argv += 2; argc -= 2; |
1606 |
|
} |
1607 |
< |
if (argc < 3) { |
1608 |
< |
fprintf(stderr, |
1609 |
< |
"Usage: %s [-t pctcull] meas1.dat meas2.dat .. > bsdf.xml\n", |
1607 |
> |
if (argc < 3) |
1608 |
> |
goto userr; |
1609 |
> |
#ifdef _WIN32 |
1610 |
> |
if (nprocs > 1) { |
1611 |
> |
fprintf(stderr, "%s: multiprocessing not supported\n", |
1612 |
|
progname); |
1613 |
|
return(1); |
1614 |
|
} |
1615 |
+ |
#endif |
1616 |
|
for (i = 1; i < argc; i++) { /* compile measurements */ |
1617 |
|
if (!load_pabopto_meas(argv[i])) |
1618 |
|
return(1); |
1628 |
|
interp_anisotropic(); |
1629 |
|
/* xml_epilogue(); /* finish XML output */ |
1630 |
|
return(0); |
1631 |
+ |
userr: |
1632 |
+ |
fprintf(stderr, |
1633 |
+ |
"Usage: %s [-n nprocs][-t pctcull] meas1.dat meas2.dat .. > bsdf.xml\n", |
1634 |
+ |
progname); |
1635 |
+ |
return(1); |
1636 |
|
} |
1637 |
|
#else |
1638 |
|
/* Test main produces a Radiance model from the given input file */ |