dcomplex csqrt(dcomplex z) { dcomplex ans; double x, y, t, ax, ay; int n, ix, iy, hx, hy, lx, ly; x = D_RE(z); y = D_IM(z); hx = HI_WORD(x); lx = LO_WORD(x); hy = HI_WORD(y); ly = LO_WORD(y); ix = hx & 0x7fffffff; iy = hy & 0x7fffffff; ay = fabs(y); ax = fabs(x); if (ix >= 0x7ff00000 || iy >= 0x7ff00000) { /* x or y is Inf or NaN */ if (ISINF(iy, ly)) D_IM(ans) = D_RE(ans) = ay; else if (ISINF(ix, lx)) { if (hx > 0) { D_RE(ans) = ax; D_IM(ans) = ay * zero; } else { D_RE(ans) = ay * zero; D_IM(ans) = ax; } } else D_IM(ans) = D_RE(ans) = ax + ay; } else if ((iy | ly) == 0) { /* y = 0 */ if (hx >= 0) { D_RE(ans) = sqrt(ax); D_IM(ans) = zero; } else { D_IM(ans) = sqrt(ax); D_RE(ans) = zero; } } else if (ix >= iy) { n = (ix - iy) >> 20; if (n >= 30) { /* x >> y or y=0 */ t = sqrt(ax); } else if (ix >= 0x5f300000) { /* x > 2**500 */ ax *= twom601; y *= twom601; t = two300 * sqrt(ax + sqrt(ax * ax + y * y)); } else if (iy < 0x20b00000) { /* y < 2**-500 */ ax *= two599; y *= two599; t = twom300 * sqrt(ax + sqrt(ax * ax + y * y)); } else t = sqrt(half * (ax + sqrt(ax * ax + ay * ay))); if (hx >= 0) { D_RE(ans) = t; D_IM(ans) = ay / (t + t); } else { D_IM(ans) = t; D_RE(ans) = ay / (t + t); } } else {
/* * arctan(x): * * if (x < 0) { * x = abs(x); * sign = 1; * } * y = arctan(x); * if (sign) { * y = -y; * } */ struct fpn * fpu_atan(struct fpemu *fe) { struct fpn a; struct fpn x; struct fpn v; if (ISNAN(&fe->fe_f2)) return &fe->fe_f2; if (ISZERO(&fe->fe_f2)) return &fe->fe_f2; CPYFPN(&a, &fe->fe_f2); if (ISINF(&fe->fe_f2)) { /* f2 <- pi/2 */ fpu_const(&fe->fe_f2, FPU_CONST_PI); fe->fe_f2.fp_exp--; fe->fe_f2.fp_sign = a.fp_sign; return &fe->fe_f2; } fpu_const(&x, FPU_CONST_1); fpu_const(&fe->fe_f2, FPU_CONST_0); CPYFPN(&v, &fe->fe_f2); fpu_cordit1(fe, &x, &a, &fe->fe_f2, &v); return &fe->fe_f2; }
/* * tan(x) = sin(x) / cos(x) */ struct fpn * fpu_tan(struct fpemu *fe) { struct fpn x; struct fpn s; struct fpn *r; if (ISNAN(&fe->fe_f2)) return &fe->fe_f2; if (ISINF(&fe->fe_f2)) return fpu_newnan(fe); /* if x is +0/-0, return +0/-0 */ if (ISZERO(&fe->fe_f2)) return &fe->fe_f2; CPYFPN(&x, &fe->fe_f2); /* sin(x) */ CPYFPN(&fe->fe_f2, &x); r = fpu_sin(fe); CPYFPN(&s, r); /* cos(x) */ CPYFPN(&fe->fe_f2, &x); r = fpu_cos(fe); CPYFPN(&fe->fe_f2, r); CPYFPN(&fe->fe_f1, &s); r = fpu_div(fe); return r; }
/* * arccos(x) = pi/2 - arcsin(x) */ struct fpn * fpu_acos(struct fpemu *fe) { struct fpn *r; if (ISNAN(&fe->fe_f2)) return &fe->fe_f2; if (ISINF(&fe->fe_f2)) return fpu_newnan(fe); r = fpu_asin(fe); CPYFPN(&fe->fe_f2, r); /* pi/2 - asin(x) */ fpu_const(&fe->fe_f1, FPU_CONST_PI); fe->fe_f1.fp_exp--; fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; r = fpu_add(fe); return r; }
/* * x * arcsin(x) = arctan(---------------) * sqrt(1 - x^2) */ struct fpn * fpu_asin(struct fpemu *fe) { struct fpn x; struct fpn *r; if (ISNAN(&fe->fe_f2)) return &fe->fe_f2; if (ISZERO(&fe->fe_f2)) return &fe->fe_f2; if (ISINF(&fe->fe_f2)) return fpu_newnan(fe); CPYFPN(&x, &fe->fe_f2); /* x^2 */ CPYFPN(&fe->fe_f1, &fe->fe_f2); r = fpu_mul(fe); /* 1 - x^2 */ CPYFPN(&fe->fe_f2, r); fe->fe_f2.fp_sign = 1; fpu_const(&fe->fe_f1, FPU_CONST_1); r = fpu_add(fe); /* sqrt(1-x^2) */ CPYFPN(&fe->fe_f2, r); r = fpu_sqrt(fe); /* x/sqrt */ CPYFPN(&fe->fe_f2, r); CPYFPN(&fe->fe_f1, &x); r = fpu_div(fe); /* arctan */ CPYFPN(&fe->fe_f2, r); return fpu_atan(fe); }
/* * Our task is to calculate the square root of a floating point number x0. * This number x normally has the form: * * exp * x = mant * 2 (where 1 <= mant < 2 and exp is an integer) * * This can be left as it stands, or the mantissa can be doubled and the * exponent decremented: * * exp-1 * x = (2 * mant) * 2 (where 2 <= 2 * mant < 4) * * If the exponent `exp' is even, the square root of the number is best * handled using the first form, and is by definition equal to: * * exp/2 * sqrt(x) = sqrt(mant) * 2 * * If exp is odd, on the other hand, it is convenient to use the second * form, giving: * * (exp-1)/2 * sqrt(x) = sqrt(2 * mant) * 2 * * In the first case, we have * * 1 <= mant < 2 * * and therefore * * sqrt(1) <= sqrt(mant) < sqrt(2) * * while in the second case we have * * 2 <= 2*mant < 4 * * and therefore * * sqrt(2) <= sqrt(2*mant) < sqrt(4) * * so that in any case, we are sure that * * sqrt(1) <= sqrt(n * mant) < sqrt(4), n = 1 or 2 * * or * * 1 <= sqrt(n * mant) < 2, n = 1 or 2. * * This root is therefore a properly formed mantissa for a floating * point number. The exponent of sqrt(x) is either exp/2 or (exp-1)/2 * as above. This leaves us with the problem of finding the square root * of a fixed-point number in the range [1..4). * * Though it may not be instantly obvious, the following square root * algorithm works for any integer x of an even number of bits, provided * that no overflows occur: * * let q = 0 * for k = NBITS-1 to 0 step -1 do -- for each digit in the answer... * x *= 2 -- multiply by radix, for next digit * if x >= 2q + 2^k then -- if adding 2^k does not * x -= 2q + 2^k -- exceed the correct root, * q += 2^k -- add 2^k and adjust x * fi * done * sqrt = q / 2^(NBITS/2) -- (and any remainder is in x) * * If NBITS is odd (so that k is initially even), we can just add another * zero bit at the top of x. Doing so means that q is not going to acquire * a 1 bit in the first trip around the loop (since x0 < 2^NBITS). If the * final value in x is not needed, or can be off by a factor of 2, this is * equivalant to moving the `x *= 2' step to the bottom of the loop: * * for k = NBITS-1 to 0 step -1 do if ... fi; x *= 2; done * * and the result q will then be sqrt(x0) * 2^floor(NBITS / 2). * (Since the algorithm is destructive on x, we will call x's initial * value, for which q is some power of two times its square root, x0.) * * If we insert a loop invariant y = 2q, we can then rewrite this using * C notation as: * * q = y = 0; x = x0; * for (k = NBITS; --k >= 0;) { * #if (NBITS is even) * x *= 2; * #endif * t = y + (1 << k); * if (x >= t) { * x -= t; * q += 1 << k; * y += 1 << (k + 1); * } * #if (NBITS is odd) * x *= 2; * #endif * } * * If x0 is fixed point, rather than an integer, we can simply alter the * scale factor between q and sqrt(x0). As it happens, we can easily arrange * for the scale factor to be 2**0 or 1, so that sqrt(x0) == q. * * In our case, however, x0 (and therefore x, y, q, and t) are multiword * integers, which adds some complication. But note that q is built one * bit at a time, from the top down, and is not used itself in the loop * (we use 2q as held in y instead). This means we can build our answer * in an integer, one word at a time, which saves a bit of work. Also, * since 1 << k is always a `new' bit in q, 1 << k and 1 << (k+1) are * `new' bits in y and we can set them with an `or' operation rather than * a full-blown multiword add. * * We are almost done, except for one snag. We must prove that none of our * intermediate calculations can overflow. We know that x0 is in [1..4) * and therefore the square root in q will be in [1..2), but what about x, * y, and t? * * We know that y = 2q at the beginning of each loop. (The relation only * fails temporarily while y and q are being updated.) Since q < 2, y < 4. * The sum in t can, in our case, be as much as y+(1<<1) = y+2 < 6, and. * Furthermore, we can prove with a bit of work that x never exceeds y by * more than 2, so that even after doubling, 0 <= x < 8. (This is left as * an exercise to the reader, mostly because I have become tired of working * on this comment.) * * If our floating point mantissas (which are of the form 1.frac) occupy * B+1 bits, our largest intermediary needs at most B+3 bits, or two extra. * In fact, we want even one more bit (for a carry, to avoid compares), or * three extra. There is a comment in fpu_emu.h reminding maintainers of * this, so we have some justification in assuming it. */ struct fpn * fpu_sqrt(struct fpemu *fe) { struct fpn *x = &fe->fe_f1; u_int bit, q, tt; u_int x0, x1, x2, x3; u_int y0, y1, y2, y3; u_int d0, d1, d2, d3; int e; FPU_DECL_CARRY; /* * Take care of special cases first. In order: * * sqrt(NaN) = NaN * sqrt(+0) = +0 * sqrt(-0) = -0 * sqrt(x < 0) = NaN (including sqrt(-Inf)) * sqrt(+Inf) = +Inf * * Then all that remains are numbers with mantissas in [1..2). */ DPRINTF(FPE_REG, ("fpu_sqer:\n")); DUMPFPN(FPE_REG, x); DPRINTF(FPE_REG, ("=>\n")); if (ISNAN(x)) { fe->fe_cx |= FPSCR_VXSNAN; DUMPFPN(FPE_REG, x); return (x); } if (ISZERO(x)) { fe->fe_cx |= FPSCR_ZX; x->fp_class = FPC_INF; DUMPFPN(FPE_REG, x); return (x); } if (x->fp_sign) { return (fpu_newnan(fe)); } if (ISINF(x)) { fe->fe_cx |= FPSCR_VXSQRT; DUMPFPN(FPE_REG, 0); return (0); } /* * Calculate result exponent. As noted above, this may involve * doubling the mantissa. We will also need to double x each * time around the loop, so we define a macro for this here, and * we break out the multiword mantissa. */ #ifdef FPU_SHL1_BY_ADD #define DOUBLE_X { \ FPU_ADDS(x3, x3, x3); FPU_ADDCS(x2, x2, x2); \ FPU_ADDCS(x1, x1, x1); FPU_ADDC(x0, x0, x0); \ } #else #define DOUBLE_X { \ x0 = (x0 << 1) | (x1 >> 31); x1 = (x1 << 1) | (x2 >> 31); \ x2 = (x2 << 1) | (x3 >> 31); x3 <<= 1; \ } #endif #if (FP_NMANT & 1) != 0 # define ODD_DOUBLE DOUBLE_X # define EVEN_DOUBLE /* nothing */ #else # define ODD_DOUBLE /* nothing */ # define EVEN_DOUBLE DOUBLE_X #endif x0 = x->fp_mant[0]; x1 = x->fp_mant[1]; x2 = x->fp_mant[2]; x3 = x->fp_mant[3]; e = x->fp_exp; if (e & 1) /* exponent is odd; use sqrt(2mant) */ DOUBLE_X; /* THE FOLLOWING ASSUMES THAT RIGHT SHIFT DOES SIGN EXTENSION */ x->fp_exp = e >> 1; /* calculates (e&1 ? (e-1)/2 : e/2 */ /* * Now calculate the mantissa root. Since x is now in [1..4), * we know that the first trip around the loop will definitely * set the top bit in q, so we can do that manually and start * the loop at the next bit down instead. We must be sure to * double x correctly while doing the `known q=1.0'. * * We do this one mantissa-word at a time, as noted above, to * save work. To avoid `(1U << 31) << 1', we also do the top bit * outside of each per-word loop. * * The calculation `t = y + bit' breaks down into `t0 = y0, ..., * t3 = y3, t? |= bit' for the appropriate word. Since the bit * is always a `new' one, this means that three of the `t?'s are * just the corresponding `y?'; we use `#define's here for this. * The variable `tt' holds the actual `t?' variable. */ /* calculate q0 */ #define t0 tt bit = FP_1; EVEN_DOUBLE; /* if (x >= (t0 = y0 | bit)) { */ /* always true */ q = bit; x0 -= bit; y0 = bit << 1; /* } */ ODD_DOUBLE; while ((bit >>= 1) != 0) { /* for remaining bits in q0 */ EVEN_DOUBLE; t0 = y0 | bit; /* t = y + bit */ if (x0 >= t0) { /* if x >= t then */ x0 -= t0; /* x -= t */ q |= bit; /* q += bit */ y0 |= bit << 1; /* y += bit << 1 */ } ODD_DOUBLE; } x->fp_mant[0] = q; #undef t0 /* calculate q1. note (y0&1)==0. */ #define t0 y0 #define t1 tt q = 0; y1 = 0; bit = 1 << 31; EVEN_DOUBLE; t1 = bit; FPU_SUBS(d1, x1, t1); FPU_SUBC(d0, x0, t0); /* d = x - t */ if ((int)d0 >= 0) { /* if d >= 0 (i.e., x >= t) then */ x0 = d0, x1 = d1; /* x -= t */ q = bit; /* q += bit */ y0 |= 1; /* y += bit << 1 */ } ODD_DOUBLE; while ((bit >>= 1) != 0) { /* for remaining bits in q1 */ EVEN_DOUBLE; /* as before */ t1 = y1 | bit; FPU_SUBS(d1, x1, t1); FPU_SUBC(d0, x0, t0); if ((int)d0 >= 0) { x0 = d0, x1 = d1; q |= bit; y1 |= bit << 1; } ODD_DOUBLE; } x->fp_mant[1] = q; #undef t1 /* calculate q2. note (y1&1)==0; y0 (aka t0) is fixed. */ #define t1 y1 #define t2 tt q = 0; y2 = 0; bit = 1 << 31; EVEN_DOUBLE; t2 = bit; FPU_SUBS(d2, x2, t2); FPU_SUBCS(d1, x1, t1); FPU_SUBC(d0, x0, t0); if ((int)d0 >= 0) { x0 = d0, x1 = d1, x2 = d2; q |= bit; y1 |= 1; /* now t1, y1 are set in concrete */ } ODD_DOUBLE; while ((bit >>= 1) != 0) { EVEN_DOUBLE; t2 = y2 | bit; FPU_SUBS(d2, x2, t2); FPU_SUBCS(d1, x1, t1); FPU_SUBC(d0, x0, t0); if ((int)d0 >= 0) { x0 = d0, x1 = d1, x2 = d2; q |= bit; y2 |= bit << 1; } ODD_DOUBLE; } x->fp_mant[2] = q; #undef t2 /* calculate q3. y0, t0, y1, t1 all fixed; y2, t2, almost done. */ #define t2 y2 #define t3 tt q = 0; y3 = 0; bit = 1 << 31; EVEN_DOUBLE; t3 = bit; FPU_SUBS(d3, x3, t3); FPU_SUBCS(d2, x2, t2); FPU_SUBCS(d1, x1, t1); FPU_SUBC(d0, x0, t0); ODD_DOUBLE; if ((int)d0 >= 0) { x0 = d0, x1 = d1, x2 = d2; q |= bit; y2 |= 1; } while ((bit >>= 1) != 0) { EVEN_DOUBLE; t3 = y3 | bit; FPU_SUBS(d3, x3, t3); FPU_SUBCS(d2, x2, t2); FPU_SUBCS(d1, x1, t1); FPU_SUBC(d0, x0, t0); if ((int)d0 >= 0) { x0 = d0, x1 = d1, x2 = d2; q |= bit; y3 |= bit << 1; } ODD_DOUBLE; } x->fp_mant[3] = q; /* * The result, which includes guard and round bits, is exact iff * x is now zero; any nonzero bits in x represent sticky bits. */ x->fp_sticky = x0 | x1 | x2 | x3; DUMPFPN(FPE_REG, x); return (x); }
struct fpn * fpu_div(struct fpemu *fe) { struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2; u_int q, bit; u_int r0, r1, r2, r3, d0, d1, d2, d3, y0, y1, y2, y3; FPU_DECL_CARRY /* * Since divide is not commutative, we cannot just use ORDER. * Check either operand for NaN first; if there is at least one, * order the signalling one (if only one) onto the right, then * return it. Otherwise we have the following cases: * * Inf / Inf = NaN, plus NV exception * Inf / num = Inf [i.e., return x] * Inf / 0 = Inf [i.e., return x] * 0 / Inf = 0 [i.e., return x] * 0 / num = 0 [i.e., return x] * 0 / 0 = NaN, plus NV exception * num / Inf = 0 * num / num = num (do the divide) * num / 0 = Inf, plus DZ exception */ DPRINTF(FPE_REG, ("fpu_div:\n")); DUMPFPN(FPE_REG, x); DUMPFPN(FPE_REG, y); DPRINTF(FPE_REG, ("=>\n")); if (ISNAN(x) || ISNAN(y)) { ORDER(x, y); fe->fe_cx |= FPSCR_VXSNAN; DUMPFPN(FPE_REG, y); return (y); } /* * Need to split the following out cause they generate different * exceptions. */ if (ISINF(x)) { if (x->fp_class == y->fp_class) { fe->fe_cx |= FPSCR_VXIDI; return (fpu_newnan(fe)); } DUMPFPN(FPE_REG, x); return (x); } if (ISZERO(x)) { fe->fe_cx |= FPSCR_ZX; if (x->fp_class == y->fp_class) { fe->fe_cx |= FPSCR_VXZDZ; return (fpu_newnan(fe)); } DUMPFPN(FPE_REG, x); return (x); } /* all results at this point use XOR of operand signs */ x->fp_sign ^= y->fp_sign; if (ISINF(y)) { x->fp_class = FPC_ZERO; DUMPFPN(FPE_REG, x); return (x); } if (ISZERO(y)) { fe->fe_cx = FPSCR_ZX; x->fp_class = FPC_INF; DUMPFPN(FPE_REG, x); return (x); } /* * Macros for the divide. See comments at top for algorithm. * Note that we expand R, D, and Y here. */ #define SUBTRACT /* D = R - Y */ \ FPU_SUBS(d3, r3, y3); FPU_SUBCS(d2, r2, y2); \ FPU_SUBCS(d1, r1, y1); FPU_SUBC(d0, r0, y0) #define NONNEGATIVE /* D >= 0 */ \ ((int)d0 >= 0) #ifdef FPU_SHL1_BY_ADD #define SHL1 /* R <<= 1 */ \ FPU_ADDS(r3, r3, r3); FPU_ADDCS(r2, r2, r2); \ FPU_ADDCS(r1, r1, r1); FPU_ADDC(r0, r0, r0) #else #define SHL1 \ r0 = (r0 << 1) | (r1 >> 31), r1 = (r1 << 1) | (r2 >> 31), \ r2 = (r2 << 1) | (r3 >> 31), r3 <<= 1 #endif #define LOOP /* do ... while (bit >>= 1) */ \ do { \ SHL1; \ SUBTRACT; \ if (NONNEGATIVE) { \ q |= bit; \ r0 = d0, r1 = d1, r2 = d2, r3 = d3; \ } \ } while ((bit >>= 1) != 0) #define WORD(r, i) /* calculate r->fp_mant[i] */ \ q = 0; \ bit = 1 << 31; \ LOOP; \ (x)->fp_mant[i] = q /* Setup. Note that we put our result in x. */ r0 = x->fp_mant[0]; r1 = x->fp_mant[1]; r2 = x->fp_mant[2]; r3 = x->fp_mant[3]; y0 = y->fp_mant[0]; y1 = y->fp_mant[1]; y2 = y->fp_mant[2]; y3 = y->fp_mant[3]; bit = FP_1; SUBTRACT; if (NONNEGATIVE) { x->fp_exp -= y->fp_exp; r0 = d0, r1 = d1, r2 = d2, r3 = d3; q = bit; bit >>= 1; } else {
/* * The multiplication algorithm for normal numbers is as follows: * * The fraction of the product is built in the usual stepwise fashion. * Each step consists of shifting the accumulator right one bit * (maintaining any guard bits) and, if the next bit in y is set, * adding the multiplicand (x) to the accumulator. Then, in any case, * we advance one bit leftward in y. Algorithmically: * * A = 0; * for (bit = 0; bit < FP_NMANT; bit++) { * sticky |= A & 1, A >>= 1; * if (Y & (1 << bit)) * A += X; * } * * (X and Y here represent the mantissas of x and y respectively.) * The resultant accumulator (A) is the product's mantissa. It may * be as large as 11.11111... in binary and hence may need to be * shifted right, but at most one bit. * * Since we do not have efficient multiword arithmetic, we code the * accumulator as four separate words, just like any other mantissa. * We use local variables in the hope that this is faster than memory. * We keep x->fp_mant in locals for the same reason. * * In the algorithm above, the bits in y are inspected one at a time. * We will pick them up 32 at a time and then deal with those 32, one * at a time. Note, however, that we know several things about y: * * - the guard and round bits at the bottom are sure to be zero; * * - often many low bits are zero (y is often from a single or double * precision source); * * - bit FP_NMANT-1 is set, and FP_1*2 fits in a word. * * We can also test for 32-zero-bits swiftly. In this case, the center * part of the loop---setting sticky, shifting A, and not adding---will * run 32 times without adding X to A. We can do a 32-bit shift faster * by simply moving words. Since zeros are common, we optimize this case. * Furthermore, since A is initially zero, we can omit the shift as well * until we reach a nonzero word. */ struct fpn * fpu_mul(struct fpemu *fe) { struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2; u_int a3, a2, a1, a0, x3, x2, x1, x0, bit, m; int sticky; FPU_DECL_CARRY; /* * Put the `heavier' operand on the right (see fpu_emu.h). * Then we will have one of the following cases, taken in the * following order: * * - y = NaN. Implied: if only one is a signalling NaN, y is. * The result is y. * - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN * case was taken care of earlier). * If x = 0, the result is NaN. Otherwise the result * is y, with its sign reversed if x is negative. * - x = 0. Implied: y is 0 or number. * The result is 0 (with XORed sign as usual). * - other. Implied: both x and y are numbers. * The result is x * y (XOR sign, multiply bits, add exponents). */ DPRINTF(FPE_REG, ("fpu_mul:\n")); DUMPFPN(FPE_REG, x); DUMPFPN(FPE_REG, y); DPRINTF(FPE_REG, ("=>\n")); ORDER(x, y); if (ISNAN(y)) { y->fp_sign ^= x->fp_sign; fe->fe_cx |= FPSCR_VXSNAN; DUMPFPN(FPE_REG, y); return (y); } if (ISINF(y)) { if (ISZERO(x)) { fe->fe_cx |= FPSCR_VXIMZ; return (fpu_newnan(fe)); } y->fp_sign ^= x->fp_sign; DUMPFPN(FPE_REG, y); return (y); } if (ISZERO(x)) { x->fp_sign ^= y->fp_sign; DUMPFPN(FPE_REG, x); return (x); } /* * Setup. In the code below, the mask `m' will hold the current * mantissa byte from y. The variable `bit' denotes the bit * within m. We also define some macros to deal with everything. */ x3 = x->fp_mant[3]; x2 = x->fp_mant[2]; x1 = x->fp_mant[1]; x0 = x->fp_mant[0]; sticky = a3 = a2 = a1 = a0 = 0; #define ADD /* A += X */ \ FPU_ADDS(a3, a3, x3); \ FPU_ADDCS(a2, a2, x2); \ FPU_ADDCS(a1, a1, x1); \ FPU_ADDC(a0, a0, x0) #define SHR1 /* A >>= 1, with sticky */ \ sticky |= a3 & 1, a3 = (a3 >> 1) | (a2 << 31), \ a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1 #define SHR32 /* A >>= 32, with sticky */ \ sticky |= a3, a3 = a2, a2 = a1, a1 = a0, a0 = 0 #define STEP /* each 1-bit step of the multiplication */ \ SHR1; if (bit & m) { ADD; }; bit <<= 1 /* * We are ready to begin. The multiply loop runs once for each * of the four 32-bit words. Some words, however, are special. * As noted above, the low order bits of Y are often zero. Even * if not, the first loop can certainly skip the guard bits. * The last word of y has its highest 1-bit in position FP_NMANT-1, * so we stop the loop when we move past that bit. */ if ((m = y->fp_mant[3]) == 0) { /* SHR32; */ /* unneeded since A==0 */ } else { bit = 1 << FP_NG; do { STEP; } while (bit != 0); } if ((m = y->fp_mant[2]) == 0) { SHR32; } else { bit = 1; do { STEP; } while (bit != 0); } if ((m = y->fp_mant[1]) == 0) { SHR32; } else { bit = 1; do { STEP; } while (bit != 0); } m = y->fp_mant[0]; /* definitely != 0 */ bit = 1; do { STEP; } while (bit <= m); /* * Done with mantissa calculation. Get exponent and handle * 11.111...1 case, then put result in place. We reuse x since * it already has the right class (FP_NUM). */ m = x->fp_exp + y->fp_exp; if (a0 >= FP_2) { SHR1; m++; } x->fp_sign ^= y->fp_sign; x->fp_exp = m; x->fp_sticky = sticky; x->fp_mant[3] = a3; x->fp_mant[2] = a2; x->fp_mant[1] = a1; x->fp_mant[0] = a0; DUMPFPN(FPE_REG, x); return (x); }
int GDens2Update(GDens *ptr) { /* update ptr */ double lpmax, lpsum, psum; int i, n = ptr->n; /* compute various constants */ for(i=0;i<n;i++) { double s, x0 = ptr->elm[i].xl, x1 = ptr->elm[i].xm, x2 = ptr->elm[i].xr, f0 = ptr->elm[i].lfl, f1 = ptr->elm[i].lfm, f2 = ptr->elm[i].lfr; ptr->elm[i].lfmax = f0; /* scale and shift */ f1 -= f0; f2 -= f0; f0 = 0.0; x1 -= x0; x2 -= x0; x0 = 0.0; s = 1./((-SQR(x2) + x2*x1)*x1); ptr->elm[i].b = -s*(-f2*SQR(x1) +f1*SQR(x2)); ptr->elm[i].c = s*(-f2*x1 +f1*x2); } /* compute the integral over each cell, unnormalized */ for(i=0;i<n;i++) { if (ISZERO(ptr->elm[i].c)) { if (ISZERO(ptr->elm[i].b)) ptr->elm[i].lnormc = log(ptr->elm[i].xr-ptr->elm[i].xl); else { double tmp = (ptr->elm[i].xr-ptr->elm[i].xl)*ptr->elm[i].b; if (fabs(tmp) > FLT_EPSILON) { /* all ok */ ptr->elm[i].lnormc = log(fabs(exp((ptr->elm[i].xr-ptr->elm[i].xl)*ptr->elm[i].b) -1.0)) - log(fabs(ptr->elm[i].b)); } else { /* this is the expansion for small 'tmp' */ ptr->elm[i].lnormc = log(fabs(tmp)) - log(fabs(ptr->elm[i].b)); } } } else { /* this can (and does) go wrong as the 'erf' and 'erfi' function may fail for high values of the arguments. perhaps we need to intergrate directly int(exp(x^2),x=low...high) ? */ double aa = 0.5*ptr->elm[i].b/sqrt(fabs(ptr->elm[i].c)); if (ptr->elm[i].c <= 0.0) ptr->elm[i].lnormc = -0.25*SQR(ptr->elm[i].b)/ptr->elm[i].c + log(1./(TWODIVSQRTPI*sqrt(-ptr->elm[i].c))) + lerf_diff(sqrt(-ptr->elm[i].c)*(ptr->elm[i].xr-ptr->elm[i].xl) -aa, -aa); else ptr->elm[i].lnormc = -0.25*SQR(ptr->elm[i].b)/ptr->elm[i].c + log(1./(TWODIVSQRTPI*sqrt(ptr->elm[i].c))) + lerfi_diff(sqrt(ptr->elm[i].c)*(ptr->elm[i].xr-ptr->elm[i].xl) +aa, aa); } if (ISINF(ptr->elm[i].lnormc)) { ptr->elm[i].lnormc = ptr->elm[i].b = ptr->elm[i].c = 0; ptr->elm[i].lp = ptr->elm[i].lfl = ptr->elm[i].lfm = ptr->elm[i].lfr = ptr->elm[i].lfmax = -FLT_MAX; } else { ptr->elm[i].lp = ptr->elm[i].lnormc + ptr->elm[i].lfmax; } } for(lpmax = ptr->elm[0].lp, i=1;i<n;i++) lpmax = MAX(lpmax, ptr->elm[i].lp); for(i=0;i<n;i++) ptr->elm[i].lp -= lpmax; for(i=0, psum=0.0;i<n;i++) psum += exp(ptr->elm[i].lp); for(lpsum = log(psum), i=0;i<n;i++) ptr->elm[i].lp -= lpsum; /* speedup the search for regions and sampling */ qsort(ptr->elm, (size_t) ptr->n, sizeof(GDensElm), GDensElmCompare); if (0) { for(i=0;i<n;i++) { printf("Gdens2 region %d\n", i); printf("\txl %f xr %f\n", ptr->elm[i].xl, ptr->elm[i].xr); printf("\tlnormc %f lp %f\n", ptr->elm[i].lnormc, ptr->elm[i].lp); } } return 0; }
/* * Perform a compare instruction (with or without unordered exception). * This updates the fcc field in the fsr. * * If either operand is NaN, the result is unordered. For cmpe, this * causes an NV exception. Everything else is ordered: * |Inf| > |numbers| > |0|. * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0), * so we get this directly. Note, however, that two zeros compare equal * regardless of sign, while everything else depends on sign. * * Incidentally, two Infs of the same sign compare equal (per the 80387 * manual---it would be nice if the SPARC documentation were more * complete). */ void __fpu_compare(struct fpemu *fe, int cmpe, int fcc) { struct fpn *a, *b; int cc; FPU_DECL_CARRY a = &fe->fe_f1; b = &fe->fe_f2; if (ISNAN(a) || ISNAN(b)) { /* * In any case, we already got an exception for signalling * NaNs; here we may replace that one with an identical * exception, but so what?. */ if (cmpe) fe->fe_cx = FSR_NV; cc = FSR_CC_UO; goto done; } /* * Must handle both-zero early to avoid sign goofs. Otherwise, * at most one is 0, and if the signs differ we are done. */ if (ISZERO(a) && ISZERO(b)) { cc = FSR_CC_EQ; goto done; } if (a->fp_sign) { /* a < 0 (or -0) */ if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */ cc = FSR_CC_LT; goto done; } } else { /* a > 0 (or +0) */ if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */ cc = FSR_CC_GT; goto done; } } /* * Now the signs are the same (but may both be negative). All * we have left are these cases: * * |a| < |b| [classes or values differ] * |a| > |b| [classes or values differ] * |a| == |b| [classes and values identical] * * We define `diff' here to expand these as: * * |a| < |b|, a,b >= 0: a < b => FSR_CC_LT * |a| < |b|, a,b < 0: a > b => FSR_CC_GT * |a| > |b|, a,b >= 0: a > b => FSR_CC_GT * |a| > |b|, a,b < 0: a < b => FSR_CC_LT */ #define opposite_cc(cc) ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT) #define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude)) if (a->fp_class < b->fp_class) { /* |a| < |b| */ cc = diff(FSR_CC_LT); goto done; } if (a->fp_class > b->fp_class) { /* |a| > |b| */ cc = diff(FSR_CC_GT); goto done; } /* now none can be 0: only Inf and numbers remain */ if (ISINF(a)) { /* |Inf| = |Inf| */ cc = FSR_CC_EQ; goto done; } /* * Only numbers remain. To compare two numbers in magnitude, we * simply subtract them. */ a = __fpu_sub(fe); if (a->fp_class == FPC_ZERO) cc = FSR_CC_EQ; else cc = diff(FSR_CC_GT); done: fe->fe_fsr = (fe->fe_fsr & fcc_nmask[fcc]) | ((u_long)cc << fcc_shift[fcc]); }
int pvsnfmt_double(pvsnfmt_vars *info, double d) { char *digits; int sign = 0; int dec; double value = d; int len; int pad = 0; //int signwidth = 0; int totallen; char signchar = 0; int leadingzeros = 0; int printdigits; /* temporary var used in different contexts */ int flags = info->flags; int width = info->width; const char fmt = *(info->fmt); int precision = info->precision; /* Check for special values first */ char *special = 0; if(ISSNAN(value)) { special = "NaN"; } else if(ISQNAN(value)) { special = "NaN"; } else if(ISINF(value)) { if(value < 0) { sign = 1; } special = "Inf"; } if(special) { totallen = len = strlen(special); /* Sign (this is silly for NaN but conforming to printf */ if(flags & (FLAG_SIGNED | FLAG_SIGN_PAD) || sign) { if(sign) { signchar = '-'; } else if(flags & FLAG_SIGN_PAD) { signchar = ' '; } else { signchar = '+'; } totallen++; } /* Padding */ if(totallen < width) { pad = width - totallen; } else { pad = 0; } totallen += pad ; // haleyjd 05/07/08: this was forgotten! if(info->nmax <= 1) { return totallen; } /* Sign now if zeropad */ if(flags & FLAG_ZERO_PAD && signchar) { if(info->nmax > 1) { *(info->pinsertion) = signchar; info->pinsertion += 1; info->nmax -= 1; } } /* Right align */ if(!(flags & FLAG_LEFT_ALIGN)) { if(info->nmax <= 1) { pad = 0; } else if((int) info->nmax - 1 < pad) { pad = info->nmax - 1; } if(flags & FLAG_ZERO_PAD) { memset(info->pinsertion, '0', pad); } else { memset(info->pinsertion, ' ', pad); } info->pinsertion += pad ; info->nmax -= pad ; } /* Sign now if not zeropad */ if(!(flags & FLAG_ZERO_PAD) && signchar) { if(info->nmax > 1) { *(info->pinsertion) = signchar; info->pinsertion += 1; info->nmax -= 1; } } if(info->nmax <= 0) { len = 0; } else if((int) info->nmax - 1 < len) { len = info->nmax - 1; } memcpy(info->pinsertion, special, len); info->pinsertion += len; info->nmax -= len; /* Left align */ if(flags & FLAG_LEFT_ALIGN) { if(info->nmax <= 1) { pad = 0; } else if((int) info->nmax - 1 < pad) { pad = info->nmax - 1; } memset(info->pinsertion, ' ', pad); info->pinsertion += pad ; info->nmax -= pad ; } return totallen; } if(fmt == 'f') { if(precision == UNKNOWN_PRECISION) { precision = 6; } digits = FCVT(value, precision, &dec, &sign); len = strlen(digits); if(dec > 0) { totallen = dec; } else { totallen = 0; } /* plus 1 for decimal place */ if(dec <= 0) { totallen += 2; /* and trailing ".0" */ } else if(precision > 0 || flags & FLAG_HASH) { totallen += 1; } /* Determine sign width (0 or 1) */ if(flags & (FLAG_SIGNED | FLAG_SIGN_PAD) || sign) { if(sign) { signchar = '-'; } else if(flags & FLAG_SIGN_PAD) { signchar = ' '; } else { signchar = '+'; } totallen++; } /* Determine if leading zeros required */ if(dec <= 0) { leadingzeros = 1 - dec; /* add one for zero before decimal point (0.) */ } if(leadingzeros - 1 > precision) { totallen += precision; } else if(len - dec > 0) { totallen += precision; } else { totallen += leadingzeros; } /* Determine padding width */ if(totallen < width) { pad = width - totallen; } totallen += pad; if(info->nmax <= 1) { return totallen; } /* Now that the length has been calculated, print as much of it * as possible into the buffer */ /* Print sign now if padding with zeros */ if(flags & FLAG_ZERO_PAD && signchar != 0) { if(info->nmax > 1) { *(info->pinsertion) = signchar; info->pinsertion += 1; info->nmax -= 1; } } /* Print width padding if right-aligned */ if(!(flags & FLAG_LEFT_ALIGN)) { if(info->nmax <= 1) { pad = 0; } else if((int) info->nmax - 1 < pad) { pad = info->nmax - 1; } if(flags & FLAG_ZERO_PAD) { memset(info->pinsertion, '0', pad); } else { memset(info->pinsertion, ' ', pad); } info->pinsertion += pad; info->nmax -= pad; } /* Print sign now if padding was spaces */ if(!(flags & FLAG_ZERO_PAD) && signchar != 0) { *(info->pinsertion) = signchar; info->pinsertion += 1; info->nmax -= 1; } /* Print leading zeros */ if(leadingzeros) { /* Print "0.", then leadingzeros - 1 */ if(info->nmax > 1) { *(info->pinsertion) = '0'; info->pinsertion += 1; info->nmax -= 1; } if(precision > 0 || flags & FLAG_HASH) { if(info->nmax > 1) { *(info->pinsertion) = '.'; info->pinsertion += 1; info->nmax -= 1; } } /* WARNING not rounding here! * i.e. printf(".3f", 0.0007) gives "0.000" not "0.001" * * This whole function could do with a rewrite... */ if(leadingzeros - 1 > precision) { leadingzeros = precision + 1; len = 0; } /* END WARNING */ precision -= leadingzeros - 1; if(info->nmax <= 1) { leadingzeros = 0; } else if((int) info->nmax /* - 1 */ < leadingzeros /* -1 */) { leadingzeros = info->nmax; /* -1 */ } leadingzeros--; memset(info->pinsertion, '0', leadingzeros); info->pinsertion += leadingzeros; info->nmax -= leadingzeros; } /* Print digits before decimal place */ if(dec > 0) { if(info->nmax <= 1) { printdigits = 0; } else if((int) info->nmax - 1 < dec) { printdigits = info->nmax - 1; } else { printdigits = dec; } memcpy(info->pinsertion, digits, printdigits); info->pinsertion += printdigits; info->nmax -= printdigits; if(precision > 0 || flags & FLAG_HASH) { /* Print decimal place */ if(info->nmax > 1) { *(info->pinsertion) = '.'; info->pinsertion += 1; info->nmax -= 1; } /* Print trailing zero if no precision but hash given */ if(precision == 0 && info->nmax > 1) { *(info->pinsertion) = '0'; info->pinsertion += 1; info->nmax -= 1; } } /* Bypass the digits we've already printed */ len -= dec; digits += dec; } /* Print digits after decimal place */ if(len > precision) { len = precision; } if(info->nmax <= 1) { printdigits = 0; } else if((int) info->nmax - 1 < len) { printdigits = info->nmax - 1; } else { printdigits = len; } memcpy(info->pinsertion, digits, printdigits); info->pinsertion += printdigits; info->nmax -= printdigits; /* Print left-aligned pad */ if(flags & FLAG_LEFT_ALIGN) { if(info->nmax <= 1) { pad = 0; } else if((int) info->nmax - 1 < pad) { pad = info->nmax - 1; } memset(info->pinsertion, ' ', pad); info->pinsertion += pad; info->nmax -= pad; } return totallen; } return 0; }
static struct fpn * __fpu_modrem(struct fpemu *fe, int is_mod) { static struct fpn X, Y; struct fpn *x, *y, *r; uint32_t signX, signY, signQ; int j, k, l, q; int cmp; if (ISNAN(&fe->fe_f1) || ISNAN(&fe->fe_f2)) return fpu_newnan(fe); if (ISINF(&fe->fe_f1) || ISZERO(&fe->fe_f2)) return fpu_newnan(fe); CPYFPN(&X, &fe->fe_f1); CPYFPN(&Y, &fe->fe_f2); x = &X; y = &Y; q = 0; r = &fe->fe_f2; /* * Step 1 */ signX = x->fp_sign; signY = y->fp_sign; signQ = (signX ^ signY); x->fp_sign = y->fp_sign = 0; /* Special treatment that just return input value but Q is necessary */ if (ISZERO(x) || ISINF(y)) { r = &fe->fe_f1; goto Step7; } /* * Step 2 */ l = x->fp_exp - y->fp_exp; k = 0; CPYFPN(r, x); if (l >= 0) { r->fp_exp -= l; j = l; /* * Step 3 */ for (;;) { cmp = abscmp3(r, y); /* Step 3.1 */ if (cmp == 0) break; /* Step 3.2 */ if (cmp > 0) { CPYFPN(&fe->fe_f1, r); CPYFPN(&fe->fe_f2, y); fe->fe_f2.fp_sign = 1; r = fpu_add(fe); q++; } /* Step 3.3 */ if (j == 0) goto Step4; /* Step 3.4 */ k++; j--; q += q; r->fp_exp++; } /* R == Y */ q++; r->fp_class = FPC_ZERO; goto Step7; } Step4: r->fp_sign = signX; /* * Step 5 */ if (is_mod) goto Step7; /* * Step 6 */ /* y = y / 2 */ y->fp_exp--; /* abscmp3 ignore sign */ cmp = abscmp3(r, y); /* revert y */ y->fp_exp++; if (cmp > 0 || (cmp == 0 && q % 2)) { q++; CPYFPN(&fe->fe_f1, r); CPYFPN(&fe->fe_f2, y); fe->fe_f2.fp_sign = !signX; r = fpu_add(fe); } /* * Step 7 */ Step7: q &= 0x7f; q |= (signQ << 7); fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = (fe->fe_fpsr & ~FPSR_QTT) | (q << 16); return r; }
void minimize_dual(DOUBLE *Xopt, DOUBLE *Xorig, INT length, DOUBLE *SSt, DOUBLE *SXt, DOUBLE *SXtXSt, DOUBLE trXXt, \ DOUBLE c, INT N, INT K) { DOUBLE INTERV = 0.1; DOUBLE EXT = 3.0; INT MAX = 20; DOUBLE RATIO = (DOUBLE) 10; DOUBLE SIG = 0.1; DOUBLE RHO = SIG / (DOUBLE) 2; INT MN = K * 1; CHAR lamch_opt = 'U'; DOUBLE realmin = LAMCH(&lamch_opt); DOUBLE red = 1; INT i = 0; INT ls_failed = 0; DOUBLE f0; DOUBLE *df0 = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE *dftemp = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE *df3 = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE *s = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE d0; INT derivFlag = 1; DOUBLE *X = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); datacpy(X, Xorig, MN); INT maxNK = IMAX(N, K); DOUBLE *SStLambda = (DOUBLE *) MALLOC(maxNK * K * sizeof(DOUBLE)); DOUBLE *tempMatrix = (DOUBLE *) MALLOC(maxNK * K * sizeof(DOUBLE)); dual_obj_grad(&f0, df0, X, SSt, SXt, SXtXSt, trXXt, c, N, K, derivFlag, SStLambda, tempMatrix); INT incx = 1; INT incy = 1; datacpy(s, df0, MN); DOUBLE alpha = -1; SCAL(&MN, &alpha, s, &incx); d0 = - DOT(&MN, s, &incx, s, &incy); DOUBLE x1; DOUBLE x2; DOUBLE x3; DOUBLE x4; DOUBLE *X0 = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE *X3 = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); DOUBLE F0; DOUBLE *dF0 = (DOUBLE *) MALLOC(MN * sizeof(DOUBLE)); INT Mmin; DOUBLE f1; DOUBLE f2; DOUBLE f3; DOUBLE f4; DOUBLE d1; DOUBLE d2; DOUBLE d3; DOUBLE d4; INT success; DOUBLE A; DOUBLE B; DOUBLE sqrtquantity; DOUBLE tempnorm; DOUBLE tempinprod1; DOUBLE tempinprod2; DOUBLE tempscalefactor; x3 = red / (1 - d0); while (i++ < length) { datacpy(X0, X, MN); datacpy(dF0, df0, MN); F0 = f0; Mmin = MAX; while (1) { x2 = 0; f2 = f0; d2 = d0; f3 = f0; datacpy(df3, df0, MN); success = 0; while ((!success) && (Mmin > 0)) { Mmin = Mmin - 1; datacpy(X3, X, MN); alpha = x3; AXPY(&MN, &alpha, s, &incx, X3, &incy); dual_obj_grad(&f3, df3, X3, SSt, SXt, SXtXSt, trXXt, c, N, K, derivFlag, SStLambda, tempMatrix); if (ISNAN(f3) || ISINF(f3)) { /* any(isnan(df3)+isinf(df3)) */ x3 = (x2 + x3) * 0.5; } else { success = 1; } } if (f3 < F0) { datacpy(X0, X, MN); alpha = x3; AXPY(&MN, &alpha, s, &incx, X0, &incy); datacpy(dF0, df3, MN); F0 = f3; } d3 = DOT(&MN, df3, &incx, s, &incy); if ((d3 > SIG * d0) || (f3 > f0 + x3 * RHO * d0) || (Mmin == 0)) { break; } x1 = x2; f1 = f2; d1 = d2; x2 = x3; f2 = f3; d2 = d3; A = 6 * (f1 - f2) + 3 * (d2 + d1) * (x2 - x1); B = 3 * (f2 - f1) - (2 * d1 + d2) * (x2 - x1); sqrtquantity = B * B - A * d1 * (x2 - x1); if (sqrtquantity < 0) { x3 = x2 * EXT; } else { x3 = x1 - d1 * SQR(x2 - x1) / (B + SQRT(sqrtquantity)); if (ISNAN(x3) || ISINF(x3) || (x3 < 0)) { x3 = x2 * EXT; } else if (x3 > x2 * EXT) { x3 = x2 * EXT; } else if (x3 < x2 + INTERV * (x2 - x1)) { x3 = x2 + INTERV * (x2 - x1); } } } while (((ABS(d3) > - SIG * d0) || (f3 > f0 + x3 * RHO * d0)) && (Mmin > 0)) { if ((d3 > 0) || (f3 > f0 + x3 * RHO * d0)) { x4 = x3; f4 = f3; d4 = d3; } else { x2 = x3; f2 = f3; d2 = d3; } if (f4 > f0) { x3 = x2 - (0.5 * d2 * SQR(x4 - x2)) / (f4 - f2 - d2 * (x4 - x2)); } else { A = 6 * (f2 - f4) / (x4 - x2) + 3 * (d4 + d2); B = 3 * (f4 - f2) - (2 * d2 + d4) * (x4 - x2); x3 = x2 + (SQRT(B * B - A * d2 * SQR(x4 - x2)) - B) / A; } if (ISNAN(x3) || ISINF(x3)) { x3 = (x2 + x4) * 0.5; } x3 = IMAX(IMIN(x3, x4 - INTERV * (x4 - x2)), x2 + INTERV * (x4 - x2)); datacpy(X3, X, MN); alpha = x3; AXPY(&MN, &alpha, s, &incx, X3, &incy); dual_obj_grad(&f3, df3, X3, SSt, SXt, SXtXSt, trXXt, c, N, K, derivFlag, SStLambda, tempMatrix); if (f3 < F0) { datacpy(X0, X, MN); alpha = x3; AXPY(&MN, &alpha, s, &incx, X0, &incy); datacpy(dF0, df3, MN); F0 = f3; } Mmin = Mmin - 1; d3 = DOT(&MN, df3, &incx, s, &incy); } if ((ABS(d3) < - SIG * d0) && (f3 < f0 + x3 * RHO * d0)) { alpha = x3; AXPY(&MN, &alpha, s, &incx, X, &incy); f0 = f3; datacpy(dftemp, df3, MN); alpha = -1; AXPY(&MN, &alpha, df0, &incx, dftemp, &incy); tempinprod1 = DOT(&MN, dftemp, &incx, df3, &incy); tempnorm = NRM2(&MN, df0, &incx); tempinprod2 = SQR(tempnorm); tempscalefactor = tempinprod1 / tempinprod2; alpha = tempscalefactor; SCAL(&MN, &alpha, s, &incx); alpha = -1; AXPY(&MN, &alpha, df3, &incx, s, &incy); datacpy(df0, df3, MN); d3 = d0; d0 = DOT(&MN, df0, &incx, s, &incy); if (d0 > 0) { datacpy(s, df0, MN); alpha = -1; SCAL(&MN, &alpha, s, &incx); tempnorm = NRM2(&MN, s, &incx); d0 = - SQR(tempnorm); } x3 = x3 * IMIN(RATIO, d3 / (d0 - realmin)); ls_failed = 0; } else { datacpy(X, X0, MN); datacpy(df0, dF0, MN); f0 = F0; if ((ls_failed == 1) || (i > length)) { break; } datacpy(s, df0, MN); alpha = -1; SCAL(&MN, &alpha, s, &incx); tempnorm = NRM2(&MN, s, &incx); d0 = - SQR(tempnorm); x3 = 1 / (1 - d0); ls_failed = 1; } } datacpy(Xopt, X, MN); FREE(SStLambda); FREE(tempMatrix); FREE(df0); FREE(dftemp); FREE(df3); FREE(s); FREE(X); FREE(X0); FREE(X3); FREE(dF0); }
/* * sin(x): * * if (x < 0) { * x = abs(x); * sign = 1; * } * if (x > 2*pi) { * x %= 2*pi; * } * if (x > pi) { * x -= pi; * sign inverse; * } * if (x > pi/2) { * y = cos(x - pi/2); * } else { * y = sin(x); * } * if (sign) { * y = -y; * } */ struct fpn * fpu_sin(struct fpemu *fe) { struct fpn x; struct fpn p; struct fpn *r; int sign; if (ISNAN(&fe->fe_f2)) return &fe->fe_f2; if (ISINF(&fe->fe_f2)) return fpu_newnan(fe); /* if x is +0/-0, return +0/-0 */ if (ISZERO(&fe->fe_f2)) return &fe->fe_f2; CPYFPN(&x, &fe->fe_f2); /* x = abs(input) */ sign = x.fp_sign; x.fp_sign = 0; /* p <- 2*pi */ fpu_const(&p, FPU_CONST_PI); p.fp_exp++; /* * if (x > 2*pi*N) * sin(x) is sin(x - 2*pi*N) */ CPYFPN(&fe->fe_f1, &x); CPYFPN(&fe->fe_f2, &p); r = fpu_cmp(fe); if (r->fp_sign == 0) { CPYFPN(&fe->fe_f1, &x); CPYFPN(&fe->fe_f2, &p); r = fpu_mod(fe); CPYFPN(&x, r); } /* p <- pi */ p.fp_exp--; /* * if (x > pi) * sin(x) is -sin(x - pi) */ CPYFPN(&fe->fe_f1, &x); CPYFPN(&fe->fe_f2, &p); fe->fe_f2.fp_sign = 1; r = fpu_add(fe); if (r->fp_sign == 0) { CPYFPN(&x, r); sign ^= 1; } /* p <- pi/2 */ p.fp_exp--; /* * if (x > pi/2) * sin(x) is cos(x - pi/2) * else * sin(x) */ CPYFPN(&fe->fe_f1, &x); CPYFPN(&fe->fe_f2, &p); fe->fe_f2.fp_sign = 1; r = fpu_add(fe); if (r->fp_sign == 0) { __fpu_sincos_cordic(fe, r); r = &fe->fe_f2; } else { __fpu_sincos_cordic(fe, &x); r = &fe->fe_f1; } r->fp_sign = sign; return r; }
int APPEND (FUNC_PREFIX, ecvt_r) (FLOAT_TYPE value, int ndigit, int *decpt, int *sign, char *buf, size_t len) { int exponent = 0; if (!ISNAN (value) && !ISINF (value) && value != 0.0) { FLOAT_TYPE (*log10_function) (FLOAT_TYPE) = &LOG10; if (log10_function) { /* Use the reasonable code if -lm is included. */ FLOAT_TYPE dexponent; dexponent = FLOOR (LOG10 (FABS (value))); value *= EXP (dexponent * -M_LN10); exponent = (int) dexponent; } else { /* Slow code that doesn't require -lm functions. */ FLOAT_TYPE d; if (value < 0.0) d = -value; else d = value; if (d < 1.0) { do { d *= 10.0; --exponent; } while (d < 1.0); } else if (d >= 10.0) { do { d *= 0.1; ++exponent; } while (d >= 10.0); } if (value < 0.0) value = -d; else value = d; } } else if (value == 0.0) /* SUSv2 leaves it unspecified whether *DECPT is 0 or 1 for 0.0. * This could be changed to -1 if we want to return 0. */ exponent = 0; if (ndigit <= 0 && len > 0) { buf[0] = '\0'; *decpt = 1; if (!ISINF (value) && !ISNAN (value)) *sign = value < 0.0; else *sign = 0; } else if (APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit - 1, decpt, sign, buf, len)) return -1; *decpt += exponent; return 0; }
struct fpn * fpu_add(struct fpemu *fe) { struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2, *r; u_int r0, r1, r2, r3; int rd; /* * Put the `heavier' operand on the right (see fpu_emu.h). * Then we will have one of the following cases, taken in the * following order: * * - y = NaN. Implied: if only one is a signalling NaN, y is. * The result is y. * - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN * case was taken care of earlier). * If x = -y, the result is NaN. Otherwise the result * is y (an Inf of whichever sign). * - y is 0. Implied: x = 0. * If x and y differ in sign (one positive, one negative), * the result is +0 except when rounding to -Inf. If same: * +0 + +0 = +0; -0 + -0 = -0. * - x is 0. Implied: y != 0. * Result is y. * - other. Implied: both x and y are numbers. * Do addition a la Hennessey & Patterson. */ DPRINTF(FPE_REG, ("fpu_add:\n")); DUMPFPN(FPE_REG, x); DUMPFPN(FPE_REG, y); DPRINTF(FPE_REG, ("=>\n")); ORDER(x, y); if (ISNAN(y)) { fe->fe_cx |= FPSCR_VXSNAN; DUMPFPN(FPE_REG, y); return (y); } if (ISINF(y)) { if (ISINF(x) && x->fp_sign != y->fp_sign) { fe->fe_cx |= FPSCR_VXISI; return (fpu_newnan(fe)); } DUMPFPN(FPE_REG, y); return (y); } rd = ((fe->fe_fpscr) & FPSCR_RN); if (ISZERO(y)) { if (rd != FSR_RD_RM) /* only -0 + -0 gives -0 */ y->fp_sign &= x->fp_sign; else /* any -0 operand gives -0 */ y->fp_sign |= x->fp_sign; DUMPFPN(FPE_REG, y); return (y); } if (ISZERO(x)) { DUMPFPN(FPE_REG, y); return (y); } /* * We really have two numbers to add, although their signs may * differ. Make the exponents match, by shifting the smaller * number right (e.g., 1.011 => 0.1011) and increasing its * exponent (2^3 => 2^4). Note that we do not alter the exponents * of x and y here. */ r = &fe->fe_f3; r->fp_class = FPC_NUM; if (x->fp_exp == y->fp_exp) { r->fp_exp = x->fp_exp; r->fp_sticky = 0; } else { if (x->fp_exp < y->fp_exp) { /* * Try to avoid subtract case iii (see below). * This also guarantees that x->fp_sticky = 0. */ SWAP(x, y); } /* now x->fp_exp > y->fp_exp */ r->fp_exp = x->fp_exp; r->fp_sticky = fpu_shr(y, x->fp_exp - y->fp_exp); } r->fp_sign = x->fp_sign; if (x->fp_sign == y->fp_sign) { FPU_DECL_CARRY /* * The signs match, so we simply add the numbers. The result * may be `supernormal' (as big as 1.111...1 + 1.111...1, or * 11.111...0). If so, a single bit shift-right will fix it * (but remember to adjust the exponent). */ /* r->fp_mant = x->fp_mant + y->fp_mant */ FPU_ADDS(r->fp_mant[3], x->fp_mant[3], y->fp_mant[3]); FPU_ADDCS(r->fp_mant[2], x->fp_mant[2], y->fp_mant[2]); FPU_ADDCS(r->fp_mant[1], x->fp_mant[1], y->fp_mant[1]); FPU_ADDC(r0, x->fp_mant[0], y->fp_mant[0]); if ((r->fp_mant[0] = r0) >= FP_2) { (void) fpu_shr(r, 1); r->fp_exp++; } } else { FPU_DECL_CARRY /* * The signs differ, so things are rather more difficult. * H&P would have us negate the negative operand and add; * this is the same as subtracting the negative operand. * This is quite a headache. Instead, we will subtract * y from x, regardless of whether y itself is the negative * operand. When this is done one of three conditions will * hold, depending on the magnitudes of x and y: * case i) |x| > |y|. The result is just x - y, * with x's sign, but it may need to be normalized. * case ii) |x| = |y|. The result is 0 (maybe -0) * so must be fixed up. * case iii) |x| < |y|. We goofed; the result should * be (y - x), with the same sign as y. * We could compare |x| and |y| here and avoid case iii, * but that would take just as much work as the subtract. * We can tell case iii has occurred by an overflow. * * N.B.: since x->fp_exp >= y->fp_exp, x->fp_sticky = 0. */ /* r->fp_mant = x->fp_mant - y->fp_mant */ FPU_SET_CARRY(y->fp_sticky); FPU_SUBCS(r3, x->fp_mant[3], y->fp_mant[3]); FPU_SUBCS(r2, x->fp_mant[2], y->fp_mant[2]); FPU_SUBCS(r1, x->fp_mant[1], y->fp_mant[1]); FPU_SUBC(r0, x->fp_mant[0], y->fp_mant[0]); if (r0 < FP_2) { /* cases i and ii */ if ((r0 | r1 | r2 | r3) == 0) { /* case ii */ r->fp_class = FPC_ZERO; r->fp_sign = rd == FSR_RD_RM; return (r); } } else { /* * Oops, case iii. This can only occur when the * exponents were equal, in which case neither * x nor y have sticky bits set. Flip the sign * (to y's sign) and negate the result to get y - x. */ #ifdef DIAGNOSTIC if (x->fp_exp != y->fp_exp || r->fp_sticky) panic("fpu_add"); #endif r->fp_sign = y->fp_sign; FPU_SUBS(r3, 0, r3); FPU_SUBCS(r2, 0, r2); FPU_SUBCS(r1, 0, r1); FPU_SUBC(r0, 0, r0); } r->fp_mant[3] = r3; r->fp_mant[2] = r2; r->fp_mant[1] = r1; r->fp_mant[0] = r0; if (r0 < FP_1) fpu_norm(r); } DUMPFPN(FPE_REG, r); return (r); }
int APPEND (FUNC_PREFIX, fcvt_r) (FLOAT_TYPE value, int ndigit, int *decpt, int *sign, char *buf, size_t len) { int n, i; int left; if (buf == NULL) { __set_errno (EINVAL); return -1; } left = 0; if (!ISINF (value) && !ISNAN (value)) { /* OK, the following is not entirely correct. -0.0 is not handled * correctly but glibc 2.0 does not have a portable function to * implement this test. */ *sign = value < 0.0; if (*sign) value = -value; if (ndigit < 0) { /* Rounding to the left of the decimal point. */ while (ndigit < 0) { FLOAT_TYPE new_value = value * 0.1; if (new_value < 1.0) { ndigit = 0; break; } value = new_value; ++left; ++ndigit; } } } else { /* Value is Inf or NaN. */ *sign = 0; } n = strx_nprint (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value); if (n < 0) return -1; i = 0; while (i < n && isdigit (buf[i])) ++i; *decpt = i; if (i == 0) /* Value is Inf or NaN. */ return 0; if (i < n) { do ++i; while (i < n && !isdigit (buf[i])); if (*decpt == 1 && buf[0] == '0' && value != 0.0) { /* We must not have leading zeroes. Strip them all out and * adjust *DECPT if necessary. */ --*decpt; while (i < n && buf[i] == '0') { --*decpt; ++i; } } memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i); buf[n - (i - MAX (*decpt, 0))] = '\0'; } if (left) { *decpt += left; if (--len > n) { while (left-- > 0 && n < len) buf[n++] = '0'; buf[n] = '\0'; } } return 0; }
/* * Perform a compare instruction (with or without unordered exception). * This updates the fcc field in the fsr. * * If either operand is NaN, the result is unordered. For ordered, this * causes an NV exception. Everything else is ordered: * |Inf| > |numbers| > |0|. * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0), * so we get this directly. Note, however, that two zeros compare equal * regardless of sign, while everything else depends on sign. * * Incidentally, two Infs of the same sign compare equal (per the 80387 * manual---it would be nice if the SPARC documentation were more * complete). */ void fpu_compare(struct fpemu *fe, int ordered) { struct fpn *a, *b, *r; int cc; a = &fe->fe_f1; b = &fe->fe_f2; r = &fe->fe_f3; if (ISNAN(a) || ISNAN(b)) { /* * In any case, we already got an exception for signalling * NaNs; here we may replace that one with an identical * exception, but so what?. */ cc = FPSCR_FU; if (ISSNAN(a) || ISSNAN(b)) cc |= FPSCR_VXSNAN; if (ordered) { if (fe->fe_fpscr & FPSCR_VE || ISQNAN(a) || ISQNAN(b)) cc |= FPSCR_VXVC; } goto done; } /* * Must handle both-zero early to avoid sign goofs. Otherwise, * at most one is 0, and if the signs differ we are done. */ if (ISZERO(a) && ISZERO(b)) { cc = FPSCR_FE; goto done; } if (a->fp_sign) { /* a < 0 (or -0) */ if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */ cc = FPSCR_FL; goto done; } } else { /* a > 0 (or +0) */ if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */ cc = FPSCR_FG; goto done; } } /* * Now the signs are the same (but may both be negative). All * we have left are these cases: * * |a| < |b| [classes or values differ] * |a| > |b| [classes or values differ] * |a| == |b| [classes and values identical] * * We define `diff' here to expand these as: * * |a| < |b|, a,b >= 0: a < b => FSR_CC_LT * |a| < |b|, a,b < 0: a > b => FSR_CC_GT * |a| > |b|, a,b >= 0: a > b => FSR_CC_GT * |a| > |b|, a,b < 0: a < b => FSR_CC_LT */ #define opposite_cc(cc) ((cc) == FPSCR_FL ? FPSCR_FG : FPSCR_FL) #define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude)) if (a->fp_class < b->fp_class) { /* |a| < |b| */ cc = diff(FPSCR_FL); goto done; } if (a->fp_class > b->fp_class) { /* |a| > |b| */ cc = diff(FPSCR_FG); goto done; } /* now none can be 0: only Inf and numbers remain */ if (ISINF(a)) { /* |Inf| = |Inf| */ cc = FPSCR_FE; goto done; } fpu_sub(fe); if (ISZERO(r)) cc = FPSCR_FE; else if (r->fp_sign) cc = FPSCR_FL; else cc = FPSCR_FG; done: fe->fe_cx = cc; }
/* * Perform a compare instruction (with or without unordered exception). * This updates the fcc field in the fsr. * * If either operand is NaN, the result is unordered. For cmpe, this * causes an NV exception. Everything else is ordered: * |Inf| > |numbers| > |0|. * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0), * so we get this directly. Note, however, that two zeros compare equal * regardless of sign, while everything else depends on sign. * * Incidentally, two Infs of the same sign compare equal (per the 80387 * manual---it would be nice if the SPARC documentation were more * complete). */ void fpu_compare(struct fpemu *fe, int cmpe) { register struct fpn *a, *b; register int cc, r3, r2, r1, r0; FPU_DECL_CARRY a = &fe->fe_f1; b = &fe->fe_f2; if (ISNAN(a) || ISNAN(b)) { /* * In any case, we already got an exception for signalling * NaNs; here we may replace that one with an identical * exception, but so what?. */ if (cmpe) fe->fe_cx = FSR_NV; cc = FSR_CC_UO; goto done; } /* * Must handle both-zero early to avoid sign goofs. Otherwise, * at most one is 0, and if the signs differ we are done. */ if (ISZERO(a) && ISZERO(b)) { cc = FSR_CC_EQ; goto done; } if (a->fp_sign) { /* a < 0 (or -0) */ if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */ cc = FSR_CC_LT; goto done; } } else { /* a > 0 (or +0) */ if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */ cc = FSR_CC_GT; goto done; } } /* * Now the signs are the same (but may both be negative). All * we have left are these cases: * * |a| < |b| [classes or values differ] * |a| > |b| [classes or values differ] * |a| == |b| [classes and values identical] * * We define `diff' here to expand these as: * * |a| < |b|, a,b >= 0: a < b => FSR_CC_LT * |a| < |b|, a,b < 0: a > b => FSR_CC_GT * |a| > |b|, a,b >= 0: a > b => FSR_CC_GT * |a| > |b|, a,b < 0: a < b => FSR_CC_LT */ #define opposite_cc(cc) ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT) #define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude)) if (a->fp_class < b->fp_class) { /* |a| < |b| */ cc = diff(FSR_CC_LT); goto done; } if (a->fp_class > b->fp_class) { /* |a| > |b| */ cc = diff(FSR_CC_GT); goto done; } /* now none can be 0: only Inf and numbers remain */ if (ISINF(a)) { /* |Inf| = |Inf| */ cc = FSR_CC_EQ; goto done; } /* * Only numbers remain. To compare two numbers in magnitude, we * simply subtract their mantissas. */ FPU_SUBS(r3, a->fp_mant[0], b->fp_mant[0]); FPU_SUBCS(r2, a->fp_mant[1], b->fp_mant[1]); FPU_SUBCS(r1, a->fp_mant[2], b->fp_mant[2]); FPU_SUBC(r0, a->fp_mant[3], b->fp_mant[3]); if (r0 < 0) /* underflow: |a| < |b| */ cc = diff(FSR_CC_LT); else if ((r0 | r1 | r2 | r3) != 0) /* |a| > |b| */ cc = diff(FSR_CC_GT); else cc = FSR_CC_EQ; /* |a| == |b| */ done: fe->fe_fsr = (fe->fe_fsr & ~FSR_FCC) | (cc << FSR_FCC_SHIFT); }
void EditableDenseThreeDimensionalModel::setColumn(size_t index, const Column &values) { QWriteLocker locker(&m_lock); while (index >= m_data.size()) { m_data.push_back(Column()); m_trunc.push_back(0); } bool allChange = false; // if (values.size() > m_yBinCount) m_yBinCount = values.size(); for (size_t i = 0; i < values.size(); ++i) { float value = values[i]; if (ISNAN(value) || ISINF(value)) { continue; } if (!m_haveExtents || value < m_minimum) { m_minimum = value; allChange = true; } if (!m_haveExtents || value > m_maximum) { m_maximum = value; allChange = true; } m_haveExtents = true; } truncateAndStore(index, values); // assert(values == expandAndRetrieve(index)); long windowStart = index; windowStart *= m_resolution; if (m_notifyOnAdd) { if (allChange) { emit modelChanged(); } else { emit modelChanged(windowStart, windowStart + m_resolution); } } else { if (allChange) { m_sinceLastNotifyMin = -1; m_sinceLastNotifyMax = -1; emit modelChanged(); } else { if (m_sinceLastNotifyMin == -1 || windowStart < m_sinceLastNotifyMin) { m_sinceLastNotifyMin = windowStart; } if (m_sinceLastNotifyMax == -1 || windowStart > m_sinceLastNotifyMax) { m_sinceLastNotifyMax = windowStart; } } } }