jewel::Decimal
wx_to_decimal
(   wxString wxs,
    wxLocale const& loc,
    DecimalParsingFlags p_flags
)
{
    bool const allow_parens =
        p_flags.test(string_flags::allow_negative_parens);
    wxs = wxs.Trim().Trim(false);  // trim both right and left.
    typedef wxChar CharT;
    static CharT const open_paren = wxChar('(');
    static CharT const close_paren = wxChar(')');
    static CharT const minus_sign = wxChar('-');
    wxString const decimal_point_s = loc.GetInfo
    (   wxLOCALE_DECIMAL_POINT,
        wxLOCALE_CAT_MONEY
    );
    wxString const thousands_sep_s = loc.GetInfo
    (   wxLOCALE_THOUSANDS_SEP,
        wxLOCALE_CAT_MONEY
    );
    if (wxs.IsEmpty())
    {
        return Decimal(0, 0);
    }
    JEWEL_ASSERT (wxs.Len() >= 1);
    if ((wxs.Len() == 1) && (*(wxs.begin()) == minus_sign))
    {
        return Decimal(0, 0);
    }

    // We first convert wxs into a canonical form in which there are no
    // thousands separators, negativity is indicated only by a minus
    // sign, and the decimal point is '.'.
    if (allow_parens && (wxs[0] == open_paren) && (wxs.Last() == close_paren))
    {
        wxs[0] = minus_sign;  // Replace left parenthesis with minus sign
        wxs.RemoveLast();  // Drop right parenthesis
    }
    wxs.Replace(thousands_sep_s, wxEmptyString);

    // We need to get the std::locale (not wxLocale) related decimal point
    // character, so that we can ensure the Decimal constructor-from-string
    // sees that appropriate decimal point character.
    locale const gloc;  // global locale
    char const spot_char = use_facet<numpunct<char> >(gloc).decimal_point();
    char const spot_str[] = { spot_char, '\0' };
    wxs.Replace(decimal_point_s, wxString(spot_str));

    string const s = wx_to_std8(wxs);
    Decimal const ret(s);
    return ret;
}
示例#2
0
    void setUp()
    {
        SqlConnection conn(Engine::sql_source_from_env());
        conn.set_convert_params(true);
        setup_log(conn);
        conn.begin_trans_if_necessary();
        conn.grant_insert_id(_T("T_ORM_TEST"), true, true);
        {
            String sql_str =
                _T("INSERT INTO T_ORM_TEST(ID, A, B, C, D) VALUES(?, ?, ?, ?, ?)");
            conn.prepare(sql_str);
            Values params(5);
            params[0] = Value(ORM_TEST_ID1);
            params[1] = Value(_T("item"));
            params[2] = Value(now());
            params[3] = Value(Decimal(_T("1.2")));
            params[4] = Value(4.56);
            conn.exec(params);
        }
        conn.grant_insert_id(_T("T_ORM_TEST"), false, true);
        conn.grant_insert_id(_T("T_ORM_XML"), true, true);
        {
            String sql_str =
                _T("INSERT INTO T_ORM_XML(ID, ORM_TEST_ID, B) VALUES (?, ?, ?)");
            conn.prepare(sql_str);
            Values params(3);
            params[0] = Value(ORM_XML_ID2);
            params[1] = Value(ORM_TEST_ID1);
            params[2] = Value(Decimal(_T("3.14")));
            conn.exec(params);
            params[0] = Value(ORM_XML_ID3);
            params[1] = Value(ORM_TEST_ID1);
            params[2] = Value(Decimal(_T("2.7")));
            conn.exec(params);
        }
        {
            String sql_str =
                _T("INSERT INTO T_ORM_XML(ID, ORM_TEST_ID, B) VALUES (?, ?, ?)");
            conn.prepare(sql_str);
            Values params(3);
            params[0] = Value(ORM_XML_ID4);
            params[1] = Value();
            params[2] = Value(Decimal(_T("42")));
            conn.exec(params);
        }
        conn.grant_insert_id(_T("T_ORM_XML"), false, true);
        conn.commit();

        Yb::init_schema();
    }
void SliderThumbElement::setPositionFromPoint(const LayoutPoint& absolutePoint)
{
    RefPtr<HTMLInputElement> input = hostInput();
    if (!input || !input->renderer() || !renderBox())
        return;

    HTMLElement* trackElement = input->sliderTrackElement();
    if (!trackElement->renderBox())
        return;

    // Do all the tracking math relative to the input's renderer's box.
    RenderBox& inputRenderer = downcast<RenderBox>(*input->renderer());
    RenderBox& trackRenderer = *trackElement->renderBox();

    bool isVertical = hasVerticalAppearance(input.get());
    bool isLeftToRightDirection = renderBox()->style().isLeftToRightDirection();
    
    LayoutPoint offset(inputRenderer.absoluteToLocal(absolutePoint, UseTransforms));
    FloatRect trackBoundingBox = trackRenderer.localToContainerQuad(FloatRect(0, 0, trackRenderer.width(), trackRenderer.height()), &inputRenderer).enclosingBoundingBox();

    LayoutUnit trackLength;
    LayoutUnit position;
    if (isVertical) {
        trackLength = trackRenderer.contentHeight() - renderBox()->height();
        position = offset.y() - renderBox()->height() / 2 - trackBoundingBox.y() - renderBox()->marginBottom();
    } else {
        trackLength = trackRenderer.contentWidth() - renderBox()->width();
        position = offset.x() - renderBox()->width() / 2 - trackBoundingBox.x();
        position -= isLeftToRightDirection ? renderBox()->marginLeft() : renderBox()->marginRight();
    }

    position = std::max<LayoutUnit>(0, std::min(position, trackLength));
    const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackLength);
    const Decimal fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio;
    StepRange stepRange(input->createStepRange(RejectAny));
    Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction));

#if ENABLE(DATALIST_ELEMENT)
    const LayoutUnit snappingThreshold = renderer()->theme().sliderTickSnappingThreshold();
    if (snappingThreshold > 0) {
        Decimal closest = input->findClosestTickMarkValue(value);
        if (closest.isFinite()) {
            double closestFraction = stepRange.proportionFromValue(closest).toDouble();
            double closestRatio = isVertical || !isLeftToRightDirection ? 1.0 - closestFraction : closestFraction;
            LayoutUnit closestPosition = trackLength * closestRatio;
            if ((closestPosition - position).abs() <= snappingThreshold)
                value = closest;
        }
    }
#endif

    String valueString = serializeForNumberType(value);
    if (valueString == input->value())
        return;

    // FIXME: This is no longer being set from renderer. Consider updating the method name.
    input->setValueFromRenderer(valueString);
    if (renderer())
        renderer()->setNeedsLayout();
}
示例#4
0
	void menu::render(size_t i, bool replace) {
		auto size = current_size();
		if(i < 0 || i >= size) { return; }

		auto &item = current_at(i);

		IDType id;
		if(replace) {
			itemDtors.at(i) = engine->add(id);
		} else {
			itemDtors.emplace_back(engine->add(id));
		}

		Decimal scale =
		    glm::min(actual_height() / Decimal(size), actual_scale());
		Decimal spacing = uiTextHeight * scale;
		Point2 origin   = Point2(60, 50 + spacing * (size - i - 1));

		engine->add<component::text>(id, font, item.value);
		engine->add<component::screenposition>(id, origin);
		engine->add<component::scale>(id, Point3(scale));

		if(int(i) == current) {
			engine->add<component::color>(id, Point4(1, 1, selectionAlpha, 1));
		}

		if(item.control) {
			IDType controlID;
			auto offset = Point2(uiTextWidth / uiBase * scale, 0);
			offset.y -= 12 * scale;
			controlDtors[(int)i] = item.control->render(engine, controlID,
			                                       origin + offset, 8 * scale);
		}
	}
示例#5
0
// MAIN.
int main(int argc, char **argv)
{
	// Referencia al archivo que se leerá.
	FILE *entrada;

	// Abrir el archivo de entrada.
	entrada = fopen(argv[1], "r");

	if(entrada == NULL)
	{
		fprintf(stdout, "Error al leer archivo de entrada.\n");
		return 1;
	}
	else if(argv[2] == NULL)
	{
		fprintf(stdout, "Ingrese parámetro de salida.\n");
	}
	else
	{
		if(strcmp(argv[2], "-d") == 0)
		{
			Decimal(entrada);		// Imprimir en formato decimal.
		}
		else if(strcmp(argv[2], "-o") == 0)
		{
			Octal(entrada);			// Imprimir en formato octal.
		}
		else if(strcmp(argv[2], "-x") == 0)
		{
			Hexadecimal(entrada);	// Imprimir en formato hexadecimal.
		}
	}

	return 0;
}
void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point)
{
    RefPtrWillBeRawPtr<HTMLInputElement> input(hostInput());
    Element* trackElement = input->closedShadowRoot()->getElementById(ShadowElementNames::sliderTrack());

    if (!input->layoutObject() || !layoutBox() || !trackElement->layoutBox())
        return;

    LayoutPoint offset = roundedLayoutPoint(input->layoutObject()->absoluteToLocal(FloatPoint(point), UseTransforms));
    bool isVertical = hasVerticalAppearance(input.get());
    bool isLeftToRightDirection = layoutBox()->style()->isLeftToRightDirection();
    LayoutUnit trackSize;
    LayoutUnit position;
    LayoutUnit currentPosition;
    // We need to calculate currentPosition from absolute points becaue the
    // renderer for this node is usually on a layer and layoutBox()->x() and
    // y() are unusable.
    // FIXME: This should probably respect transforms.
    LayoutPoint absoluteThumbOrigin = layoutBox()->absoluteBoundingBoxRectIgnoringTransforms().location();
    LayoutPoint absoluteSliderContentOrigin = roundedLayoutPoint(input->layoutObject()->localToAbsolute());
    IntRect trackBoundingBox = trackElement->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms();
    IntRect inputBoundingBox = input->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms();
    if (isVertical) {
        trackSize = trackElement->layoutBox()->contentHeight() - layoutBox()->size().height();
        position = offset.y() - layoutBox()->size().height() / 2 - trackBoundingBox.y() + inputBoundingBox.y() - layoutBox()->marginBottom();
        currentPosition = absoluteThumbOrigin.y() - absoluteSliderContentOrigin.y();
    } else {
        trackSize = trackElement->layoutBox()->contentWidth() - layoutBox()->size().width();
        position = offset.x() - layoutBox()->size().width() / 2 - trackBoundingBox.x() + inputBoundingBox.x();
        position -= isLeftToRightDirection ? layoutBox()->marginLeft() : layoutBox()->marginRight();
        currentPosition = absoluteThumbOrigin.x() - absoluteSliderContentOrigin.x();
    }
    position = std::max<LayoutUnit>(0, std::min(position, trackSize));
    const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackSize);
    const Decimal fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio;
    StepRange stepRange(input->createStepRange(RejectAny));
    Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction));

    Decimal closest = input->findClosestTickMarkValue(value);
    if (closest.isFinite()) {
        double closestFraction = stepRange.proportionFromValue(closest).toDouble();
        double closestRatio = isVertical || !isLeftToRightDirection ? 1.0 - closestFraction : closestFraction;
        LayoutUnit closestPosition = trackSize * closestRatio;
        const LayoutUnit snappingThreshold = 5;
        if ((closestPosition - position).abs() <= snappingThreshold)
            value = closest;
    }

    String valueString = serializeForNumberType(value);
    if (valueString == input->value())
        return;

    // FIXME: This is no longer being set from renderer. Consider updating the method name.
    input->setValueFromRenderer(valueString);
    if (layoutObject())
        layoutObject()->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalidationReason::SliderValueChanged);
}
示例#7
0
Decimal StepRange::parseStep(AnyStepHandling anyStepHandling, const StepDescription& stepDescription, const String& stepString)
{
    if (stepString.isEmpty())
        return stepDescription.defaultValue();

    if (equalIgnoringCase(stepString, "any")) {
        switch (anyStepHandling) {
        case RejectAny:
            return Decimal::nan();
        case AnyIsDefaultStep:
            return stepDescription.defaultValue();
        default:
            ASSERT_NOT_REACHED();
        }
    }

    Decimal step = parseToDecimalForNumberType(stepString);
    if (!step.isFinite() || step <= 0)
        return stepDescription.defaultValue();

    switch (stepDescription.stepValueShouldBe) {
    case StepValueShouldBeReal:
        step *= stepDescription.stepScaleFactor;
        break;
    case ParsedStepValueShouldBeInteger:
        // For date, month, and week, the parsed value should be an integer for some types.
        step = std::max(step.round(), Decimal(1));
        step *= stepDescription.stepScaleFactor;
        break;
    case ScaledStepValueShouldBeInteger:
        // For datetime, datetime-local, time, the result should be an integer.
        step *= stepDescription.stepScaleFactor;
        step = std::max(step.round(), Decimal(1));
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    ASSERT(step > 0);
    return step;
}
示例#8
0
 void parse( const std::string& value )
 {
     if ( value == "normal" )
     {
         myDecimal = Decimal( 0 );
         myIsNormal = true;
     }
     else
     {
         /* if it contains only numeric
          characters it must be a number */
         myDecimal.parse( value );
         myIsNormal = false;
     }
 }
示例#9
0
	void menu::on_cursor(int y) {
		auto size = current_size();

		auto scale = glm::min(actual_height() / Decimal(size), actual_scale());
		auto spacing = uiTextHeight * scale;

		auto height = engine->get<renderer::base>().lock()->getheight();
		auto origin = height - y;

		/* origin = 50 + spacing * (size - i - 1);
		 * spacing * (size - i - 1) = origin - 50
		 * size - i - 1 = (origin - 50) / spacing
		 * i = size - (origin - 50) / spacing - 1
		 */
		auto i = int(glm::floor(size - (origin - 50) / spacing));
		if(i >= 0 && i < int(size)) { navigate_to(i); }
	}
示例#10
0
Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbackValue)
{
    // http://www.whatwg.org/specs/web-apps/current-work/#floating-point-numbers and parseToDoubleForNumberType
    // String::toDouble() accepts leading + and whitespace characters, which are not valid here.
    const UChar firstCharacter = string[0];
    if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter))
        return fallbackValue;

    const Decimal value = Decimal::fromString(string);
    if (!value.isFinite())
        return fallbackValue;

    // Numbers are considered finite IEEE 754 Double-precision floating point values.
    const Decimal doubleMax = Decimal::fromDouble(std::numeric_limits<double>::max());
    if (value < -doubleMax || value > doubleMax)
        return fallbackValue;

    // We return +0 for -0 case.
    return value.isZero() ? Decimal(0) : value;
}
示例#11
0
 /*
  * Constructor: char* B64coder::encode(char* key)
  *
  * Purpose: Use Base64 to encode data
  *
  * Arguments: char* key = starting address of a char array
  *
  * Returns: Result of encoded data
  */
char* B64coder::encode(char* key)
{
	std::string fullBinary;
        fullBinary = To8Binary(key);
        std::vector<int> Decimal((fullBinary.size() + 4)/6);
        Decimal = B64->Bit6ToDec(fullBinary);
        int finalSize = Decimal.size();
        while (finalSize % 4 != 0)
        {
                finalSize++;
        }
        char* fkptr = new char[Decimal.size()];
        for (int x = 0; x < finalSize; x++)
        {
                if( x < Decimal.size() )
                {
                        fkptr[x] = B64->cypherLookup(Decimal[x]);
                }else {
                        fkptr[x] = '=';
                }
        }
        return fkptr;
}
示例#12
0
Decimal parseToDecimalForNumberType(const String& string, const Decimal& fallbackValue)
{
    // See HTML5 2.5.4.3 `Real numbers.' and parseToDoubleForNumberType

    // String::toDouble() accepts leading + and whitespace characters, which are not valid here.
    const UChar firstCharacter = string[0];
    if (firstCharacter != '-' && firstCharacter != '.' && !isASCIIDigit(firstCharacter))
        return fallbackValue;

    const Decimal value = Decimal::fromString(string);
    if (!value.isFinite())
        return fallbackValue;

    // Numbers are considered finite IEEE 754 single-precision floating point values.
    // See HTML5 2.5.4.3 `Real numbers.'
    // FIXME: We should use numeric_limits<double>::max for number input type.
    const Decimal floatMax = Decimal::fromDouble(std::numeric_limits<float>::max());
    if (value < -floatMax || value > floatMax)
        return fallbackValue;

    // We return +0 for -0 case.
    return value.isZero() ? Decimal(0) : value;
}
int main()
{
	scanf("%d",&N);
	
	for(int i=0;i<N;i++)
	{
		memset(Numero,0,sizeof(Numero));
		scanf("%s",Numero);
		
		int R = Decimal();
		
		if(R%3==0)
			printf("YES %d",R);
		else
			printf("NO %d",R);
		
		if(i<N-1)
		{
			printf("\n");
		}
	}    

	return 0;
}
Decimal PriceCalculationRow::getPrice() const 
{ 
  return Decimal(price);
}
示例#15
0
Decimal& Decimal::operator*=(Decimal rhs)
{
    Decimal orig = *this;
    rationalize();
    rhs.rationalize();

    // Rule out problematic smallest Decimal
    JEWEL_ASSERT (minimum() == Decimal(numeric_limits<int_type>::min(), 0));
    JEWEL_ASSERT (maximum() == Decimal(numeric_limits<int_type>::max(), 0));
    if (*this == minimum() || rhs == minimum())
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalMultiplicationException,
            "Cannot multiply smallest possible "
            "Decimal safely."
        );
    }

    // Make absolute and remember signs
    bool const signs_differ =
    (   (m_intval < 0 && rhs.m_intval > 0) ||
        (m_intval > 0 && rhs.m_intval < 0)
    );
    if (m_intval < 0)
    {
        JEWEL_ASSERT
        (   !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1))
        );
        m_intval *= -1;
    }
    if (rhs.m_intval < 0)
    {
        JEWEL_ASSERT
        (   !multiplication_is_unsafe(rhs.m_intval, static_cast<int_type>(-1))
        );
        rhs.m_intval *= -1;
    }

    // Do "unchecked multiply" if we can
    JEWEL_ASSERT (m_intval >= 0 && rhs.m_intval >= 0);    
    if (!multiplication_is_unsafe(m_intval, rhs.m_intval))
    {
        JEWEL_ASSERT (!addition_is_unsafe(m_places, rhs.m_places));
        m_intval *= rhs.m_intval;
        m_places += rhs.m_places;
        while (m_places > s_max_places)
        {
            JEWEL_ASSERT (m_places > 0);
            #ifndef NDEBUG
                int const check = rescale(m_places - 1);
                JEWEL_ASSERT (check == 0);
            #else
                rescale(m_places - 1);
            #endif
        }
        if (signs_differ)
        {
            JEWEL_ASSERT (m_intval != numeric_limits<int_type>::min());
            JEWEL_ASSERT
            (   !multiplication_is_unsafe
                (   m_intval,
                    static_cast<int_type>(-1)
                )
            );
            m_intval *= -1;
        }
        rationalize();
        return *this;
    }

    *this = orig;
    JEWEL_THROW(DecimalMultiplicationException, "Unsafe multiplication.");
    JEWEL_HARD_ASSERT (false);  // Execution should never reach here.
    return *this;    // Silence compiler re. return from non-void function.

}
 Decimal YesNoNumber::getValueNumber() const
 {
     return Decimal( myImpl->getValueNumber().getValue() );
 }
 void setValue( const Decimal& value )
 {
     myDecimal = Decimal( value );
     myIsDecimal = true;
 }
示例#18
0
 void setValue( const Decimal& value )
 {
     myDecimal = Decimal( value );
     myIsNormal = false;
 }
示例#19
0
 void setValueNormal()
 {
     myDecimal = Decimal( 0 );
     myIsNormal = true;;
 }
示例#20
0
 Decimal FontSize::getValueNumber() const
 {
     return Decimal( myImpl->getValueNumber().getValue() );
 }
示例#21
0
int main(int argc, char **argv)
{
  init_rand();
  setup_gsl_dgen();

  dgen_parse_cmdline(argc, argv);

  int i, j, h, p, k, c;
  
  int cons_cap, num_cons = -1, root_cap, num_root = -1;
  char **cons_seqs, **root_seqs;

  int internal_node_index = 0, leaf_node_index = M;
  int max_internal_node_index = 2000000;
  int max_leaf_node_index = 2000000;
  int sum_seen_or_unseen = 0;

  int ploidy, codon_sequence_length = -1, n_genes, total_n_HLA;
  Decimal mu;

  if(json_parameters_path == NULL) die("No .json file passed.");

  load_lengths_for_simulation_from_json(json_parameters_path, &kappa, &mu,
                                        &codon_sequence_length, &total_n_HLA, &ploidy, &n_genes);

  if(ploidy < 1) die("Ploidy is less than 1.");
  if(n_genes < 1) die("Number of genes is less than 1.");
  
  if(cons_path != NULL) {
    printf("Loading sequences to obtain consensus...\n");
    num_cons = load_seqs(cons_path, &cons_seqs, &cons_cap);
    assert(num_cons > 0);
    printf("Loaded %i sequences to determine consensus.\n", num_cons);
    
    codon_sequence_length = strlen(cons_seqs[0]);
    printf("Codon_sequence_length: %i\n",codon_sequence_length/3);
    
    if(codon_sequence_length % 3 != 0)
      die("Sequences contain partial codons [%i mod 3 != 0].", codon_sequence_length);

    for(c = 0; c < num_cons; c++) {
      if((int) strlen(cons_seqs[c]) != codon_sequence_length) {
        die("Sequences from which to derive the consensus sequence aren't all "
            "the same length.");
      }
    }
    codon_sequence_length = codon_sequence_length/3;
  }

  if(root_path != NULL) {
    printf("Loading sequences to obtain root...\n");
    num_root = load_seqs(root_path, &root_seqs, &root_cap);
    printf("Loaded %i sequences to determine root.\n", num_root);
    
    if(cons_path == NULL)
      die("Did not pass a file to find the consensus sequence.");
    
    if((int) (strlen(root_seqs[0])/3) != codon_sequence_length)
      die("Sequences used to determine the root are different lengths to those used for the consensus.");

    for(c = 0; c < num_root; c++) {
      if((int) strlen(root_seqs[c]) != 3*codon_sequence_length) {
        die("Sequences from which to derive the root sequence aren't all "
            "the same length.");
      }
    }
  }

  Decimal *internal_node_times = my_malloc(max_internal_node_index * sizeof(Decimal) , __FILE__, __LINE__);
  Decimal *leaf_node_times = my_malloc(max_leaf_node_index * sizeof(Decimal), __FILE__, __LINE__);
  int *seen_or_unseen = my_malloc(max_internal_node_index * sizeof(int), __FILE__, __LINE__);

  birth_death_simulation_backwards(max_internal_node_index, max_leaf_node_index,
                                   internal_node_times, 
                                   leaf_node_times,
                                   &internal_node_index, &leaf_node_index,
                                   seen_or_unseen,
                                   N, M, lambda, mu_tree, past_sampling);

  for(i = 0; i < internal_node_index; i++) sum_seen_or_unseen += seen_or_unseen[i];
  
  int total_nodes = (2 * leaf_node_index) - 1 + internal_node_index - sum_seen_or_unseen;
  Tree *tree = my_malloc((total_nodes+1) * sizeof(Tree), __FILE__, __LINE__);
  // Now malloc the memory that this points to.
  int *HLAs_in_tree = my_malloc((total_nodes+1) * ploidy * n_genes * sizeof(int), __FILE__, __LINE__);

  for(i = 0; i < total_nodes; i++) 
    tree[i].HLAs = &HLAs_in_tree[i * ploidy * n_genes];

  construct_birth_death_tree(leaf_node_index, internal_node_index,
                             leaf_node_times, internal_node_times,
                             M, seen_or_unseen,
                             tree);

  // Reverse the direction that time is measured in the tree.
  // DEV: Don't need to do this, waste of computation - sort.
  // DEV: The parent times are wrong when there are unseen nodes.
  for(i = 0; i < total_nodes; i++)
    tree[i].node_time = tree[total_nodes-1].node_time - tree[i].node_time;
   
  int root_node = tree[total_nodes-1].node;
  
  if(write_newick_tree_to_file == true) {
    write_newick_tree(newick_tree_data_file, tree, root_node, 1);
    fclose(newick_tree_data_file);
  }

  Decimal S_portion[NUM_CODONS];
  Decimal NS_portion[NUM_CODONS];

  for(c = 0; c < NUM_CODONS; c++) {
    S_portion[c] = kappa * beta_S[c] + beta_V[c];
    NS_portion[c] = kappa * alpha_S[c] + alpha_V[c];
  }
  
  int n_HLA[n_genes];

  printf("Total number of HLA types: %i.\n", total_n_HLA);

  Decimal HLA_prevalences[total_n_HLA];
  int wildtype_sequence[codon_sequence_length];
  Decimal *R = my_malloc(codon_sequence_length * sizeof(Decimal), __FILE__, __LINE__);
  Decimal *omega = my_malloc(codon_sequence_length * sizeof(Decimal), __FILE__, __LINE__);
  Decimal *reversion_selection = my_malloc(codon_sequence_length * sizeof(Decimal), __FILE__, __LINE__);

  memory_allocation(num_cons, num_root, codon_sequence_length,
                    max_internal_node_index, max_leaf_node_index, 
                    total_nodes, ploidy, n_genes, total_n_HLA,
                    leaf_node_index);

  int (*codon_sequence_matrix)[codon_sequence_length] = my_malloc(total_nodes *
                                                                  sizeof(int[codon_sequence_length]),
                                                                  __FILE__, __LINE__);
  Decimal (*HLA_selection_profiles)[codon_sequence_length] = my_malloc(total_n_HLA * sizeof(Decimal[codon_sequence_length]),
                                                                       __FILE__, __LINE__);

  load_parameters_for_simulation_from_json(json_parameters_path, codon_sequence_length,
                                           omega, R, reversion_selection, total_n_HLA,
                                           n_genes, n_HLA, HLA_prevalences,
                                           HLA_selection_profiles);
  
  Decimal sum_check;
  for(i = 0, k = 0; i < n_genes; i++) {
    sum_check = 0;
    for(h = 0; h < n_HLA[i]; h++, k++) {
      sum_check += HLA_prevalences[k];
    }
    if(sum_check > 1.00001 || sum_check < 0.9999) die("HLA prevalences for gene %i do not sum to 1\n", i+1);
  }
  
  if(cons_path != NULL) {
    printf("Mapping gaps to consensus...\n");
    // Set the consensus sequence - the consensus of the optional sequence file 
    // that is passed.
    char wildtype_sequence_dummy[3*codon_sequence_length+1];
    generate_consensus(cons_seqs, num_cons, 3*codon_sequence_length, wildtype_sequence_dummy);
    printf("Wildtype sequence:\n%s\n", wildtype_sequence_dummy);
    // By default, set the root as the wildtype sequence.
    for(i = 0; i < codon_sequence_length; i++)
      wildtype_sequence[i] = (int) amino_to_code(wildtype_sequence_dummy+i*3);

    if(root_path == NULL) {
      for(i = 0; i < codon_sequence_length; i++)
        codon_sequence_matrix[root_node][i] = wildtype_sequence[i];
    } else {
      printf("Mapping gaps to root...\n");
      char root_sequence_dummy[3*codon_sequence_length+1];
      generate_consensus(root_seqs, num_root, 3*codon_sequence_length, root_sequence_dummy);
      printf("Root sequence:\n%s\n", root_sequence_dummy);
      
      for(i = 0; i < codon_sequence_length; i++)
        codon_sequence_matrix[root_node][i] = (int) amino_to_code(root_sequence_dummy+i*3);
      printf("Number of root sequences: %i.\n", num_root);
      for(c = 0; c < num_root; c++) free(root_seqs[c]);
      free(root_seqs);
    }
    printf("Number of consensus sequences: %i.\n", num_cons);
    for(c = 0; c < num_cons; c++) free(cons_seqs[c]);
    free(cons_seqs);
  
  } else {
    for(i = 0; i < codon_sequence_length; i++) {
      // Sample the root sequence according to the HIV codon usage information.
      codon_sequence_matrix[root_node][i] = discrete_sampling_dist(NUM_CODONS, prior_C1);
      // As default, set the root node to the consensus sequence.  
      wildtype_sequence[i] = codon_sequence_matrix[root_node][i];
    }
  }
  
  // No matter what is read in, there is no recombination simulated - so make sure it's set to 0.
  for(i = 0; i < codon_sequence_length; i++) R[i] = 0;

  write_summary_json(json_summary_file,
                     mu, codon_sequence_length, ploidy,
                     n_genes, n_HLA, total_n_HLA,
                     HLA_prevalences,
                     omega, R, reversion_selection,
                     HLA_selection_profiles);

  free(R);
  
  fprintf(simulated_root_file, ">root_sequence\n");
  for(i = 0; i < codon_sequence_length; i++)
    fprintf(simulated_root_file, "%s", code_to_char(codon_sequence_matrix[root_node][i]));
  fprintf(simulated_root_file, "\n");

  int root_HLA[ploidy * n_genes];
  int cumulative_n_HLA = 0;

  for(i = 0, k = 0; i < n_genes; i++) {
    for(p = 0; p < ploidy; p++, k++) {
      root_HLA[k] = cumulative_n_HLA + 
                    discrete_sampling_dist(n_HLA[i], &HLA_prevalences[cumulative_n_HLA]);
      tree[root_node].HLAs[k] = root_HLA[k];
    }
    cumulative_n_HLA = cumulative_n_HLA + n_HLA[i];
  }

  printf("Passing HLA information...\n");
  pass_HLA(ploidy, n_genes, root_node,
                           tree, leaf_node_index, total_n_HLA,
                           n_HLA, HLA_prevalences);
  printf("Passed HLA information\n");
  
  // printf("Printing the tree\n");
  // for(i = 0; i < total_nodes; i++) {
  //   printf("%i %i %i "DECPRINT" %i", tree[i].node, tree[i].daughter_nodes[0],
  //          tree[i].daughter_nodes[1], tree[i].node_time,
  //          tree[i].seen_or_unseen);
  //   for(j = 0; j < (ploidy * n_genes); j++) {
  //     printf(" %i", tree[i].HLAs[j]);
  //   }
  //   printf("\n");
  // }

  if(write_tree_to_file == true) {
    write_tree(tree_data_file, tree, root_node, ploidy, n_genes);
    fclose(tree_data_file);
  }

  printf("Passing sequence information...\n");
  
  pass_codon_sequence_change(codon_sequence_length, ploidy,
                             n_genes, total_n_HLA, 
                             root_node, mu,
                             codon_sequence_matrix,
                             tree,
                             leaf_node_index,
                             S_portion, NS_portion,
                             HLA_selection_profiles,
                             wildtype_sequence,
                             omega, reversion_selection);

  printf("Passed sequence information\n"
         "Now generating .fasta files of reference and query sequences, and\n"
         "a .csv file of the HLA information associated to the query sequences.\n");

  if(num_queries < 0) {
    // Set the number of query sequences.
    num_queries = (int) (query_fraction * leaf_node_index);
    printf("Number of queries: %i.\n", num_queries);
  } else {
    printf("Number of queries: %i.\n", num_queries);
  }

  if(num_queries > leaf_node_index) die("Number of query sequences larger than the number of leaves");
  int *all_sequences = my_malloc(leaf_node_index * sizeof(int), __FILE__, __LINE__);
  int num_refs = leaf_node_index - num_queries;

  for(i = 0; i < leaf_node_index; i++) all_sequences[i] = i;

  save_simulated_ref_and_query_fasta(num_queries, num_refs, leaf_node_index,
                                     all_sequences, codon_sequence_length, codon_sequence_matrix,
                                     tree, ploidy, n_genes);

  // Now save the hla types to a .csv file.
  fprintf(hla_query_file, "\"\",");
  for(h = 0; h < total_n_HLA-1; h++) fprintf(hla_query_file, "\"%i\",", h+1);
  fprintf(hla_query_file, "\"%i\"\n", total_n_HLA);
  
  // Write the HLA types of the leaves to a file.
  int (*hla_types)[total_n_HLA] = my_malloc(leaf_node_index * sizeof(int[total_n_HLA]), __FILE__, __LINE__);

  for(i = 0; i < leaf_node_index; i++)
  {
    for(h = 0; h < total_n_HLA; h++)
      hla_types[i][h] = 0;
    for(j = 0; j < (n_genes * ploidy); j++)
      hla_types[i][tree[i].HLAs[j]] = 1;
  }

  // Write the query HLA types to a .csv file.
  for(i = num_refs; i < leaf_node_index; i++)
  {
    fprintf(hla_query_file,"\"simulated_seq_%i_HLA", all_sequences[i]+1);
    for(h = 0; h < (ploidy * n_genes); h++) fprintf(hla_query_file, "_%i", tree[all_sequences[i]].HLAs[h]);
    fprintf(hla_query_file, "\"");
    for(h = 0; h < total_n_HLA; h++) {
      fprintf(hla_query_file, ",%i", hla_types[all_sequences[i]][h]);
    }
    fprintf(hla_query_file, "\n");
  }

  free(hla_types); 
  free(internal_node_times);
  free(leaf_node_times);
  free(seen_or_unseen);
  free(codon_sequence_matrix);
  free(HLA_selection_profiles);
  free(all_sequences);
  free(omega);
  free(reversion_selection);

  free(tree[0].HLAs);
  free(tree);

  fclose(summary_file);
  fclose(json_summary_file);
  fclose(simulated_refs_file);
  fclose(simulated_root_file);
  fclose(simulated_queries_file);
  fclose(hla_query_file);

  clearup_gsl_dgen();
  return EXIT_SUCCESS;
}
示例#22
0
Decimal Decimal::fromCents(long long cents)
{
    return Decimal((double)cents / 100.0);
}
示例#23
0
Decimal Decimal::operator /(const int rhs) const
{
    return Decimal(m_cents / rhs);
}
示例#24
0
Decimal Decimal::operator /(const double rhs) const
{
    return Decimal(m_cents / rhs);
}
示例#25
0
Decimal Decimal::operator -(const Decimal &rhs) const
{
    return Decimal(m_cents - rhs.m_cents);
}
示例#26
0
Decimal Decimal::fromValue(double value)
{
    return Decimal(value);
}
示例#27
0
// Update_F_numerical_recipes fills a preinitialised F from start_site
// to end_site.
void update_F_numerical_recipes(int num_sites, int closest_n, int total_num_refs,
                                Decimal codon_to_codon_HLA[NUM_CODONS][num_sites],
                                char ref_codons[total_num_refs][num_sites],
                                char ref_triplets[total_num_refs][num_sites],
                                Decimal R[num_sites],
                                Decimal F_in[closest_n][num_sites],
                                int F_rnorm_in[num_sites],
                                int F_rnorm_out[num_sites],
                                Decimal F_out[closest_n][num_sites],
                                int start_site, int end_site,
                                int closest_refs[closest_n],
                                int num_bases,
                                char cons_query_nucls[num_bases])
{
  int r, s = start_site, prev_F_rnorm;
  Decimal sum, ref_sum, F_sum;

  // The first column of F is the corresponding entries from codon_to_codon_HLA.
  Decimal (*F)[num_sites] = (s == 0 ? F_out : F_in);

  #ifdef USE_TRIPLET
    (void)ref_codons;
    if(s == 0)
    {
      for(r = 0; r < closest_n; r++)
        F_out[r][0] = codon_to_codon_HLA[(int)triplet_to_codon(ref_triplets[closest_refs[r]][0],
                                                               &cons_query_nucls[0])][0];

      F_rnorm_out[0] = 0;
      F_rnorm_in[0] = 0;
      s++;
    }
  #else
    (void)ref_triplets;
    (void)cons_query_nucls;
    (void)num_bases;
    if(s == 0)
    {
      for(r = 0; r < closest_n; r++)
        F_out[r][0] = codon_to_codon_HLA[(int)ref_codons[closest_refs[r]][0]][0];

      F_rnorm_out[0] = 0;
      F_rnorm_in[0] = 0;
      s++;
    }
  #endif

  prev_F_rnorm = F_rnorm_in[s - 1];

  // Now fill the remainder of F.
  // Note: F_norm records the number of times we multiply through by BIG
  // to get the column sum bigger than BIGI.
  for(; s <= end_site; s++)
  {
    F_sum = 0;
    ref_sum = 0;
    for(r = 0; r < closest_n; r++)
      ref_sum += F[r][s-1];
    ref_sum = ref_sum * R[s] / total_num_refs;
    for(r = 0; r < closest_n; r++)
    {
      sum = ref_sum;
      sum += (1 - R[s]) * F[r][s - 1];
      #ifdef USE_TRIPLET
        sum *= codon_to_codon_HLA[(int)triplet_to_codon(ref_triplets[closest_refs[r]][s],
                                                        &cons_query_nucls[s*3])][s];
        if(isnan(sum))
          printf("site: %i, codon: %i, reference: %i, "DECPRINT"\n", s,
                 (int)triplet_to_codon(ref_triplets[closest_refs[r]][s], &cons_query_nucls[s*3]), r,
                 codon_to_codon_HLA[(int)triplet_to_codon(ref_triplets[closest_refs[r]][s],
                                                          &cons_query_nucls[s*3])][s]);
      #else
        sum *= codon_to_codon_HLA[(int)ref_codons[closest_refs[r]][s]][s];
        if(isnan(sum))
          printf("hello "DECPRINT"\n", codon_to_codon_HLA[(int)ref_codons[closest_refs[r]][s]][s]);
      #endif

      F_out[r][s] = sum;
      F_sum += sum;
    } 
    
    F_rnorm_out[s] = prev_F_rnorm;
    
    if(F_sum < BIGI) {
      ++F_rnorm_out[s];
      for(r = 0; r < closest_n; r++)
        F_out[r][s] *= BIG;
    }
    F = F_out;
    prev_F_rnorm = F_rnorm_out[s];
  }
}
示例#28
0
namespace jewel
{

namespace
{

    /*
     * Hack: using this instead of static_cast because there appears to be a
     * bug in GCC 4.6.1 (at least on MinGW on Windows) when casting to
     * long long using static_cast or implicit cast.
     */
    template <typename Target>
    struct Converter
    {
        template <typename Source>
        static Target convert(Source p_source)
        {
            return p_source;
        }
    };

    /*
     * Specialize for conversions to long long to use boost::numeric cast to
     * avoid the bug.
     *
     * NOTE: Don't rely on the exceptions thrown by boost::numeric_cast.
     * If boost::numeric_cast is throws here, there's something wrong
     * with the program!
     */
    template <>
    struct Converter<long long>
    {
        template <typename Source>
        static long long convert(Source p_source)
        {
            return numeric_cast<long long>(p_source);
        }
    };

    template <typename Target, typename Source>
    Target num_cast(Source p_source);

    template <typename Target, typename Source>
    inline
    Target num_cast(Source p_source)
    {
        return Converter<Target>::template convert(p_source);
    }

}  // end anonymous namespace


/*
 * NOTE: Don't rely on the exceptions thrown by boost::numeric_cast.
 * If boost::numeric_cast is throws here, there's something wrong
 * with the program!
 */
#ifndef NDEBUG
#   define JEWEL_NUMERIC_CAST numeric_cast
#else
#   define JEWEL_NUMERIC_CAST num_cast      // faster
#endif


// initialize static data members

size_t const
Decimal::s_max_places = NumDigits::num_digits
(   numeric_limits<int_type>::min()
);

Decimal const
Decimal::s_maximum = Decimal(numeric_limits<int_type>::max(), 0);

Decimal const
Decimal::s_minimum = Decimal(numeric_limits<int_type>::min(), 0);


// static member functions


void Decimal::co_normalize(Decimal& x, Decimal& y)
{
    if (x.m_places == y.m_places)
    {
        // do nothing
    }
    else if (x.m_places < y.m_places)
    {
        if (x.rescale(y.m_places) != 0)
        {
            JEWEL_THROW
            (   DecimalRangeException,
                "Unsafe attempt to set fractional precision in course "
                "of co-normalization attempt."
            );
        }
    }
    else
    {
        JEWEL_ASSERT (y.m_places < x.m_places);
        if (y.rescale(x.m_places) != 0)
        {
            JEWEL_THROW
            (   DecimalRangeException,
                "Unsafe attempt to set fractional precision in course "
                "of co-normalization attempt."
            );
        }
    }
    return;
}


// some member functions


Decimal::Decimal(): m_places(0), m_intval(0)
{
}

Decimal::Decimal(int_type p_intval, places_type p_places):
    m_places(p_places),
    m_intval(p_intval)
{
    JEWEL_ASSERT (s_max_places == maximum_precision());
    if (m_places > s_max_places)
    {
        // There is no point setting m_intval and m_places to 0 (or any other
        // other valid value) here, since the Decimal instance is not going
        // to be created anyway - nothing will be able to refer to it after
        // this exception is thrown.
        JEWEL_THROW
        (   DecimalRangeException,
            "Attempt to construct Decimal with precision greater"
            " than maximum precision."
        );
    }
}

void
Decimal::rationalize(places_type min_places)
{
    JEWEL_ASSERT (s_base > 0);
    JEWEL_ASSERT (!remainder_is_unsafe(m_intval, s_base));
    while ((m_places > min_places) && (m_intval % s_base == 0))
    {
        JEWEL_ASSERT (!division_is_unsafe(m_intval, s_base));
        m_intval /= s_base;
        JEWEL_ASSERT (m_places > 0);
        --m_places;
    }
    return;
}

int Decimal::rescale(places_type p_places)
{
    #ifndef NDEBUG
        places_type const DEBUGVARIABLE_orig_places = m_places;
        int_type const DEBUGVARIABLE_orig_intval = m_intval;
    #endif

    if (m_places == p_places)
    {
        return 0;
    }

    // remember sign
    bool const is_positive = (m_intval > 0);
    #ifndef NDEBUG
        bool const is_zero = (m_intval == 0);
        bool const is_negative = (m_intval < 0);
    #endif

    if (m_places < p_places)
    {   
        if (p_places > s_max_places)
        {
            JEWEL_ASSERT (m_places == DEBUGVARIABLE_orig_places);
            JEWEL_ASSERT (m_intval == DEBUGVARIABLE_orig_intval);
            return 1;
        }
        JEWEL_ASSERT (p_places <= s_max_places);
        // This should never cause overflow, as p_places is never greater
        // than s_max_places, and s_base raised to a number equal to or
        // greater than p_places will always be less than
        // numeric_limits<int_type>::max(), given that s_max_places is
        // equal to the number of digits in numeric_limits<int_type>::min().
        JEWEL_ASSERT (!subtraction_is_unsafe(p_places, m_places));
        int_type multiplier = JEWEL_NUMERIC_CAST<int_type>
        (   pow(s_base, p_places - m_places)
        );

        if (multiplication_is_unsafe(m_intval, multiplier))
        {
            JEWEL_ASSERT (m_places == DEBUGVARIABLE_orig_places);
            JEWEL_ASSERT (m_intval == DEBUGVARIABLE_orig_intval);
            return 1;
         }
        m_intval *= multiplier;
    }
    else
    {
        JEWEL_ASSERT (p_places < m_places);

        // truncate all but one of the required places
        JEWEL_ASSERT (m_places > 0);
        for (unsigned int j = m_places - 1; j != p_places; --j)
        {
            JEWEL_ASSERT (!division_is_unsafe(m_intval, s_base));
            m_intval /= s_base;
        }

        // with one more place still to eliminate, we calculate
        // whether rounding is required
        JEWEL_ASSERT (!remainder_is_unsafe(m_intval, s_base));
        bool remainder =
        (   std::abs(m_intval % s_base) >=
            s_rounding_threshold
        );

        // now remove the remaining place
        JEWEL_ASSERT (!division_is_unsafe(m_intval, s_base));
        JEWEL_ASSERT (s_base > 1);
        m_intval /= s_base;
        JEWEL_ASSERT (m_intval < numeric_limits<int_type>::max());
        JEWEL_ASSERT (m_intval > numeric_limits<int_type>::min());

        // and add rounding if required
        if (remainder)
        {
            if (is_positive)
            {
                JEWEL_ASSERT
                (   !addition_is_unsafe(m_intval, static_cast<int_type>(1))
                );
                ++m_intval;
            }
            else
            {
                JEWEL_ASSERT (is_negative);
                JEWEL_ASSERT (!is_zero);
                JEWEL_ASSERT
                (   !subtraction_is_unsafe(m_intval, static_cast<int_type>(1))
                );
                --m_intval;
            }
        }
    }
    m_places = p_places;
    return 0;
}


Decimal::int_type
Decimal::implicit_divisor() const
{   
    static bool calculated_already = false;
    static vector<int_type> divisor_lookup(1, 1);
    while (!calculated_already)
    {
        while (divisor_lookup.size() != s_max_places)
        {
            JEWEL_ASSERT (!divisor_lookup.empty());
            JEWEL_ASSERT
            (   !multiplication_is_unsafe(divisor_lookup.back(), s_base)
            );
            divisor_lookup.push_back(divisor_lookup.back() * s_base);
        }
        calculated_already = true;
    }
    JEWEL_ASSERT (m_places < divisor_lookup.size());
    return divisor_lookup[m_places];
}



// operators

Decimal const& Decimal::operator++()
{
    #ifndef NDEBUG
        places_type const benchmark_places = m_places;
        Decimal const orig = *this;
    #endif
    if (addition_is_unsafe(m_intval, implicit_divisor()))
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalIncrementationException,
            "Incrementation may cause overflow."
        );
    }
    m_intval += implicit_divisor();
    JEWEL_ASSERT (m_places >= benchmark_places);
    return *this;
}

Decimal Decimal::operator++(int)
{
    Decimal const ret(*this);
    ++*this;
    return ret;
}

Decimal const& Decimal::operator--()
{
    #ifndef NDEBUG
        places_type const benchmark_places = m_places;
        Decimal const orig = *this;
    #endif
    if (subtraction_is_unsafe(m_intval, implicit_divisor()))
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalDecrementationException,
            "Decrementation may cause "
            "overflow."
        );
    }
    m_intval -= implicit_divisor();
    JEWEL_ASSERT (m_places >= benchmark_places);
    return *this;
}

Decimal Decimal::operator--(int)
{
    Decimal const ret(*this);
    --*this;
    return ret;
}

Decimal& Decimal::operator+=(Decimal rhs)
{
    #ifndef NDEBUG
        places_type const benchmark_places = max(m_places, rhs.m_places);
    #endif
    Decimal orig = *this;
    co_normalize(*this, rhs);
    if (addition_is_unsafe(m_intval, rhs.m_intval))
    {
        *this = orig;
        JEWEL_THROW(DecimalAdditionException, "Addition may cause overflow.");
    }
    m_intval += rhs.m_intval;
    JEWEL_ASSERT (m_places >= benchmark_places);
    return *this;
}



Decimal& Decimal::operator-=(Decimal rhs)
{
    #ifndef NDEBUG
        places_type const benchmark_places = max(m_places, rhs.m_places);
    #endif
    Decimal orig = *this;
    co_normalize(*this, rhs);
    if (subtraction_is_unsafe(m_intval, rhs.m_intval))
    {
        *this = orig;
        JEWEL_THROW
        (   DecimalSubtractionException,
            "Subtraction may cause overflow."
        );
    }
    m_intval -= rhs.m_intval;
    JEWEL_ASSERT (m_places >= benchmark_places);
    return *this;
}


Decimal& Decimal::operator*=(Decimal rhs)
{
    Decimal orig = *this;
    rationalize();
    rhs.rationalize();

    // Rule out problematic smallest Decimal
    JEWEL_ASSERT (minimum() == Decimal(numeric_limits<int_type>::min(), 0));
    JEWEL_ASSERT (maximum() == Decimal(numeric_limits<int_type>::max(), 0));
    if (*this == minimum() || rhs == minimum())
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalMultiplicationException,
            "Cannot multiply smallest possible "
            "Decimal safely."
        );
    }

    // Make absolute and remember signs
    bool const signs_differ =
    (   (m_intval < 0 && rhs.m_intval > 0) ||
        (m_intval > 0 && rhs.m_intval < 0)
    );
    if (m_intval < 0)
    {
        JEWEL_ASSERT
        (   !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1))
        );
        m_intval *= -1;
    }
    if (rhs.m_intval < 0)
    {
        JEWEL_ASSERT
        (   !multiplication_is_unsafe(rhs.m_intval, static_cast<int_type>(-1))
        );
        rhs.m_intval *= -1;
    }

    // Do "unchecked multiply" if we can
    JEWEL_ASSERT (m_intval >= 0 && rhs.m_intval >= 0);    
    if (!multiplication_is_unsafe(m_intval, rhs.m_intval))
    {
        JEWEL_ASSERT (!addition_is_unsafe(m_places, rhs.m_places));
        m_intval *= rhs.m_intval;
        m_places += rhs.m_places;
        while (m_places > s_max_places)
        {
            JEWEL_ASSERT (m_places > 0);
            #ifndef NDEBUG
                int const check = rescale(m_places - 1);
                JEWEL_ASSERT (check == 0);
            #else
                rescale(m_places - 1);
            #endif
        }
        if (signs_differ)
        {
            JEWEL_ASSERT (m_intval != numeric_limits<int_type>::min());
            JEWEL_ASSERT
            (   !multiplication_is_unsafe
                (   m_intval,
                    static_cast<int_type>(-1)
                )
            );
            m_intval *= -1;
        }
        rationalize();
        return *this;
    }

    *this = orig;
    JEWEL_THROW(DecimalMultiplicationException, "Unsafe multiplication.");
    JEWEL_HARD_ASSERT (false);  // Execution should never reach here.
    return *this;    // Silence compiler re. return from non-void function.

}


Decimal& Decimal::operator/=(Decimal rhs)
{
    // Record original dividend and divisor
    Decimal const orig = *this;

    rhs.rationalize();

    // Capture division by zero
    if (rhs.m_intval == 0)
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW(DecimalDivisionByZeroException, "Division by zero.");
    }
    
    // To prevent complications
    if ( m_intval == numeric_limits<int_type>::min() ||
      rhs.m_intval == numeric_limits<int_type>::min() )
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalDivisionException,
            "Smallest possible Decimal cannot "
            "feature in division operation."
        );
    }
    JEWEL_ASSERT (NumDigits::num_digits(rhs.m_intval) <= maximum_precision());
    if (NumDigits::num_digits(rhs.m_intval) == maximum_precision())
    {
        JEWEL_ASSERT (*this == orig);
        JEWEL_THROW
        (   DecimalDivisionException,
            "Dividend has a number of significant"
             "digits that is greater than or equal to the return value of "
            "Decimal::maximum_precision(); as a result, division cannot be "
            "performed safely."
        );
    }
    
    // Remember required sign of product
    bool const diff_signs =
    (   ( m_intval > 0 && rhs.m_intval < 0) ||
        ( m_intval < 0 && rhs.m_intval > 0)
    );

    // Make absolute
    JEWEL_ASSERT
    (   !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1))
    );
    JEWEL_ASSERT
    (   !multiplication_is_unsafe(rhs.m_intval, static_cast<int_type>(-1))
    );
    if (m_intval < 0) m_intval *= -1;
    if (rhs.m_intval < 0) rhs.m_intval *= -1;

    // Rescale the dividend as high as we can
    while (m_places < rhs.m_places && rescale(m_places + 1) == 0)
    {
    }
    if (rhs.m_places > m_places)
    {
        // We can't rescale high enough to proceed, so reset and throw
        *this = orig;
        JEWEL_THROW(DecimalDivisionException, "Unsafe division.");
    }

    // Proceed with basic division algorithm
    JEWEL_ASSERT (m_places >= rhs.m_places);
    JEWEL_ASSERT (!subtraction_is_unsafe(m_places, rhs.m_places));
    m_places -= rhs.m_places;
    JEWEL_ASSERT (rhs.m_intval != 0);
    JEWEL_ASSERT (m_intval != numeric_limits<int_type>::min());
    JEWEL_ASSERT (!remainder_is_unsafe(m_intval, rhs.m_intval));
    int_type remainder = m_intval % rhs.m_intval;
    JEWEL_ASSERT (!division_is_unsafe(m_intval, rhs.m_intval));
    m_intval /= rhs.m_intval;

    // Deal with any remainder using "long division"
    while (remainder != 0 && rescale(m_places + 1) == 0)
    {
        JEWEL_ASSERT (!multiplication_is_unsafe(remainder, s_base));

        /*
         * Previously this commented-out section of code dealt
         * with the case where it was unsafe to multiply remainder
         * and s_base. However, this is now dealt with by the fact that
         * an exception is thrown if the number of significant digits
         * in the dividend is equal to Decimal::maximum_precision().
         * This makes for a more straightforward API, since the
         * below code caused loss of precision under difficult-to-explain
         * circumstances.
        if (multiplication_is_unsafe(remainder, s_base))
        {
            // Then we can't proceed with ordinary "long division" safely,
            // and need to "scale down" first

            bool add_rounding_right = false;
            if (rhs.m_intval % s_base >= s_rounding_threshold)
            {
                add_rounding_right = true;
            }
            rhs.m_intval /= s_base;
            if (add_rounding_right)
            {
                JEWEL_ASSERT (!addition_is_unsafe(rhs.m_intval,
                  JEWEL_NUMERIC_CAST<int_type>(1)));
                ++(rhs.m_intval);
            }

            // Redo the Decimal division on a "safe scale"
            Decimal lhs = orig;
            if (lhs.m_intval < 0) lhs.m_intval *= -1;
            JEWEL_ASSERT (rhs.m_intval >= 0);
            lhs /= rhs;
            bool add_rounding_left = false;
            if (lhs.m_intval % s_base >= s_rounding_threshold)
            {
                add_rounding_left = true;    
            }
            lhs.m_intval /= s_base;
            if (add_rounding_left)
            {
                JEWEL_ASSERT (!addition_is_unsafe(lhs.m_intval,
                  JEWEL_NUMERIC_CAST<int_type>(1)));
                ++(lhs.m_intval);
            }
            if (diff_signs) lhs.m_intval *= -1;
            *this = lhs;

            return *this;
        }
        */

        // It's safe to proceed with ordinary "long division"
        JEWEL_ASSERT (!multiplication_is_unsafe(remainder, s_base));
        remainder *= s_base;

        JEWEL_ASSERT (rhs.m_intval > 0);
        JEWEL_ASSERT (!remainder_is_unsafe(remainder, rhs.m_intval));
        int_type const temp_remainder = remainder % rhs.m_intval;
        JEWEL_ASSERT (!division_is_unsafe(remainder, rhs.m_intval));
        m_intval += remainder / rhs.m_intval;
        remainder = temp_remainder;
    }

    // Do rounding if required
    JEWEL_ASSERT (rhs.m_intval >= remainder);
    JEWEL_ASSERT (!subtraction_is_unsafe(rhs.m_intval, remainder));
    if (rhs.m_intval - remainder <= remainder)
    {
        // If the required rounding would be unsafe, we throw
        if (addition_is_unsafe(m_intval, JEWEL_NUMERIC_CAST<int_type>(1)))
        {
            *this = orig;
            JEWEL_THROW(DecimalDivisionException, "Unsafe division.");
        }
        // Do the rounding, it's safe
        ++m_intval;
    }

    // Put the correct sign
    JEWEL_ASSERT (m_intval >= 0);
    JEWEL_ASSERT
    (   !multiplication_is_unsafe(m_intval, static_cast<int_type>(-1))
    );
    if (diff_signs) m_intval *= -1;
    rationalize();
    return *this;
}


bool Decimal::operator<(Decimal rhs) const
{   
    Decimal lhs = *this;
    lhs.rationalize();
    rhs.rationalize();
    if (lhs.m_places == rhs.m_places)
    {
        return lhs.m_intval < rhs.m_intval;
    }
    bool const left_is_longer = (lhs.m_places > rhs.m_places);
    Decimal const *const shorter = (left_is_longer? &rhs: &lhs);
    Decimal const *const longer = (left_is_longer? &lhs: &rhs);
    places_type const target_places = shorter->m_places;
    int_type longers_revised_intval = longer->m_intval;
    int_type const shorters_intval = shorter->m_intval;
    bool const longer_is_negative = (longers_revised_intval < 0);
    for
    (   places_type longers_places = longer->m_places;
        longers_places != target_places;
        --longers_places
    )
    {
        JEWEL_ASSERT (s_base > 0);
        JEWEL_ASSERT (!division_is_unsafe(longers_revised_intval, s_base));
        longers_revised_intval /= s_base;
        JEWEL_ASSERT (longers_places > 0);
    }
    bool longer_is_smaller =
    (   longer_is_negative?
        (longers_revised_intval <= shorters_intval):
        (longers_revised_intval < shorters_intval)
    );
    return ( &lhs == (longer_is_smaller? longer: shorter) );
}


bool Decimal::operator==(Decimal rhs) const
{
    Decimal temp_lhs = *this;
    temp_lhs.rationalize();
    rhs.rationalize();
    return
    (   temp_lhs.m_intval == rhs.m_intval &&
        temp_lhs.m_places == rhs.m_places
    );
}


Decimal round(Decimal const& x, Decimal::places_type decimal_places)
{
    Decimal ret = x;
    if (ret.rescale(decimal_places) != 0)
    {   
        JEWEL_THROW
        (   DecimalRangeException,
            "Decimal number cannot safely be rounded to "
            "this number of places."
        );
    }
    return ret;
}


Decimal operator-(Decimal const& d)
{
    typedef Decimal::int_type int_type;
    if (d.m_intval == numeric_limits<int_type>::min())
    {
        JEWEL_THROW
        (   DecimalUnaryMinusException,
            "Unsafe arithmetic operation (unary minus)."
        );
    }
    JEWEL_ASSERT (d.m_intval != numeric_limits<int_type>::min());
    Decimal ret = d;
    JEWEL_ASSERT
    (   !multiplication_is_unsafe(ret.m_intval, static_cast<int_type>(-1))
    );
    ret.m_intval *= -1;
    return ret;
}



}  // namespace jewel