void HistoryInteraction::build_coefficient_table() { Interpolation::UniformLagrangeSet lagrange(interp_order); for(int pair_idx = 0; pair_idx < num_interactions; ++pair_idx) { int src, obs; std::tie(src, obs) = idx2coord(pair_idx); Vec3d dr(separation((*dots)[src], (*dots)[obs])); std::pair<int, double> delay( split_double(dr.norm() / (config.c0 * config.dt))); floor_delays[pair_idx] = delay.first; lagrange.calculate_weights(delay.second, config.dt); std::vector<Eigen::Matrix3cd> interp_dyads( dyadic->coefficients(dr, lagrange)); for(int i = 0; i <= interp_order; ++i) { coefficients[pair_idx][i] = (*dots)[obs].dipole().dot(interp_dyads[i] * (*dots)[src].dipole()); } } }
/** * Multiply a GPS time by a number. Computes gps * x and places the result * in gps. Returns gps on success, NULL on failure. */ LIGOTimeGPS *XLALGPSMultiply( LIGOTimeGPS *gps, REAL8 x ) { LIGOTimeGPS workspace = *gps; double slo, shi; double xlo, xhi; double addendlo[4], addendhi[4]; if(isnan(x) || isinf(x)) { XLALPrintError("%s(): invalid multiplicand %g", __func__, x); XLAL_ERROR_NULL(XLAL_EFPINVAL); } /* ensure the seconds and nanoseconds components have the same sign so * that the addend fragments we compute below all have the same sign */ if(workspace.gpsSeconds < 0 && workspace.gpsNanoSeconds > 0) { workspace.gpsSeconds += 1; workspace.gpsNanoSeconds -= 1000000000; } else if(workspace.gpsSeconds > 0 && workspace.gpsNanoSeconds < 0) { workspace.gpsSeconds -= 1; workspace.gpsNanoSeconds += 1000000000; } /* split seconds and multiplicand x into leading-order and low-order * components */ slo = workspace.gpsSeconds % (1<<16); shi = workspace.gpsSeconds - slo; split_double(x, &xhi, &xlo); /* the count of seconds and the multiplicand x have each been split into * two parts, a high part and a low part. from these, there are 4 terms * in their product, and each term has sufficiently low dynamic range * that it can be computed using double precision floating point * arithmetic. we compute the 4 terms, split each into an integer and * fractional part on its own, then sum the fractional parts and integer * parts separately, adding the product of the nanoseconds and x into the * fractional parts when summing them. because the storage locations for * those sums have relatively low dynamic range no care need be taken in * computing the sums. */ addendlo[0] = modf(slo * xlo, &addendhi[0]); addendlo[1] = modf(shi * xlo, &addendhi[1]); addendlo[2] = modf(slo * xhi, &addendhi[2]); addendlo[3] = modf(shi * xhi, &addendhi[3]); /* initialize result with the sum of components that contribute to the * fractional part */ if(!XLALGPSSetREAL8(gps, addendlo[0] + addendlo[1] + addendlo[2] + addendlo[3] + workspace.gpsNanoSeconds * x / XLAL_BILLION_REAL8)) XLAL_ERROR_NULL(XLAL_EFUNC); /* now add the components that contribute only to the integer seconds * part */ if(!XLALGPSSetREAL8(&workspace, addendhi[0] + addendhi[1] + addendhi[2] + addendhi[3])) XLAL_ERROR_NULL(XLAL_EFUNC); return XLALGPSAddGPS(gps, &workspace); }
rtx fr30_move_double (rtx * operands) { rtx src = operands[1]; rtx dest = operands[0]; enum rtx_code src_code = GET_CODE (src); enum rtx_code dest_code = GET_CODE (dest); enum machine_mode mode = GET_MODE (dest); rtx val; start_sequence (); if (dest_code == REG) { if (src_code == REG) { int reverse = (REGNO (dest) == REGNO (src) + 1); /* We normally copy the low-numbered register first. However, if the first register of operand 0 is the same as the second register of operand 1, we must copy in the opposite order. */ emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, reverse, TRUE, mode), operand_subword (src, reverse, TRUE, mode))); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, !reverse, TRUE, mode), operand_subword (src, !reverse, TRUE, mode))); } else if (src_code == MEM) { rtx addr = XEXP (src, 0); int dregno = REGNO (dest); rtx dest0; rtx dest1; rtx new_mem; /* If the high-address word is used in the address, we must load it last. Otherwise, load it first. */ int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0); gcc_assert (GET_CODE (addr) == REG); dest0 = operand_subword (dest, reverse, TRUE, mode); dest1 = operand_subword (dest, !reverse, TRUE, mode); if (reverse) { emit_insn (gen_rtx_SET (VOIDmode, dest1, adjust_address (src, SImode, 0))); emit_insn (gen_rtx_SET (SImode, dest0, gen_rtx_REG (SImode, REGNO (addr)))); emit_insn (gen_rtx_SET (SImode, dest0, plus_constant (dest0, UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, dest0); MEM_COPY_ATTRIBUTES (new_mem, src); emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem)); } else { emit_insn (gen_rtx_SET (VOIDmode, dest0, adjust_address (src, SImode, 0))); emit_insn (gen_rtx_SET (SImode, dest1, gen_rtx_REG (SImode, REGNO (addr)))); emit_insn (gen_rtx_SET (SImode, dest1, plus_constant (dest1, UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, dest1); MEM_COPY_ATTRIBUTES (new_mem, src); emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem)); } } else if (src_code == CONST_INT || src_code == CONST_DOUBLE) { rtx words[2]; split_double (src, &words[0], &words[1]); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 0, TRUE, mode), words[0])); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 1, TRUE, mode), words[1])); } } else if (src_code == REG && dest_code == MEM) { rtx addr = XEXP (dest, 0); rtx src0; rtx src1; gcc_assert (GET_CODE (addr) == REG); src0 = operand_subword (src, 0, TRUE, mode); src1 = operand_subword (src, 1, TRUE, mode); emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0), src0)); if (REGNO (addr) == STACK_POINTER_REGNUM || REGNO (addr) == FRAME_POINTER_REGNUM) emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, UNITS_PER_WORD), src1)); else { rtx new_mem; /* We need a scratch register to hold the value of 'address + 4'. We ought to allow gcc to find one for us, but for now, just push one of the source registers. */ emit_insn (gen_movsi_push (src0)); emit_insn (gen_movsi_internal (src0, addr)); emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, src0); MEM_COPY_ATTRIBUTES (new_mem, dest); emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1)); emit_insn (gen_movsi_pop (src0)); } } else /* This should have been prevented by the constraints on movdi_insn. */ gcc_unreachable (); val = get_insns (); end_sequence (); return val; }
void crx_print_operand (FILE * file, rtx x, int code) { switch (code) { case 'p' : if (GET_CODE (x) == REG) { if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode) { int regno = REGNO (x); if (regno + 1 >= SP_REGNUM) abort (); fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]); return; } else { if (REGNO (x) >= SP_REGNUM) abort (); fprintf (file, "%s", reg_names[REGNO (x)]); return; } } case 'd' : { const char *crx_cmp_str; switch (GET_CODE (x)) { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg) * -> swap all non symmetric ops */ case EQ : crx_cmp_str = "eq"; break; case NE : crx_cmp_str = "ne"; break; case GT : crx_cmp_str = "lt"; break; case GTU : crx_cmp_str = "lo"; break; case LT : crx_cmp_str = "gt"; break; case LTU : crx_cmp_str = "hi"; break; case GE : crx_cmp_str = "le"; break; case GEU : crx_cmp_str = "ls"; break; case LE : crx_cmp_str = "ge"; break; case LEU : crx_cmp_str = "hs"; break; default : abort (); } fprintf (file, "%s", crx_cmp_str); return; } case 'H': /* Print high part of a double precision value. */ switch (GET_CODE (x)) { case CONST_DOUBLE: if (GET_MODE (x) == SFmode) abort (); if (GET_MODE (x) == DFmode) { /* High part of a DF const. */ REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_DOUBLE (r, l); fprintf (file, "$0x%lx", l[1]); return; } /* -- Fallthrough to handle DI consts -- */ case CONST_INT: { rtx high, low; split_double (x, &low, &high); putc ('$', file); output_addr_const (file, high); return; } case REG: if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort (); fprintf (file, "%s", reg_names[REGNO (x) + 1]); return; case MEM: /* Adjust memory address to high part. */ { rtx adj_mem = x; adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4); output_memory_reference_mode = GET_MODE (adj_mem); output_address (XEXP (adj_mem, 0)); return; } default: abort (); } case 'L': /* Print low part of a double precision value. */ switch (GET_CODE (x)) { case CONST_DOUBLE: if (GET_MODE (x) == SFmode) abort (); if (GET_MODE (x) == DFmode) { /* High part of a DF const. */ REAL_VALUE_TYPE r; long l[2]; REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_DOUBLE (r, l); fprintf (file, "$0x%lx", l[0]); return; } /* -- Fallthrough to handle DI consts -- */ case CONST_INT: { rtx high, low; split_double (x, &low, &high); putc ('$', file); output_addr_const (file, low); return; } case REG: fprintf (file, "%s", reg_names[REGNO (x)]); return; case MEM: output_memory_reference_mode = GET_MODE (x); output_address (XEXP (x, 0)); return; default: abort (); } case 0 : /* default */ switch (GET_CODE (x)) { case REG: fprintf (file, "%s", reg_names[REGNO (x)]); return; case MEM: output_memory_reference_mode = GET_MODE (x); output_address (XEXP (x, 0)); return; case CONST_DOUBLE: { REAL_VALUE_TYPE r; long l; /* Always use H and L for double precision - see above */ gcc_assert (GET_MODE (x) == SFmode); REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_SINGLE (r, l); fprintf (file, "$0x%lx", l); return; } default: putc ('$', file); output_addr_const (file, x); return; } default: output_operand_lossage ("invalid %%xn code"); } abort (); }
rtx fr30_move_double (rtx * operands) { rtx src = operands[1]; rtx dest = operands[0]; enum rtx_code src_code = GET_CODE (src); enum rtx_code dest_code = GET_CODE (dest); enum machine_mode mode = GET_MODE (dest); rtx val; start_sequence (); if (dest_code == REG) { if (src_code == REG) { int reverse = (REGNO (dest) == REGNO (src) + 1); /* We normally copy the low-numbered register first. However, if the first register of operand 0 is the same as the second register of operand 1, we must copy in the opposite order. */ emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, reverse, TRUE, mode), operand_subword (src, reverse, TRUE, mode))); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, !reverse, TRUE, mode), operand_subword (src, !reverse, TRUE, mode))); } else if (src_code == MEM) { rtx addr = XEXP (src, 0); int dregno = REGNO (dest); rtx dest0 = operand_subword (dest, 0, TRUE, mode);; rtx dest1 = operand_subword (dest, 1, TRUE, mode);; rtx new_mem; gcc_assert (GET_CODE (addr) == REG); /* Copy the address before clobbering it. See PR 34174. */ emit_insn (gen_rtx_SET (SImode, dest1, addr)); emit_insn (gen_rtx_SET (VOIDmode, dest0, adjust_address (src, SImode, 0))); emit_insn (gen_rtx_SET (SImode, dest1, plus_constant (dest1, UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, dest1); MEM_COPY_ATTRIBUTES (new_mem, src); emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem)); } else if (src_code == CONST_INT || src_code == CONST_DOUBLE) { rtx words[2]; split_double (src, &words[0], &words[1]); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 0, TRUE, mode), words[0])); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 1, TRUE, mode), words[1])); } } else if (src_code == REG && dest_code == MEM) { rtx addr = XEXP (dest, 0); rtx src0; rtx src1; gcc_assert (GET_CODE (addr) == REG); src0 = operand_subword (src, 0, TRUE, mode); src1 = operand_subword (src, 1, TRUE, mode); emit_move_insn (adjust_address (dest, SImode, 0), src0); if (REGNO (addr) == STACK_POINTER_REGNUM || REGNO (addr) == FRAME_POINTER_REGNUM) emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, UNITS_PER_WORD), src1)); else { rtx new_mem; rtx scratch_reg_r0 = gen_rtx_REG (SImode, 0); /* We need a scratch register to hold the value of 'address + 4'. We use r0 for this purpose. It is used for example for long jumps and is already marked to not be used by normal register allocation. */ emit_insn (gen_movsi_internal (scratch_reg_r0, addr)); emit_insn (gen_addsi_small_int (scratch_reg_r0, scratch_reg_r0, GEN_INT (UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, scratch_reg_r0); MEM_COPY_ATTRIBUTES (new_mem, dest); emit_move_insn (new_mem, src1); emit_insn (gen_blockage ()); } } else /* This should have been prevented by the constraints on movdi_insn. */ gcc_unreachable (); val = get_insns (); end_sequence (); return val; }