particle *MakeParticle(particle *P, REAL ENE, REAL ANG, REAL AZI, unsigned int *seed) { REAL angle, azimuth; P->type = PROTON; P->energy = ENE; angle = ANG * M_PI / AS_REAL(180.0); azimuth = AZI * M_PI / AS_REAL(180.0); position_particle(azimuth, angle, P); #if DO_ELASTIC GenerateElasticDistances(P, seed); #endif #if MIN_TRACE P->eloss = AS_REAL(0.0); P->where = WhereAmI(P->pos[CX], P->pos[CY], P->pos[CZ]); #endif #if GOM_DEBUG if (VERBOSE) { print_particle("Made particle:", P); } #endif return(P); }
void MonteCarlo(collector *C, int NMC, REAL emean, REAL estdv, REAL sigma, REAL angle, REAL azimuth) { particle *P; trace *T; int NF; unsigned int seed; NF = 0; #if DEBUG printf("entering MonteCarlo for %d samples and storing into %lx (%d)\n", NMC, (long unsigned int) C, C->NTOTAL); #endif /* create the trace and particle */ fast_srand(&seed); T = alloc_trace(); P = (particle *) malloc(sizeof(particle)); /* the Monte Carlo loop */ //what is sigma?? if (sigma > AS_REAL(0.0)) { while (NF++ < NMC) { MakeParticle(P, normal(emean, estdv,&seed), angle+normal(AS_REAL(0.0), sigma,&seed), azimuth+normal(AS_REAL(0.0), sigma,&seed), &seed); reset_trace(T); while (P->energy > AS_REAL(0.0)) { proton_event(P, T, &seed); //stepping() } if (TRACE) dump_trace(stdout, T, P); collect(C, P, T); //Hits collection } } else { while (NF++ < NMC) { MakeParticle(P, normal(emean, estdv,&seed), angle, azimuth, &seed); reset_trace(T); while (P->energy > AS_REAL(0.0)) { proton_event(P, T, &seed); } if (TRACE) dump_trace(stdout, T, P); collect(C, P, T); } } }
void position_particle(ANGLE phi, ANGLE theta, particle *P) { int i; POSITION A[3], B[3], C[3], xy, d1, d2, dx, dy, dz; enum plane_type S[3]; /* A is the center */ A[CX] = ARENA->CEN[CX]; A[CY] = ARENA->CEN[CY]; A[CZ] = ARENA->CEN[CZ]; /* B is a point with phi/theta at Radius */ xy = ARENA->RADIUS * SIN(phi); B[CX] = A[CX] + xy * COS(theta); B[CY] = A[CY] + xy * SIN(theta); B[CZ] = A[CZ] + ARENA->RADIUS * COS(phi); /* check */ assert(inside(A)); assert(! inside(B)); #if GOM_DEBUG printf("entering position particle: phi=%7.3f theta=%7.3f\n\tA=(%7.3f,%7.3f,%7.3f) B=(%7.3f,%7.3f,%7.3f)\n", phi, theta, A[CX], A[CY], A[CZ], B[CX], B[CY], B[CZ]); #endif /* loop for NITER times */ for (i=0; i<NITER; i++) { C[CX] = AS_REAL(0.5)*(A[CX] + B[CX]); C[CY] = AS_REAL(0.5)*(A[CY] + B[CY]); C[CZ] = AS_REAL(0.5)*(A[CZ] + B[CZ]); if (inside(C)) { A[CX] = C[CX]; A[CY] = C[CY]; A[CZ] = C[CZ]; } else { B[CX] = C[CX]; B[CY] = C[CY]; B[CZ] = C[CZ]; } } #if GOM_DEBUG printf("after binary search C: %7.3f %7.3f %7.3f\n", C[CX], C[CY], C[CZ]); #endif /* calculate distances to nearest plane in X/Y/Z */ d1 = ABS(A[CX]-ARENA->MIN[CX]); d2 = ABS(A[CX]-ARENA->MAX[CX]); if (d1 < d2) { dx = d1; S[CX] = WEST; } else { dx = d2; S[CX] = EAST; } d1 = ABS(A[CY]-ARENA->MIN[CY]); d2 = ABS(A[CY]-ARENA->MAX[CY]); if (d1 < d2) { dy = d1; S[CY] = NORTH; } else { dy = d2; S[CY] = SOUTH; } d1 = ABS(A[CZ]-ARENA->MIN[CZ]); d2 = ABS(A[CZ]-ARENA->MAX[CZ]); if (d1 < d2) { dz = d1; S[CZ] = BOTTOM; } else { dz = d2; S[CZ] = TOP; } #if GOM_DEBUG printf("distances: %7.3f %s %7.3f %s %7.3f %s\n", dx, plane_name[(int) S[CX]], dy, plane_name[(int) S[CY]], dz, plane_name[(int) S[CZ]]); #endif /* find the closest one and snap the appropriate coordinate */ if (dx <= dy) { if (dx <= dz) { C[CX] = (S[CX] == WEST ? ARENA->MIN[CX] : ARENA->MAX[CX]); } else { C[CZ] = (S[CZ] == BOTTOM ? ARENA->MIN[CZ] : ARENA->MAX[CZ]); } } else { if (dy <= dz) { C[CY] = (S[CY] == NORTH ? ARENA->MIN[CY] : ARENA->MAX[CY]); } else { C[CZ] = (S[CZ] == BOTTOM ? ARENA->MIN[CZ] : ARENA->MAX[CZ]); } } P->pos[CX] = C[CX]; P->pos[CY] = C[CY]; P->pos[CZ] = C[CZ]; C[CX] -= ARENA->CEN[CX]; C[CY] -= ARENA->CEN[CY]; C[CZ] -= ARENA->CEN[CZ]; d1 = SQRT(C[CX]*C[CX] + C[CY]*C[CY] + C[CZ]*C[CZ]); P->dir[CX] = -C[CX]/d1; P->dir[CY] = -C[CY]/d1; P->dir[CZ] = -C[CZ]/d1; #if GOM_DEBUG printf("final C: %7.3f %7.3f %7.3f -> %7.3f %7.3f %7.3f\n", P->pos[CX], P->pos[CY], P->pos[CZ], P->dir[CX], P->dir[CY], P->dir[CZ]); #endif }
/* intialize path to MRI file */ char *MRIFIL = NULL; /* intialize path to LOCATION (0/1) file */ char *LOCFIL = NULL; /* intialize path to binary output file */ char *BOUTFIL = NULL; /* intialize path to text output file */ char *TOUTFIL = NULL; /* verbosity switch */ int VERBOSE = 1; /* trace switch */ int TRACE = 0; /* the geometry */ arena* ARENA = NULL; /* MRI voxel size */ REAL PIXEL = AS_REAL(0.0); /* threshold for dumping voxels (proportion of maximum) */ REAL THR = AS_REAL(0.01); /* this describes the options */ ParamDescriptor _params[] = { /* name type dflt mandatory */ { "nmc", P_INTEGER, "10000", 0, }, { "mean", P_REAL, "100", 0, }, /* 100MeV */ { "stdv", P_REAL, "2", 0, }, /* 2MeV */ { "sigma", P_REAL, "0.01", 0, }, /* initial postion sigma */ { "path", P_PATH, "./tables", 0, }, /* path to where the tables are */ { "mri", P_READ, 0, 0, }, /* path to an MRI cube file */ { "trace", P_FLAG, "0", 0, }, /* generate traces? */ { "plot", P_FLAG, "0", 0, }, /* make plot file? */ { "angle", P_REAL, "0.0", 0, }, /* angle in XY plane */ { "azimuth", P_REAL, "90.0", 0, }, /* angle to Z axis */
void execute_function(VM *vm) { restart: { Frame *frame = vm->current; Closure *closure = frame->closure; Chunk *chunk = closure->chunk; StackObject *registers = frame->registers; while (frame->pc < chunk->numinstructions) { int instruction = chunk->instructions[frame->pc]; OpCode o = GET_O(instruction); int a = GET_A(instruction); int b = GET_B(instruction); int c = GET_C(instruction); switch (o) { case OP_MOVE: { if (b < 256) { copy_object(®isters[a], ®isters[b]); } else { copy_constant(vm, ®isters[a], chunk->constants[b - 256]); } } break; case OP_GETUPVAR: { Upval *upval = closure->upvals[b]; if (!upval->open) { // upval is closed copy_object(®isters[a], upval->data.o); } else { // still on stack copy_object(®isters[a], &upval->data.ref.frame->registers[upval->data.ref.slot]); } } break; case OP_SETUPVAR: { Upval *upval = closure->upvals[b]; if (!upval->open) { // upval is closed copy_object(upval->data.o, ®isters[a]); } else { // still on stack copy_object(&upval->data.ref.frame->registers[upval->data.ref.slot], ®isters[a]); } } break; case OP_ADD: { // TODO - make string coercion better // TODO - make string type with special operators if (IS_STR(b) || IS_STR(c)) { char *arg1 = TO_STR(b); char *arg2 = TO_STR(c); char *arg3 = malloc((strlen(arg1) + strlen(arg2) + 1) + sizeof *arg3); strcpy(arg3, arg1); strcat(arg3, arg2); registers[a].value.o = make_string_ref(vm, arg3); registers[a].type = OBJECT_REFERENCE; // put this after free(arg1); free(arg2); } else { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Cannot add types."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 + arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 + arg2; } } } break; case OP_SUB: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to sub non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 - arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 - arg2; } } break; case OP_MUL: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to mul non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 * arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 * arg2; } } break; case OP_DIV: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if ((IS_INT(c) && AS_INT(c) == 0) || (IS_REAL(c) && AS_REAL(c) == 0)) { fatal("Div by 0."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 / arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = arg1 / arg2; } } break; case OP_MOD: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if ((IS_INT(c) && AS_INT(c) == 0) || (IS_REAL(c) && AS_REAL(c) == 0)) { fatal("Mod by 0."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = arg1 % arg2; } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.i = fmod(arg1, arg2); } } break; case OP_POW: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to div non-numbers."); } if (IS_INT(b) && IS_INT(c)) { int arg1 = AS_INT(b); int arg2 = AS_INT(c); registers[a].type = OBJECT_INT; registers[a].value.i = (int) pow(arg1, arg2); } else { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_REAL; registers[a].value.d = pow(arg1, arg2); } } break; case OP_NEG: { if (IS_INT(b)) { registers[a].type = OBJECT_INT; registers[a].value.i = -AS_INT(b); } else if (IS_REAL(b)) { registers[a].type = OBJECT_INT; registers[a].value.i = -AS_REAL(b); } else { fatal("Tried to negate non-numeric type."); } } break; case OP_NOT: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } registers[a].value.i = registers[a].value.i == 1 ? 0 : 1; } break; case OP_EQ: { if ((IS_INT(b) || IS_REAL(b)) && (IS_INT(c) || IS_REAL(c))) { double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 == arg2; } else { fatal("Comparison of reference types not yet supported."); } } break; case OP_LT: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to compare non-numbers."); } double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 < arg2; } break; case OP_LE: { if (!(IS_INT(b) || IS_REAL(b)) || !(IS_INT(c) || IS_REAL(c))) { fatal("Tried to compare non-numbers."); } double arg1 = IS_INT(b) ? (double) AS_INT(b) : AS_REAL(b); double arg2 = IS_INT(c) ? (double) AS_INT(c) : AS_REAL(c); registers[a].type = OBJECT_BOOL; registers[a].value.i = arg1 <= arg2; } break; case OP_CLOSURE: { Closure *child = make_closure(chunk->children[b]); int i; for (i = 0; i < chunk->children[b]->numupvars; i++) { int inst = chunk->instructions[++frame->pc]; OpCode oc = GET_O(inst); int ac = GET_A(inst); int bc = GET_B(inst); int cc = GET_C(inst); if (oc == OP_MOVE) { // first upval for this variable child->upvals[ac] = make_upval(vm, bc); } else { // share upval child->upvals[ac] = closure->upvals[bc]; child->upvals[ac]->refcount++; } } registers[a].value.o = make_closure_ref(vm, child); registers[a].type = OBJECT_REFERENCE; // put this after } break; case OP_CALL: { if (registers[b].type != OBJECT_REFERENCE || registers[b].value.o->type != OBJECT_CLOSURE) { fatal("Tried to call non-closure."); } // TODO - safety issue (see compile.c for notes) Closure *child = registers[b].value.o->value.c; Frame *subframe = make_frame(frame, child); int i; for (i = 0; i < child->chunk->numparams; i++) { copy_object(&subframe->registers[i + 1], ®isters[c + i]); } vm->current = subframe; goto restart; } break; case OP_RETURN: { UpvalNode *head; for (head = vm->open; head != NULL; ) { Upval *u = head->upval; if (u->data.ref.frame == frame) { StackObject *o = malloc(sizeof *o); if (!o) { fatal("Out of memory."); } u->open = 0; copy_object(o, ®isters[u->data.ref.slot]); u->data.o = o; if (vm->open == head) { vm->open = head->next; } else { head->next->prev = head->prev; head->prev->next = head->next; } UpvalNode *temp = head; head = head->next; free(temp); } else { head = head->next; } } if (vm->current->parent != NULL) { Frame *p = vm->current->parent; StackObject *target = &p->registers[GET_A(p->closure->chunk->instructions[p->pc++])]; if (b < 256) { // debug char *d = obj_to_str(®isters[b]); printf("Return value: %s\n", d); free(d); copy_object(target, ®isters[b]); } else { copy_constant(vm, target, chunk->constants[b - 256]); } free_frame(frame); vm->current = p; goto restart; } else { // debug char *d = obj_to_str(®isters[b]); printf("Return value: %s\n", d); free(d); free_frame(frame); vm->current = NULL; return; } } break; case OP_JUMP: frame->pc += c ? -b : b; break; case OP_JUMP_TRUE: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } if (registers[a].value.i == 1) { frame->pc += c ? -b : b; } } break; case OP_JUMP_FALSE: { if (registers[a].type != OBJECT_BOOL) { fatal("Expected boolean type, not %d.", registers[a].type); } if (registers[a].value.i == 0) { frame->pc += c ? -b : b; } } break; case OP_ENTER_TRY: { vm->catchframe = make_catch_frame(frame, vm->catchframe, frame->pc + b); } break; case OP_LEAVE_TRY: { CatchFrame *temp = vm->catchframe; vm->catchframe = vm->catchframe->parent; free_catch_frame(temp); } break; case OP_THROW: { // TODO - replace unwinding of stack with an exceptions // table per-chunk. It will have an instructions range, // the starting instruction of a handler, and the type of // exception that it may handle. // Exception table: // From To Target Type // 0 4 5 Class TestExc1 // 0 12 12 Class TestExc2 // TODO - implement a way to expect an exception // of a given type instead of a generic catch-all. char *s = obj_to_str(®isters[a]); printf("Exception value: %s!\n", s); free(s); // TODO - this is probably wrong. Not sure how complicated // it will be to handle upvalues and frame destruction here, // so we're just doing it a shitty way for now :D [GO LAZE]. if (!vm->catchframe) { // TODO - print a stack trace [ requires debug symbols :( ] fatal("Exception thrown outside of handler."); } while (vm->current != vm->catchframe->frame) { // TODO - destruct frame vm->current = vm->current->parent; } vm->current->pc = vm->catchframe->target; CatchFrame *temp = vm->catchframe; vm->catchframe = vm->catchframe->parent; free_catch_frame(temp); goto restart; } break; } frame->pc++; } fatal("VM left instruction-space."); } }