static struct xpr rred (struct xpr z, int kf, int *ps) { struct xpr is, q; if (x_neg (&z)) { z = xneg (z); is = xOne; } else is = xZero; z = xfmod (z, xPi, &q); if (kf == 't') q = is; else if (kf == 's') q = xadd (q, is, 0); if (xprcmp (&z, &xPi2) == 1) { z = xadd (xPi, z, 1); if (kf == 'c' || kf == 't') q = xadd (q, xOne, 0); } *ps = (xodd (q)) ? 1 : 0; return z; }
struct xpr cxarg (struct cxpr z) { int rs, is; rs = xsgn (&z.re); is = xsgn (&z.im); if (rs > 0) return xatan (xdiv (z.im, z.re)); else if (rs < 0) { z.re.nmm[0] ^= xM_sgn; z.im.nmm[0] ^= xM_sgn; if (is >= 0) return xadd (xPi, xatan (xdiv (z.im, z.re)), 0); else return xadd (xatan (xdiv (z.im, z.re)), xPi, 1); } else /* z.re is zero ! */ { if (!xsigerr (is == 0, XEDOM, "cxarg()")) return (is > 0 ? xPi2 : xneg (xPi2)); else return xneg (xPi2); /* Dummy value :) */ } }
int main (int na, char **av) { struct xpr s, t, f; char nbx[64], nby[64]; FILE *fp; if (na != 2) { printf ("para: input_file\n"); exit (-1); } fp = fopen (*++av, "r"); printf (" Test of Elementary Operations\n"); while (fscanf (fp, "%s %s", nbx, nby) != EOF) { s = atox (nbx); t = atox (nby); printf ("\n x= "); xprxpr (s, decd); printf ("\n y= "); xprxpr (t, decd); /* extended precision addition */ printf ("\nadd\n"); f = xadd (s, t, 0); printf (" %16.10f\n", xtodbl (f)); xprxpr (f, decd); /* extended precision subtraction */ printf ("\nsubtract\n"); f = xadd (s, t, 1); printf (" %16.10f\n", xtodbl (f)); xprxpr (f, decd); /* extended precision multiplication */ printf ("\nmultiply\n"); f = xmul (s, t); printf (" %16.10f\n", xtodbl (f)); xprxpr (f, decd); /* extended precision division */ printf ("\ndivide\n"); f = xdiv (s, t); printf (" %16.10f\n", xtodbl (f)); xprxpr (f, decd); } putchar ('\n'); return 0; }
void runtime·entersyscall(void) { uint32 v; if(m->profilehz > 0) runtime·setprof(false); // Leave SP around for gc and traceback. runtime·gosave(&g->sched); g->gcsp = g->sched.sp; g->gcstack = g->stackbase; g->gcguard = g->stackguard; g->status = Gsyscall; if(g->gcsp < g->gcguard-StackGuard || g->gcstack < g->gcsp) { // runtime·printf("entersyscall inconsistent %p [%p,%p]\n", // g->gcsp, g->gcguard-StackGuard, g->gcstack); runtime·throw("entersyscall"); } // Fast path. // The slow path inside the schedlock/schedunlock will get // through without stopping if it does: // mcpu-- // gwait not true // waitstop && mcpu <= mcpumax not true // If we can do the same with a single atomic add, // then we can skip the locks. v = runtime·xadd(&runtime·sched.atomic, -1<<mcpuShift); if(!atomic_gwaiting(v) && (!atomic_waitstop(v) || atomic_mcpu(v) > atomic_mcpumax(v))) return; schedlock(); v = runtime·atomicload(&runtime·sched.atomic); if(atomic_gwaiting(v)) { matchmg(); v = runtime·atomicload(&runtime·sched.atomic); } if(atomic_waitstop(v) && atomic_mcpu(v) <= atomic_mcpumax(v)) { runtime·xadd(&runtime·sched.atomic, -1<<waitstopShift); runtime·notewakeup(&runtime·sched.stopped); } // Re-save sched in case one of the calls // (notewakeup, matchmg) triggered something using it. runtime·gosave(&g->sched); schedunlock(); }
struct xpr cxabs (struct cxpr z) { struct xpr x; int ea, eb; if (xprcmp (&z.re, &xZero) == 0 && xprcmp (&z.im, &xZero) == 0) return xZero; else { ea = (z.re.nmm[0] &= xM_exp) - xBias; eb = (z.im.nmm[0] &= xM_exp) - xBias; if (ea > eb + XBOUND) return z.re; else if (eb > ea + XBOUND) return z.im; else { z.re.nmm[0] -= eb; z.im.nmm[0] = xBias; x = xsqrt (xadd (xmul (z.re, z.re), xmul (z.im, z.im), 0)); x.nmm[0] += eb; return x; } } }
struct xpr xtan (struct xpr z) { int k, m; z = rred (z, 't', &k); if ((xsigerr (xprcmp (&z, &xPi2) >= 0, XEDOM, "xtan()"))) return (!k ? xPinf : xMinf); else { if (xprcmp (&z, &xPi4) == 1) { m = 1; z = xadd (xPi2, z, 1); } else m = 0; if ((k)) z = xneg (c_tan (z)); else z = c_tan (z); if (m) return xdiv (xOne, z); else return z; } }
int main (void) { struct xpr z, h, f, u; printf (" Test of Exp Functions\n"); z = xneg (xOne); h = atox ("0.5"); u = atox ("3.01"); for (; xprcmp (&z, &u) < 0; z = xadd (z, h, 0)) { /* compute extended precision exponential */ f = xexp (z); printf (" %8.4f ", xtodbl (z)); xprxpr (f, decd); f = xexp2 (z); printf ("\n "); xprxpr (f, decd); f = xexp10 (z); printf ("\n "); xprxpr (f, decd); putchar ('\n'); } return 0; }
void runtime·dopanic(int32 unused) { static bool didothers; if(g->sig != 0) runtime·printf("[signal %x code=%p addr=%p pc=%p]\n", g->sig, g->sigcode0, g->sigcode1, g->sigpc); if(runtime·gotraceback()){ if(g != m->g0) { runtime·printf("\n"); runtime·goroutineheader(g); runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g); } if(!didothers) { didothers = true; runtime·tracebackothers(g); } } runtime·unlock(&paniclk); if(runtime·xadd(&runtime·panicking, -1) != 0) { // Some other m is panicking too. // Let it print what it needs to print. // Wait forever without chewing up cpu. // It will exit when it's done. static Lock deadlock; runtime·lock(&deadlock); runtime·lock(&deadlock); } runtime·exit(2); }
// Put on `g' queue. Sched must be locked. static void gput(G *g) { M *m; // If g is wired, hand it off directly. if((m = g->lockedm) != nil && canaddmcpu()) { mnextg(m, g); return; } // If g is the idle goroutine for an m, hand it off. if(g->idlem != nil) { if(g->idlem->idleg != nil) { runtime·printf("m%d idle out of sync: g%d g%d\n", g->idlem->id, g->idlem->idleg->goid, g->goid); runtime·throw("runtime: double idle"); } g->idlem->idleg = g; return; } g->schedlink = nil; if(runtime·sched.ghead == nil) runtime·sched.ghead = g; else runtime·sched.gtail->schedlink = g; runtime·sched.gtail = g; // increment gwait. // if it transitions to nonzero, set atomic gwaiting bit. if(runtime·sched.gwait++ == 0) runtime·xadd(&runtime·sched.atomic, 1<<gwaitingShift); }
int cxrec (struct cxpr z, struct cxpr *w) { struct xpr x; int sa, sb, ea, eb; if (xprcmp (&z.re, &xZero) == 0 && xprcmp (&z.im, &xZero) == 0) return 0; else { sa = z.re.nmm[0] & xM_sgn; sb = z.im.nmm[0] & xM_sgn; ea = (z.re.nmm[0] &= xM_exp) - xBias; eb = (z.im.nmm[0] &= xM_exp) - xBias; if (ea > eb + XBOUND) x = z.re; else if (eb > ea + XBOUND) x = z.im; else { z.re.nmm[0] -= eb; z.im.nmm[0] = xBias; x = xsqrt (xadd (xmul (z.re, z.re), xmul (z.im, z.im), 0)); x.nmm[0] += eb; z.re.nmm[0] += eb; z.im.nmm[0] += eb; } w->re = xdiv (xdiv (z.re, x), x); w->im = xdiv (xdiv (z.im, x), x); w->re.nmm[0] |= sa; w->im.nmm[0] |= xM_sgn ^ sb; return 1; } }
// User-level semaphore implementation: // try to do the operations in user space on u, // but when it's time to block, fall back on the kernel semaphore k. // This is the same algorithm used in Plan 9. void usemacquire(Usema *s) { if((int32)xadd(&s->u, -1) < 0) { if(s->k == 0) initsema(&s->k); mach_semacquire(s->k); } }
void usemrelease(Usema *s) { if((int32)xadd(&s->u, 1) <= 0) { if(s->k == 0) initsema(&s->k); mach_semrelease(s->k); } }
void canonic_form (struct xpr *px) { unsigned short *p, u; short e, i, j, skip; p = (unsigned short *) px; e = (*p & xM_exp); /* biased exponent of x */ u = (*p & xM_sgn); /* sign of x */ if (e < xBias - 1) return; else { unsigned short mask = 0xffff; /* e >= xBias - 1 */ for (i = 1, skip = e + 1 - xBias; skip / 16 > 0; i++, skip -= 16); if (i <= XDIM) { /* skip = 0, ..., 15 */ mask >>= skip; if ((p[i] & mask) != mask) return; else { for (j = i + 1; j <= XDIM && p[j] == 0xffff; j++); if (j > XDIM) { p[i] -= mask; for (j = i + 1; j <= XDIM; p[j] = 0, j++); if (!(p[1] & 0x8000)) { p[1] = 0x8000; *p = ++e; *p |= u; } else if ((u)) *px = xadd (*px, xOne, 1); else *px = xadd (*px, xOne, 0); } } } /* end if(i <= XDIM ) */ } /* end outer else */
static void eventlock(Lock *l) { // Allocate event if needed. if(l->event == 0) initevent(&l->event); if(xadd(&l->key, 1) > 1) // someone else has it; wait stdcall(WaitForSingleObject, l->event, -1); }
static void eventlock(Lock *l) { // Allocate event if needed. if(l->event == 0) initevent(&l->event); if(runtime·xadd(&l->key, 1) > 1) // someone else has it; wait runtime·stdcall(runtime·WaitForSingleObject, 2, l->event, (uintptr)-1); }
int main (void) { struct xpr z, w, f, u; int k; char cf[3]; cf[0] = 's'; cf[1] = 'c'; cf[2] = 't'; for (k = 0; k < 3; ++k) { switch (cf[k]) { case 't': printf (" Test of Atanh Function\n"); break; case 's': printf (" Test of Asinh Function\n"); break; case 'c': printf (" Test of Acosh Function\n"); break; } z = atox ("-3.10"); w = atox ("0.2"); u = atox ("3"); for (; xprcmp (&z, &u) < 0; z = xadd (z, w, 0)) { xErrNo = 0; /* compute selected extended precision hyperbolic function */ switch (cf[k]) { case 't': f = xatanh (z); break; case 's': f = xasinh (z); break; case 'c': f = xacosh (z); break; } if (!xErrNo) { printf (" %8.4f ", xtodbl (z)); xprxpr (f, decd); putchar ('\n'); } else printf ("*** Out of range\n"); } } return 0; }
void runtime·startpanic(void) { if(m->dying) { runtime·printf("panic during panic\n"); runtime·exit(3); } m->dying = 1; runtime·xadd(&runtime·panicking, 1); runtime·lock(&paniclk); }
struct xpr xcos (struct xpr z) { int k; z = rred (z, 'c', &k); if (x_exp (&z) < xK_lin) { if ((k)) return xneg (xOne); else return xOne; } z = c_tan (xpr2 (z, -1)); z = xmul (z, z); z = xdiv (xadd (xOne, z, 1), xadd (xOne, z, 0)); if ((k)) return xneg (z); else return z; }
void lock(Lock *l) { if(m->locks < 0) throw("lock count"); m->locks++; if(xadd(&l->key, 1) > 1) { // someone else has it; wait // Allocate semaphore if needed. if(l->sema == 0) initsema(&l->sema); mach_semacquire(l->sema); } }
void unlock(Lock *l) { m->locks--; if(m->locks < 0) throw("lock count"); if(xadd(&l->key, -1) > 0) { // someone else is waiting // Allocate semaphore if needed. if(l->sema == 0) initsema(&l->sema); mach_semrelease(l->sema); } }
int adjacent_to (int board[][BOARD_HEIGHT], int i, int j) { int k, l, count; count = 0; /* go around the cell */ for (k=-1; k<=1; k++) for (l=-1; l<=1; l++) /* only count if at least one of k,l isn't zero */ if (k || l) if (board[xadd(i,k)][yadd(j,l)]) count++; return count; }
static struct xpr c_tan (struct xpr z) { struct xpr s, f, d; int m; unsigned short k; if (x_exp (&z) < xK_lin) return z; s = xneg (xmul (z, z)); for (k = 1; k <= XDIM && s.nmm[k] == 0; k++); if ((xsigerr (s.nmm[0] == 0xffff && k > XDIM, XFPOFLOW, NULL))) return xZero; else { f = xZero; for (d = inttox (m = xMS_trg); m > 1;) { f = xdiv (s, xadd (d, f, 0)); d = inttox (m -= 2); } return xdiv (z, xadd (d, f, 0)); } }
struct xpr xsin (struct xpr z) { int k; z = rred (z, 's', &k); if (x_exp (&z) >= xK_lin) { z = c_tan (xpr2 (z, -1)); z = xdiv (xpr2 (z, 1), xadd (xOne, xmul (z, z), 0)); } if ((k)) return xneg (z); else return z; }
void runtime·startpanic(void) { if(runtime·mheap == 0 || runtime·mheap->cachealloc.size == 0) { // very early runtime·printf("runtime: panic before malloc heap initialized\n"); m->mallocing = 1; // tell rest of panic not to try to malloc } else if(m->mcache == nil) // can happen if called from signal handler or throw m->mcache = runtime·allocmcache(); if(m->dying) { runtime·printf("panic during panic\n"); runtime·exit(3); } m->dying = 1; runtime·xadd(&runtime·panicking, 1); runtime·lock(&paniclk); }
struct cxpr cxatanh (struct cxpr z) { struct cxpr w; struct xpr t; int errcond; t = xadd (xabs (z.re), xOne, 1); errcond = xsgn (&z.im) == 0 && xsgn (&t) == 0; if (xsigerr (errcond, XEDOM, "cxatanh()")) return cxZero; else { w = cxdiv (cxsum (cxOne, z), cxsub (cxOne, z)); w = cxlog_sqrt (w); return w; } }
// The goroutine g exited its system call. // Arrange for it to run on a cpu again. // This is called only from the go syscall library, not // from the low-level system calls used by the runtime. void runtime·exitsyscall(void) { uint32 v; // Fast path. // If we can do the mcpu++ bookkeeping and // find that we still have mcpu <= mcpumax, then we can // start executing Go code immediately, without having to // schedlock/schedunlock. v = runtime·xadd(&runtime·sched.atomic, (1<<mcpuShift)); if(m->profilehz == runtime·sched.profilehz && atomic_mcpu(v) <= atomic_mcpumax(v)) { // There's a cpu for us, so we can run. g->status = Grunning; // Garbage collector isn't running (since we are), // so okay to clear gcstack. g->gcstack = nil; if(m->profilehz > 0) runtime·setprof(true); return; } // Tell scheduler to put g back on the run queue: // mostly equivalent to g->status = Grunning, // but keeps the garbage collector from thinking // that g is running right now, which it's not. g->readyonstop = 1; // All the cpus are taken. // The scheduler will ready g and put this m to sleep. // When the scheduler takes g away from m, // it will undo the runtime·sched.mcpu++ above. runtime·gosched(); // Gosched returned, so we're allowed to run now. // Delete the gcstack information that we left for // the garbage collector during the system call. // Must wait until now because until gosched returns // we don't know for sure that the garbage collector // is not running. g->gcstack = nil; }
int main (void) { struct xpr z, w, f, u; printf (" Test of Sqrt Function\n"); z = xZero; w = atox ("0.2"); u = atox ("4.01"); for (; xprcmp (&z, &u) < 0; z = xadd (z, w, 0)) { /* compute extended precision square root */ f = xsqrt (z); printf (" %8.4f ", xtodbl (z)); xprxpr (f, decd); putchar ('\n'); } return 0; }
// Get from `g' queue. Sched must be locked. static G* gget(void) { G *g; g = runtime·sched.ghead; if(g){ runtime·sched.ghead = g->schedlink; if(runtime·sched.ghead == nil) runtime·sched.gtail = nil; // decrement gwait. // if it transitions to zero, clear atomic gwaiting bit. if(--runtime·sched.gwait == 0) runtime·xadd(&runtime·sched.atomic, -1<<gwaitingShift); } else if(m->idleg != nil) { g = m->idleg; m->idleg = nil; } return g; }
void runtime·startpanic(void) { if(runtime·mheap.cachealloc.size == 0) { // very early runtime·printf("runtime: panic before malloc heap initialized\n"); m->mallocing = 1; // tell rest of panic not to try to malloc } else if(m->mcache == nil) // can happen if called from signal handler or throw m->mcache = runtime·allocmcache(); switch(m->dying) { case 0: m->dying = 1; if(g != nil) g->writebuf = nil; runtime·xadd(&runtime·panicking, 1); runtime·lock(&paniclk); if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0) runtime·schedtrace(true); runtime·freezetheworld(); return; case 1: // Something failed while panicing, probably the print of the // argument to panic(). Just print a stack trace and exit. m->dying = 2; runtime·printf("panic during panic\n"); runtime·dopanic(0); runtime·exit(3); case 2: // This is a genuine bug in the runtime, we couldn't even // print the stack trace successfully. m->dying = 3; runtime·printf("stack trace unavailable\n"); runtime·exit(4); default: // Can't even print! Just exit. runtime·exit(5); } }
static char* xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign) { char s2[NSIGNIF+10]; double g, h; int e, d, i; int c2, sign, oerr; if(chr == 'F') chr = 'f'; if(prec > NSIGNIF) prec = NSIGNIF; if(prec < 0) prec = 0; if(__isNaN(f)) { *decpt = 9999; *rsign = 0; strcpy(s1, "nan"); return &s1[3]; } sign = 0; if(f < 0) { f = -f; sign++; } *rsign = sign; if(__isInf(f, 1) || __isInf(f, -1)) { *decpt = 9999; strcpy(s1, "inf"); return &s1[3]; } e = 0; g = f; if(g != 0) { frexp(f, &e); e = (int)(e * .301029995664); if(e >= -150 && e <= +150) { d = 0; h = f; } else { d = e/2; h = f * pow10(-d); } g = h * pow10(d-e); while(g < 1) { e--; g = h * pow10(d-e); } while(g >= 10) { e++; g = h * pow10(d-e); } } /* * convert NSIGNIF digits and convert * back to get accuracy. */ for(i=0; i<NSIGNIF; i++) { d = (int)g; s1[i] = d + '0'; g = (g - d) * 10; } s1[i] = 0; /* * try decimal rounding to eliminate 9s */ c2 = prec + 1; if(chr == 'f') c2 += e; oerr = errno; if(c2 >= NSIGNIF-2) { strcpy(s2, s1); d = e; s1[NSIGNIF-2] = '0'; s1[NSIGNIF-1] = '0'; xaddexp(s1+NSIGNIF, e-NSIGNIF+1); g = fmtstrtod(s1, nil); if(g == f) goto found; if(xadd(s1, NSIGNIF-3, 1)) { e++; xaddexp(s1+NSIGNIF, e-NSIGNIF+1); } g = fmtstrtod(s1, nil); if(g == f) goto found; strcpy(s1, s2); e = d; } /* * convert back so s1 gets exact answer */ for(d = 0; d < 10; d++) { xaddexp(s1+NSIGNIF, e-NSIGNIF+1); g = fmtstrtod(s1, nil); if(f > g) { if(xadd(s1, NSIGNIF-1, 1)) e--; continue; } if(f < g) { if(xsub(s1, NSIGNIF-1, 1)) e++; continue; } break; } found: errno = oerr; /* * sign */ d = 0; i = 0; /* * round & adjust 'f' digits */ c2 = prec + 1; if(chr == 'f'){ if(xadd(s1, c2+e, 5)) e++; c2 += e; if(c2 < 0){ c2 = 0; e = -prec - 1; } }else{ if(xadd(s1, c2, 5)) e++; } if(c2 > NSIGNIF){ c2 = NSIGNIF; } *decpt = e + 1; /* * terminate the converted digits */ s1[c2] = '\0'; return &s1[c2]; }