Пример #1
0
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());
    }
  }
}
Пример #2
0
/**
 * 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);
}
Пример #3
0
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 ();
}
Пример #5
0
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;
}