bool Index::ConstructLowerBoundTuple( storage::Tuple *index_key, const std::vector<peloton::Value> &values, const std::vector<oid_t> &key_column_ids, const std::vector<ExpressionType> &expr_types) { auto schema = index_key->GetSchema(); auto col_count = schema->GetColumnCount(); bool all_constraints_equal = true; // Go over each column in the key tuple // Setting either the placeholder or the min value for (oid_t column_itr = 0; column_itr < col_count; column_itr++) { auto key_column_itr = std::find(key_column_ids.begin(), key_column_ids.end(), column_itr); bool placeholder = false; Value value; // This column is part of the key column ids if (key_column_itr != key_column_ids.end()) { auto offset = std::distance(key_column_ids.begin(), key_column_itr); // Equality constraint if (expr_types[offset] == EXPRESSION_TYPE_COMPARE_EQUAL) { placeholder = true; value = values[offset]; } // Not all expressions / constraints are equal else { all_constraints_equal = false; } } LOG_TRACE("Column itr : %u Placeholder : %d ", column_itr, placeholder); // Fill in the placeholder if (placeholder == true) { index_key->SetValue(column_itr, value, GetPool()); } // Fill in the min value else { auto value_type = schema->GetType(column_itr); index_key->SetValue(column_itr, Value::GetMinValue(value_type), GetPool()); } } LOG_TRACE("Lower Bound Tuple :: %s", index_key->GetInfo().c_str()); if (col_count > values.size()) all_constraints_equal = false; return all_constraints_equal; }
// WorkerThread Method unsigned int cSQLPool::WorkerThread(void) { PerSQLConnection* perSQLConnection = NULL; while ( !_is_exit ) { _condition.wait(_mutex); mc_system_db::PPerhandleDataDB tmpData = GetData(); // SQLConnection. perSQLConnection = GetPool( ); // SQLConnection. if ( perSQLConnection == NULL ) { // 10/1000(s) - CPU Sleep( 10 ); QueueRequest( tmpData ); continue; } // SQLConnection. ReleasePool( perSQLConnection ); } return 0L; }
// DefaultWorkingSize Method bool cSocketContextPool::DefaultWorkingSize(DWORD workingSize) { cCSLock lock( mCs ); // Critical Section PerSocketContext* temp = NULL; try { while ( workingSize > 0 ) { temp = GetPool( ); if ( temp == NULL ) throw false; // Socket Context workingSize--; } throw true; } catch ( bool boolean ) { while ( mPagedPoolUsage != NULL ) { ReleasePool( mPagedPoolUsage ); } return boolean; } }
bool DataTable::InsertInSecondaryIndexes(const storage::Tuple *tuple, ItemPointer location) { int index_count = GetIndexCount(); // (A) Check existence for primary/unique indexes // FIXME Since this is NOT protected by a lock, concurrent insert may happen. for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) { auto index = GetIndex(index_itr); auto index_schema = index->GetKeySchema(); auto indexed_columns = index_schema->GetIndexedColumns(); std::unique_ptr<storage::Tuple> key(new storage::Tuple(index_schema, true)); key->SetFromTuple(tuple, indexed_columns, index->GetPool()); switch (index->GetIndexType()) { case INDEX_CONSTRAINT_TYPE_PRIMARY_KEY: break; case INDEX_CONSTRAINT_TYPE_UNIQUE: { // if in this index there has been a visible or uncommitted // <key, location> pair, this constraint is violated index->InsertEntry(key.get(), location); } break; case INDEX_CONSTRAINT_TYPE_DEFAULT: default: index->InsertEntry(key.get(), location); break; } LOG_TRACE("Index constraint check on %s passed.", index->GetName().c_str()); } return true; }
void CoWork::Pool::ThreadRun(int tno) { LLOG("CoWork thread #" << tno << " started"); Pool& p = GetPool(); p.lock.Enter(); for(;;) { while(!p.jobs.InList()) { LHITCOUNT("CoWork: Parking thread to Wait"); if(p.quit) { p.lock.Leave(); return; } p.waiting_threads++; LLOG("#" << tno << " Waiting for job"); p.waitforjob.Wait(p.lock); LLOG("#" << tno << " Waiting ended"); p.waiting_threads--; } LLOG("#" << tno << " Job acquired"); LHITCOUNT("CoWork: Running new job"); p.DoJob(*p.jobs.GetNext()); LLOG("#" << tno << " Job finished"); } p.lock.Leave(); LLOG("CoWork thread #" << tno << " finished"); }
/* * Withdraw some bits from the pool. Regardless of the distribution of the * input bits, the bits returned are uniformly distributed, although they * cannot, of course, contain more Shannon entropy than the input bits. */ static void sRandPoolGetBytesEntropy( void * priv, PGPByte * buf, unsigned len, unsigned bits) { RandomPool *pool = GetPool(); unsigned t; pgpAssert( pool ); (void)priv; if (pool->randBits >= bits) pool->randBits -= bits; else pool->randFrac = pool->randBits = 0; while (len > (t = sizeof(pool->randOut) - pool->randOutGetPos)) { pgpCopyMemory( (PGPByte *)pool->randOut + pool->randOutGetPos, buf, t); buf += t; len -= t; sRandGetOutput( pool ); } if (len) { pgpCopyMemory( (PGPByte *)pool->randOut+pool->randOutGetPos, buf, len); pool->randOutGetPos += len; } }
bool CoWork::IsFinished() { Pool& p = GetPool(); p.lock.Enter(); bool b = jobs.IsEmpty(1); p.lock.Leave(); return b; }
static void sRandPoolStirLock(void *priv) { RandomPool *pool = GetPool(); PGPRMWOLockStartWriting( &pool->criticalLock ); sRandPoolStir( priv ); PGPRMWOLockStopWriting( &pool->criticalLock ); }
bool DataTable::InsertInSecondaryIndexes(const AbstractTuple *tuple, const TargetList *targets_ptr, ItemPointer *index_entry_ptr) { int index_count = GetIndexCount(); // Transaform the target list into a hash set // when attempting to perform insertion to a secondary index, // we must check whether the updated column is a secondary index column. // insertion happens only if the updated column is a secondary index column. std::unordered_set<oid_t> targets_set; for (auto target : *targets_ptr) { targets_set.insert(target.first); } // Check existence for primary/unique indexes // Since this is NOT protected by a lock, concurrent insert may happen. for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) { auto index = GetIndex(index_itr); auto index_schema = index->GetKeySchema(); auto indexed_columns = index_schema->GetIndexedColumns(); if (index->GetIndexType() == INDEX_CONSTRAINT_TYPE_PRIMARY_KEY) { continue; } // Check if we need to update the secondary index bool updated = false; for (auto col : indexed_columns) { if (targets_set.find(col) != targets_set.end()) { updated = true; break; } } // If attributes on key are not updated, skip the index update if (updated == false) { continue; } // Key attributes are updated, insert a new entry in all secondary index std::unique_ptr<storage::Tuple> key(new storage::Tuple(index_schema, true)); key->SetFromTuple(tuple, indexed_columns, index->GetPool()); switch (index->GetIndexType()) { case INDEX_CONSTRAINT_TYPE_PRIMARY_KEY: break; case INDEX_CONSTRAINT_TYPE_UNIQUE: break; case INDEX_CONSTRAINT_TYPE_DEFAULT: default: index->InsertEntry(key.get(), index_entry_ptr); break; } LOG_TRACE("Index constraint check on %s passed.", index->GetName().c_str()); } return true; }
bool CoWork::TrySchedule(Function<void ()>&& fn) { Pool& p = GetPool(); Mutex::Lock __(p.lock); if(!p.free) return false; p.PushJob(pick(fn), NULL); return true; }
static void sRandPoolAddBytesLock( void * priv, PGPByte const * p, unsigned len) { RandomPool *pool = GetPool(); PGPRMWOLockStartWriting( &pool->criticalLock ); sRandPoolAddBytes( priv, p, len ); PGPRMWOLockStopWriting( &pool->criticalLock ); }
static void sRandPoolGetBytesEntropyLock( void * priv, PGPByte * buf, unsigned len, unsigned bits) { RandomPool *pool = GetPool(); PGPRMWOLockStartWriting( &pool->criticalLock ); sRandPoolGetBytesEntropy( priv, buf, len, bits ); PGPRMWOLockStopWriting( &pool->criticalLock ); }
void RedisReply::ReserveMember(size_t num) { type = REDIS_REPLY_ARRAY; if (NULL == elements) { elements = new std::deque<RedisReply*>; } for (uint32 i = elements->size(); i < num; i++) { RedisReply& reply = GetPool().Allocate(); reply.type = REDIS_REPLY_NIL; elements->push_back(&reply); } }
// GetPerSocketContext Method // ReleasePerSocketContext Context Switching PerSocketContext* cSocketContextPool::GetPerSocketContext(SOCKET socket, SOCKADDR_IN addr, DWORD ttl) { cCSLock lock( mCs ); // Critical Section PerSocketContext* perSocketContext = GetPool( ); // Socket Context if ( perSocketContext != NULL ) { perSocketContext->socket = socket; perSocketContext->addr = addr; // IP perSocketContext->timeToLive = GetTickCount( ) + ttl; // TTL. } return perSocketContext; }
void CoWork::Finish() { Pool& p = GetPool(); p.lock.Enter(); while(!jobs.IsEmpty(1)) { LLOG("Finish: todo: " << todo << " (CoWork " << FormatIntHex(this) << ")"); p.DoJob(*jobs.GetNext(1)); } while(todo) { LLOG("WaitForFinish (CoWork " << FormatIntHex(this) << ")"); waitforfinish.Wait(p.lock); } p.lock.Leave(); LLOG("CoWork " << FormatIntHex(this) << " finished"); }
BOOL BN_SUB_I(BIGNUM * y, DWORD n) { BOOL bRet=FALSE; BIGNUM *temp; temp = GetPool(sizeof(BIGNUM)); if (temp){ BN_SET_I(temp, n); bRet = BN_SUB(y, temp); ExFreePool(temp); } return bRet; }
/* * Destroys already-used random numbers. Ensures no sensitive data * remains in memory that can be recovered later. This repeatedly * mixes the output of the generator back into itself until all internal * state has been overwritten. */ static void sRandPoolStir(void * priv ) { RandomPool *pool = GetPool(); unsigned i; pgpAssert( pool ); (void)priv; for (i = 0; i < 5*sizeof(pool->randKey)/sizeof(pool->randOut); i++) { sRandPoolAddBytes(priv, (PGPByte *)pool->randOut, sizeof(pool->randOut)); sRandGetOutput( pool ); } }
RedisReply& RedisReply::AddMember(bool tail) { type = REDIS_REPLY_ARRAY; if (NULL == elements) { elements = new std::deque<RedisReply*>; } RedisReply& reply = GetPool().Allocate(); if (tail) { elements->push_back(&reply); } else { elements->push_front(&reply); } return reply; }
void CoWork::Do(Function<void ()>&& fn) { LHITCOUNT("CoWork: Sheduling callback"); Pool& p = GetPool(); p.lock.Enter(); if(!p.free) { LLOG("Stack full: running in the originating thread"); LHITCOUNT("CoWork: Stack full: Running in originating thread"); p.lock.Leave(); fn(); if(Pool::finlock) p.lock.Leave(); return; } p.PushJob(pick(fn), this); todo++; p.lock.Leave(); }
/* * Make a deposit of information (entropy) into the pool. */ static void sRandPoolAddBytes( void * priv, PGPByte const * p, unsigned len) { RandomPool *pool = GetPool(); pgpAssert( pool ); (void)priv; while (len--) { sRandPoolAddByte( pool, *p++ ); } /* Pool has changed, randOut is out of date */ pool->randOutGetPos = sizeof(pool->randOut); }
CTimeSpan CThreadPool_Controller_PID::GetSafeSleepTime(void) const { double last_err = 0, integr_err = 0; CThreadPool* pool = GetPool(); if (!pool) { return CTimeSpan(0, 0); } {{ CMutexGuard guard(GetMainPoolMutex(pool)); if (m_ErrHistory.size() == 0) { return CThreadPool_Controller::GetSafeSleepTime(); } last_err = m_ErrHistory.back().err; integr_err = m_IntegrErr; }} unsigned int threads_cnt = pool->GetThreadsCount(); if (last_err == 0 || (last_err > 0 && threads_cnt == GetMaxThreads()) || (last_err < 0 && threads_cnt == GetMinThreads())) { return CThreadPool_Controller::GetSafeSleepTime(); } double sleep_time = 0; if (last_err > 0) { sleep_time = (m_Threshold - last_err - integr_err) * m_IntegrCoeff / last_err; } else { sleep_time = (-m_Threshold - last_err - integr_err) * m_IntegrCoeff / last_err; } if (sleep_time < 0) sleep_time = 0; return CTimeSpan(sleep_time); }
/** * @brief Insert a tuple into all indexes. If index is primary/unique, * check visibility of existing * index entries. * @warning This still doesn't guarantee serializability. * * @returns True on success, false if a visible entry exists (in case of *primary/unique). */ bool DataTable::InsertInIndexes(const storage::Tuple *tuple, ItemPointer location) { int index_count = GetIndexCount(); auto &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); std::function<bool(const ItemPointer &)> fn = std::bind(&concurrency::TransactionManager::IsOccupied, &transaction_manager, std::placeholders::_1); // (A) Check existence for primary/unique indexes // FIXME Since this is NOT protected by a lock, concurrent insert may happen. for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) { auto index = GetIndex(index_itr); auto index_schema = index->GetKeySchema(); auto indexed_columns = index_schema->GetIndexedColumns(); std::unique_ptr<storage::Tuple> key(new storage::Tuple(index_schema, true)); key->SetFromTuple(tuple, indexed_columns, index->GetPool()); switch (index->GetIndexType()) { case INDEX_CONSTRAINT_TYPE_PRIMARY_KEY: case INDEX_CONSTRAINT_TYPE_UNIQUE: { // TODO: get unique tuple from primary index. // if in this index there has been a visible or uncommitted // <key, location> pair, this constraint is violated if (index->CondInsertEntry(key.get(), location, fn) == false) { return false; } } break; case INDEX_CONSTRAINT_TYPE_DEFAULT: default: index->InsertEntry(key.get(), location); break; } LOG_TRACE("Index constraint check on %s passed.", index->GetName().c_str()); } return true; }
PGPError pgpInitGlobalRandomPool() { RandomPool * pool = NULL; pool = GetPool(); pool->randBits = 0; pool->randFrac = 0; pool->randInBits = 0; pool->randKeyBits = 0; pool->randKeyFrac = 0; pool->randPoolAddPos = 0; pool->randKeyAddPos = 0; pool->randOutGetPos = sizeof( pool->randOut); pool->randHashCounter = 0; InitializePGPRMWOLock( &pool->criticalLock ); return( kPGPError_NoErr ); }
static PGPUInt32 pgpGlobalRandomPoolEntropyWasAdded( PGPUInt32 delta ) { PGPUInt32 frac, t; unsigned n; RandomPool * pool = GetPool(); if (delta < 1 << DERATING) return 0; n = 31-DERATING; if (!(delta & 0xffff0000)) delta <<= 16, n -= 16; if (!(delta & 0xff000000)) delta <<= 8, n -= 8; if (!(delta & 0xf0000000)) delta <<= 4, n -= 4; if (!(delta & 0xc0000000)) delta <<= 2, n -= 2; if (!(delta & 0x80000000)) delta <<= 1, n -= 1; pgpAssert(n < 32); /* Lose high-order bit of delta */ pgpAssert(delta & 0x80000000); delta <<= 1; frac = pool->randKeyFrac; UMULH_32(t,delta,frac); if ((frac += t) < t) { if ((frac += delta) < delta) frac = (frac >> 1) + 0x80000000ul; else frac >>= 1; n++; } else if ((frac += delta) < delta) {
BWTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::BWTreeIndex( IndexMetadata *metadata) : Index(metadata), container(KeyComparator(metadata), KeyEqualityChecker(metadata)), equals(metadata), comparator(metadata) { // Add your implementation here // Set min key of bwtree auto schema = metadata->GetKeySchema(); auto col_count = schema->GetColumnCount(); std::unique_ptr<storage::Tuple> min_key_tuple(new storage::Tuple(metadata->GetKeySchema(), true)); for (oid_t column_itr = 0; column_itr < col_count; column_itr++) { auto value_type = schema->GetType(column_itr); min_key_tuple->SetValue(column_itr, Value::GetMinValue(value_type), GetPool()); } KeyType min_key; min_key.SetFromKey(min_key_tuple.get()); container.SetMinKey(min_key); container.Init(); }
// delete a tuple from all its indexes it belongs to. void TransactionLevelGCManager::DeleteTupleFromIndexes(ItemPointer *indirection) { // do nothing if indirection is null if (indirection == nullptr){ return; } LOG_TRACE("Deleting indirection %p from index", indirection); ItemPointer location = *indirection; auto &manager = catalog::Manager::GetInstance(); auto tile_group = manager.GetTileGroup(location.block); PL_ASSERT(tile_group != nullptr); storage::DataTable *table = dynamic_cast<storage::DataTable *>(tile_group->GetAbstractTable()); PL_ASSERT(table != nullptr); // construct the expired version. expression::ContainerTuple<storage::TileGroup> expired_tuple(tile_group.get(), location.offset); // unlink the version from all the indexes. for (size_t idx = 0; idx < table->GetIndexCount(); ++idx) { auto index = table->GetIndex(idx); auto index_schema = index->GetKeySchema(); auto indexed_columns = index_schema->GetIndexedColumns(); // build key. std::unique_ptr<storage::Tuple> key( new storage::Tuple(index_schema, true)); key->SetFromTuple(&expired_tuple, indexed_columns, index->GetPool()); index->DeleteEntry(key.get(), indirection); } }
void CoWork::FinLock() { Pool::finlock = true; GetPool().lock.Enter(); }
void CThreadPool_Controller_PID::OnEvent(EEvent event) { if (event == eSuspend) { return; } // All reads below are atomic reads of one variable, thus they cannot // return bad results. They can be a little bit inconsistent with each // other because of races with other threads but that's okay for the // purposes of this controller. unsigned int threads_count = GetPool()->GetThreadsCount(); unsigned int queued_tasks = GetPool()->GetQueuedTasksCount(); unsigned int run_tasks = GetPool()->GetExecutingTasksCount(); if (threads_count == 0) { EnsureLimits(); threads_count = GetMinThreads(); // Special case when MinThreads == 0 if (threads_count == 0) { if (queued_tasks == 0) { return; } threads_count = 1; SetThreadsCount(threads_count); } } double now_err = (double(queued_tasks + run_tasks) - threads_count) / threads_count; double now_time = m_Timer.Elapsed(); if (event == eResume) { // When we resuming we need to avoid panic because of big changes in // error value. So we will assume that current error value was began // long time ago and didn't change afterwards. m_ErrHistory.clear(); m_ErrHistory.push_back(SThreadPool_PID_ErrInfo(now_time - m_DerivTime, now_err)); } double period = now_time - m_ErrHistory.back().call_time; if (now_err < 0 && threads_count == GetMinThreads() && m_IntegrErr <= 0) { now_err = 0; } double integr_err = m_IntegrErr + (now_err + m_ErrHistory.back().err) / 2 * period / m_IntegrCoeff; while (m_ErrHistory.size() > 1 && now_time - m_ErrHistory[1].call_time >= m_DerivTime) { m_ErrHistory.pop_front(); } if (now_time - m_ErrHistory.back().call_time >= m_DerivTime / 10) { m_ErrHistory.push_back(SThreadPool_PID_ErrInfo(now_time, now_err)); if (threads_count == GetMaxThreads() && integr_err > m_Threshold) { m_IntegrErr = m_Threshold; } else if (threads_count == GetMinThreads() && integr_err < -m_Threshold) { m_IntegrErr = -m_Threshold; } else { m_IntegrErr = integr_err; } } double deriv_err = (now_err - m_ErrHistory[0].err) / m_DerivTime * m_DerivCoeff; double final_val = (now_err + integr_err + deriv_err) / m_Threshold; /* LOG_POST(CTime(CTime::eCurrent).AsString("M/D/Y h:m:s.l").c_str() << " count=" << threads_count << ", queued=" << queued_tasks << ", run=" << run_tasks << ", err=" << now_err << ", time=" << now_time << ", intErr=" << m_IntegrErr << ", derivErr=" << deriv_err << ", final=" << final_val << ", hist_size=" << m_ErrHistory.size()); */ if (final_val >= 1 || final_val <= -1) { if (final_val < 0 && -final_val > threads_count) SetThreadsCount(GetMinThreads()); else SetThreadsCount(threads_count + int(final_val)); } else { EnsureLimits(); } }
/** * @brief Insert a tuple into all indexes. If index is primary/unique, * check visibility of existing * index entries. * @warning This still doesn't guarantee serializability. * * @returns True on success, false if a visible entry exists (in case of *primary/unique). */ bool DataTable::InsertInIndexes(const storage::Tuple *tuple, ItemPointer location, concurrency::Transaction *transaction, ItemPointer **index_entry_ptr) { int index_count = GetIndexCount(); size_t active_indirection_array_id = number_of_tuples_ % ACTIVE_INDIRECTION_ARRAY_COUNT; size_t indirection_offset = INVALID_INDIRECTION_OFFSET; while (true) { auto active_indirection_array = active_indirection_arrays_[active_indirection_array_id]; indirection_offset = active_indirection_array->AllocateIndirection(); if (indirection_offset != INVALID_INDIRECTION_OFFSET) { *index_entry_ptr = active_indirection_array->GetIndirectionByOffset(indirection_offset); break; } } (*index_entry_ptr)->block = location.block; (*index_entry_ptr)->offset = location.offset; if (indirection_offset == INDIRECTION_ARRAY_MAX_SIZE - 1) { AddDefaultIndirectionArray(active_indirection_array_id); } auto &transaction_manager = concurrency::TransactionManagerFactory::GetInstance(); std::function<bool(const void *)> fn = std::bind(&concurrency::TransactionManager::IsOccupied, &transaction_manager, transaction, std::placeholders::_1); // Since this is NOT protected by a lock, concurrent insert may happen. bool res = true; int success_count = 0; for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) { auto index = GetIndex(index_itr); auto index_schema = index->GetKeySchema(); auto indexed_columns = index_schema->GetIndexedColumns(); std::unique_ptr<storage::Tuple> key(new storage::Tuple(index_schema, true)); key->SetFromTuple(tuple, indexed_columns, index->GetPool()); switch (index->GetIndexType()) { case INDEX_CONSTRAINT_TYPE_PRIMARY_KEY: { // get unique tuple from primary index. // if in this index there has been a visible or uncommitted // <key, location> pair, this constraint is violated res = index->CondInsertEntry(key.get(), *index_entry_ptr, fn); } break; case INDEX_CONSTRAINT_TYPE_UNIQUE: { // get unique tuple from primary index. // if in this index there has been a visible or uncommitted // <key, location> pair, this constraint is violated // res = index->CondInsertEntry(key.get(), *index_entry_ptr, fn); } break; case INDEX_CONSTRAINT_TYPE_DEFAULT: default: index->InsertEntry(key.get(), *index_entry_ptr); break; } // Handle failure if (res == false) { // If some of the indexes have been inserted, // the pointer has a chance to be dereferenced by readers and it cannot be deleted *index_entry_ptr = nullptr; return false; } else { success_count += 1; } LOG_TRACE("Index constraint check on %s passed.", index->GetName().c_str()); } return true; }
//x = y * n + m BOOL BN_DIV(BIGNUM * y, CONST BIGNUM * x, CONST BIGNUM * n, BIGNUM * m) { BOOL bRet = FALSE; BOOL bResult = FALSE; INT nResult= 0; DWORD i = 0; ULARGE_INTEGER m0; ULONGLONG n0 = 0; ULONGLONG min = 0, div = 0, max = 0; BIGNUM *mul=NULL; BIGNUM *sub=NULL; ULONGLONG ld = 0, d = 0, rd = 0; // mul = GetPool(sizeof(BIGNUM)); sub = GetPool(sizeof(BIGNUM)); if (!sub || !mul){ CONDITION_ASSERT(bResult); } BN_SET_I(sub, 0); BN_SET_I(mul, 0); BN_SET_I(y, 0); BN_SET(m, x); // for (i = x->dwCount; n->dwCount <= i; --i) { CONDITION_ASSERT(i == m->dwCount || i + 1 == m->dwCount); m0.QuadPart = m->dwDigits[i - 1]; if (i < m->dwCount) { m0.u.HighPart = m->dwDigits[m->dwCount - 1]; } n0 = n->dwDigits[n->dwCount - 1]; max = (m0.QuadPart / n0); min = (m0.QuadPart / (n0 + 1)); CONDITION_ASSERT(min <= max); // for ( ld = 0, rd = max - min; ; ) { d = ld + (rd - ld) / 2; div = max - d; if (ld == rd) break; // bResult = BN_MUL_I(mul, n, div); CONDITION_ASSERT(bResult); // bResult = BN_LSHIFT_D(mul, i - n->dwCount); CONDITION_ASSERT(bResult); // nResult = BN_CMP(m, mul); if (0 < nResult) { BN_SET(sub, m); // bResult = BN_SUB(sub, mul); CONDITION_ASSERT(bResult); // BN_RSHIFT_D(sub, i - n->dwCount); // nResult = BN_CMP(n, sub); if (0 < nResult) break; // rd = d; continue; } if (nResult < 0) { ld = d + 1; continue; } // if (0 == r) { break; } } // bResult = BN_MUL_I(mul, n, div); CONDITION_ASSERT(bResult); // bResult = BN_LSHIFT_D(mul, i - n->dwCount); CONDITION_ASSERT(bResult); // bResult = BN_SUB(m, mul); CONDITION_ASSERT(bResult); // y->dwDigits[i - n->dwCount] = (DWORD)div; } // if (n->dwCount < x->dwCount) { y->dwCount = x->dwCount - n->dwCount + 1; } for (i = y->dwCount; 0 < i; --i) { if (y->dwDigits[i - 1]) { break; } if (1 < y->dwCount) { --y->dwCount; } } bRet = TRUE; Exit0: if (mul){ ExFreePool(mul); } if (sub){ ExFreePool(sub); } return bRet; }