int main() { char num1[100]; char num2[100]; char op[2]; while(scanf("%s",num1) != EOF) { getchar(); scanf("%s", op); scanf("%s", num2); reverseStr(num1); reverseStr(num2); char ret[100] = {0}; if(op[0] == '*') { bigMulChar(num1, num2, ret); } else { bigDivide(num1, num2, ret); } reverseStr(ret); printf("%s\n", ret); } return 0; }
void getRet(char* ret, int n, int m) { int i; for(i = m + n; i > 1; i--) { bigMuti(ret, i); } bigMuti(ret, m + 1 - n); bigDivide(ret, m + 1); }
void getRet(char* ret, int n) { int i; for(i = 2 * n; i > n; i--) { bigMuti(ret, i); } for(i = 2; i <= n + 1; i++) { bigDivide(ret, i); } }
bool InflationOpFrame::doApply(medida::MetricsRegistry& metrics, LedgerDelta& delta, LedgerManager& ledgerManager) { LedgerDelta inflationDelta(delta); auto& lcl = inflationDelta.getHeader(); time_t closeTime = lcl.scpValue.closeTime; uint32_t seq = lcl.inflationSeq; time_t inflationTime = (INFLATION_START_TIME + seq * INFLATION_FREQUENCY); if (closeTime < inflationTime) { metrics.NewMeter({"op-inflation", "failure", "not-time"}, "operation") .Mark(); innerResult().code(INFLATION_NOT_TIME); return false; } /* Inflation is calculated using the following 1. calculate tally of votes based on "inflationDest" set on each account 2. take the top accounts (by vote) that get at least .05% of the vote 3. If no accounts are over this threshold then the extra goes back to the inflation pool */ int64_t totalVotes = lcl.totalCoins; int64_t minBalance = bigDivide(totalVotes, INFLATION_WIN_MIN_PERCENT, TRILLION); std::vector<AccountFrame::InflationVotes> winners; auto& db = ledgerManager.getDatabase(); AccountFrame::processForInflation( [&](AccountFrame::InflationVotes const& votes) { if (votes.mVotes >= minBalance) { winners.push_back(votes); return true; } return false; }, INFLATION_NUM_WINNERS, db); int64 amountToDole = bigDivide(lcl.totalCoins, INFLATION_RATE_TRILLIONTHS, TRILLION); amountToDole += lcl.feePool; lcl.feePool = 0; lcl.inflationSeq++; // now credit each account innerResult().code(INFLATION_SUCCESS); auto& payouts = innerResult().payouts(); int64 leftAfterDole = amountToDole; for (auto const& w : winners) { AccountFrame::pointer winner; int64 toDoleThisWinner = bigDivide(amountToDole, w.mVotes, totalVotes); if (toDoleThisWinner == 0) continue; winner = AccountFrame::loadAccount(w.mInflationDest, db); if (winner) { leftAfterDole -= toDoleThisWinner; lcl.totalCoins += toDoleThisWinner; winner->getAccount().balance += toDoleThisWinner; winner->storeChange(inflationDelta, db); payouts.emplace_back(w.mInflationDest, toDoleThisWinner); } } // put back in fee pool as unclaimed funds lcl.feePool += leftAfterDole; inflationDelta.commit(); metrics.NewMeter({"op-inflation", "success", "apply"}, "operation").Mark(); return true; }
bool InflationOpFrame::doApply(medida::MetricsRegistry& metrics, LedgerDelta& delta, LedgerManager& ledgerManager) { LedgerDelta inflationDelta(delta); auto& lcl = inflationDelta.getHeader(); time_t closeTime = lcl.scpValue.closeTime; uint32_t seq = lcl.inflationSeq; time_t inflationTime = (INFLATION_START_TIME + seq * INFLATION_FREQUENCY); if (closeTime < inflationTime) { metrics.NewMeter({"op-inflation", "failure", "not-time"}, "operation") .Mark(); innerResult().code(INFLATION_NOT_TIME); return false; } /* Inflation is calculated using the following 1. calculate tally of votes based on "inflationDest" set on each account 2. take the top accounts (by vote) that exceed 1.5% (INFLATION_WIN_MIN_PERCENT) of votes, up to 50 accounts (INFLATION_NUM_WINNERS) exception: if no account crosses the INFLATION_WIN_MIN_PERCENT, the top 50 is used 3. share the coins between those accounts proportionally to the number of votes they got. */ int64_t totalVotes = 0; bool first = true; int64_t minBalance = bigDivide(lcl.totalCoins, INFLATION_WIN_MIN_PERCENT, TRILLION); std::vector<AccountFrame::InflationVotes> winners; auto& db = ledgerManager.getDatabase(); AccountFrame::processForInflation( [&](AccountFrame::InflationVotes const& votes) { if (first && votes.mVotes < minBalance) { // need to take the entire set if nobody crossed the threshold minBalance = 0; } first = false; bool res; if (votes.mVotes >= minBalance) { totalVotes += votes.mVotes; winners.push_back(votes); res = true; } else { res = false; } return res; }, INFLATION_NUM_WINNERS, db); int64 amountToDole = bigDivide(lcl.totalCoins, INFLATION_RATE_TRILLIONTHS, TRILLION); amountToDole += lcl.feePool; lcl.feePool = 0; lcl.inflationSeq++; // now credit each account innerResult().code(INFLATION_SUCCESS); auto& payouts = innerResult().payouts(); if (totalVotes != 0) { for (auto const& w : winners) { AccountFrame::pointer winner; int64 toDoleThisWinner = bigDivide(amountToDole, w.mVotes, totalVotes); if (toDoleThisWinner == 0) continue; winner = AccountFrame::loadAccount(w.mInflationDest, db); if (winner) { lcl.totalCoins += toDoleThisWinner; winner->getAccount().balance += toDoleThisWinner; winner->storeChange(inflationDelta, db); payouts.emplace_back(w.mInflationDest, toDoleThisWinner); } else { // put back in fee pool as unclaimed funds lcl.feePool += toDoleThisWinner; } } } else { // put back in fee pool as unclaimed funds lcl.feePool += amountToDole; } inflationDelta.commit(); metrics.NewMeter({"op-inflation", "success", "apply"}, "operation").Mark(); return true; }
OfferExchange::CrossOfferResult OfferExchange::crossOffer(OfferFrame& sellingWheatOffer, int64_t maxWheatReceived, int64_t& numWheatReceived, int64_t maxSheepSend, int64_t& numSheepSend) { Asset& sheep = sellingWheatOffer.getOffer().buying; Asset& wheat = sellingWheatOffer.getOffer().selling; AccountID& accountBID = sellingWheatOffer.getOffer().sellerID; Database& db = mLedgerManager.getDatabase(); AccountFrame::pointer accountB; accountB = AccountFrame::loadAccount(accountBID, db); if (!accountB) { throw std::runtime_error( "invalid database state: offer must have matching account"); } TrustFrame::pointer wheatLineAccountB; if (wheat.type() != ASSET_TYPE_NATIVE) { wheatLineAccountB = TrustFrame::loadTrustLine(accountBID, wheat, db); if (!wheatLineAccountB) { throw std::runtime_error( "invalid database state: offer must have matching trust line"); } } TrustFrame::pointer sheepLineAccountB; if (sheep.type() == ASSET_TYPE_NATIVE) { numWheatReceived = INT64_MAX; } else { sheepLineAccountB = TrustFrame::loadTrustLine(accountBID, sheep, db); if (!sheepLineAccountB) { throw std::runtime_error( "invalid database state: offer must have matching trust line"); } // compute numWheatReceived based on what the account can receive int64_t sellerMaxSheep = sheepLineAccountB->getMaxAmountReceive(); if (!bigDivide(numWheatReceived, sellerMaxSheep, sellingWheatOffer.getOffer().price.d, sellingWheatOffer.getOffer().price.n)) { numWheatReceived = INT64_MAX; } } // adjust numWheatReceived with what the seller has { int64_t wheatCanSell; if (wheat.type() == ASSET_TYPE_NATIVE) { // can only send above the minimum balance wheatCanSell = accountB->getBalanceAboveReserve(mLedgerManager); } else { if (wheatLineAccountB->isAuthorized()) { wheatCanSell = wheatLineAccountB->getBalance(); } else { wheatCanSell = 0; } } if (numWheatReceived > wheatCanSell) { numWheatReceived = wheatCanSell; } } // you can receive the lesser of the amount of wheat offered or // the amount the guy has if (numWheatReceived >= sellingWheatOffer.getOffer().amount) { numWheatReceived = sellingWheatOffer.getOffer().amount; } else { // update the offer based on the balance (to determine if it should be // deleted or not) // note that we don't need to write into the db at this point as the // actual update // is done further down sellingWheatOffer.getOffer().amount = numWheatReceived; } bool reducedOffer = false; if (numWheatReceived > maxWheatReceived) { numWheatReceived = maxWheatReceived; reducedOffer = true; } // this guy can get X wheat to you. How many sheep does that get him? if (!bigDivide(numSheepSend, numWheatReceived, sellingWheatOffer.getOffer().price.n, sellingWheatOffer.getOffer().price.d)) { numSheepSend = INT64_MAX; } if (numSheepSend > maxSheepSend) { // reduce the number even more if there is a limit on Sheep numSheepSend = maxSheepSend; reducedOffer = true; } // bias towards seller (this cannot overflow at this point) numWheatReceived = bigDivide(numSheepSend, sellingWheatOffer.getOffer().price.d, sellingWheatOffer.getOffer().price.n); bool offerTaken = false; if (numWheatReceived == 0 || numSheepSend == 0) { if (reducedOffer) { return eOfferCantConvert; } else { // force delete the offer as it represents a bogus offer numWheatReceived = 0; numSheepSend = 0; offerTaken = true; } } offerTaken = offerTaken || sellingWheatOffer.getOffer().amount <= numWheatReceived; if (offerTaken) { // entire offer is taken sellingWheatOffer.storeDelete(mDelta, db); accountB->addNumEntries(-1, mLedgerManager); accountB->storeChange(mDelta, db); } else { sellingWheatOffer.getOffer().amount -= numWheatReceived; sellingWheatOffer.storeChange(mDelta, db); } // Adjust balances if (sheep.type() == ASSET_TYPE_NATIVE) { accountB->getAccount().balance += numSheepSend; accountB->storeChange(mDelta, db); } else { if (!sheepLineAccountB->addBalance(numSheepSend)) { return eOfferCantConvert; } sheepLineAccountB->storeChange(mDelta, db); } if (wheat.type() == ASSET_TYPE_NATIVE) { accountB->getAccount().balance -= numWheatReceived; accountB->storeChange(mDelta, db); } else { if (!wheatLineAccountB->addBalance(-numWheatReceived)) { return eOfferCantConvert; } wheatLineAccountB->storeChange(mDelta, db); } mOfferTrail.push_back( ClaimOfferAtom(accountB->getID(), sellingWheatOffer.getOfferID(), wheat, numWheatReceived, sheep, numSheepSend)); return offerTaken ? eOfferTaken : eOfferPartial; }
int64_t OfferFrame::computePrice() const { return bigDivide(mOffer.price.n, OFFER_PRICE_DIVISOR, mOffer.price.d); }