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; }
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(); }
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); } }
// 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); }
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; }
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; } }
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); } }
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; }
/* * 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; }
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); }
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; }
void setValue( const Decimal& value ) { myDecimal = Decimal( value ); myIsNormal = false; }
void setValueNormal() { myDecimal = Decimal( 0 ); myIsNormal = true;; }
Decimal FontSize::getValueNumber() const { return Decimal( myImpl->getValueNumber().getValue() ); }
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; }
Decimal Decimal::fromCents(long long cents) { return Decimal((double)cents / 100.0); }
Decimal Decimal::operator /(const int rhs) const { return Decimal(m_cents / rhs); }
Decimal Decimal::operator /(const double rhs) const { return Decimal(m_cents / rhs); }
Decimal Decimal::operator -(const Decimal &rhs) const { return Decimal(m_cents - rhs.m_cents); }
Decimal Decimal::fromValue(double value) { return Decimal(value); }
// 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]; } }
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