/* static int hasForcedNeighbours (astar_t *astar, coord_t coord, int dir) { #define ENTERABLE(n) isEnterable (astar, \ adjustInDirection (coord, dir + (n))) if (directionIsDiagonal (dir)) return !implies (ENTERABLE (-2), ENTERABLE (-3)) || !implies (ENTERABLE (2), ENTERABLE (3)); else return !implies (ENTERABLE (-1), ENTERABLE (-2)) || !implies (ENTERABLE (1), ENTERABLE (2)); #undef ENTERABLE } */ static directionset forcedNeighbours (astar_t *astar, coord_t coord, direction dir) { if (dir == NO_DIRECTION) return 0; directionset dirs = 0; #define ENTERABLE(n) isEnterable (astar, \ adjustInDirection (coord, (dir + (n)) % 8)) if (directionIsDiagonal (dir)) { if (!implies (ENTERABLE (6), ENTERABLE (5))) dirs = addDirectionToSet (dirs, (dir + 6) % 8); if (!implies (ENTERABLE (2), ENTERABLE (3))) dirs = addDirectionToSet (dirs, (dir + 2) % 8); } else { if (!implies (ENTERABLE (7), ENTERABLE (6))) dirs = addDirectionToSet (dirs, (dir + 7) % 8); if (!implies (ENTERABLE (1), ENTERABLE (2))) dirs = addDirectionToSet (dirs, (dir + 1) % 8); } #undef ENTERABLE return dirs; }
ListenerRecord::ListenerRecord(IEventListener *aListener, com::SafeArray<VBoxEventType_T> &aInterested, BOOL aActive, EventSource *aOwner) : mActive(aActive), mOwner(aOwner), mQEventBusyCnt(0), mRefCnt(0) { mListener = aListener; EventMap *aEvMap = &aOwner->m->mEvMap; for (size_t i = 0; i < aInterested.size(); ++i) { VBoxEventType_T interested = aInterested[i]; for (int j = FirstEvent; j < LastEvent; j++) { VBoxEventType_T candidate = (VBoxEventType_T)j; if (implies(interested, candidate)) { (*aEvMap)[j - FirstEvent].add(this); } } } if (!mActive) { ::RTCritSectInit(&mcsQLock); ::RTSemEventCreate(&mQEvent); mLastRead = RTTimeMilliTS(); } else { mQEvent = NIL_RTSEMEVENT; RT_ZERO(mcsQLock); mLastRead = 0; } }
int main(){ int i,j; for(i=0; i < 100; ++i){ g(a,i); g(b,i); foo(i); } ASSERT(forall(idx, implies(0<=idx && idx <100, a[idx] == 0 && b[idx] == 0))); for(j=100;j < 200; ++j){ g(b,j); foo(j); } ASSERT(forall(idx_0, implies(100<=idx_0 && idx_0 < 200, b[idx_0] == 0))); return 1; }
void Device_init_control_vars( const Device* device, Device_states* dstates, Device_control_var_mode mode, Random* random, Channel* channel) { assert(device != NULL); assert(dstates != NULL); assert(implies(mode == DEVICE_CONTROL_VAR_MODE_MIXED, random != NULL)); assert(implies(mode == DEVICE_CONTROL_VAR_MODE_VOICE, channel != NULL)); if (device->init_control_vars != NULL) device->init_control_vars(device, dstates, mode, random, channel); return; }
bool Predicate::implies(const AST::Predicate& other) const { if (kind() == FALSE || other.kind() == TRUE) { return true; } if (kind() == OR) { // (A or B) => C is true iff ((A => C) and (B => C)). return orLeft().implies(other) && orRight().implies(other); } if (other.kind() == AND) { // A => (B and C) is true iff ((A => B) and (A => C)). return implies(other.andLeft()) && implies(other.andRight()); } if (kind() == AND) { // (A and B) => C is true iff ((A => C) or (B => C)). return andLeft().implies(other) || andRight().implies(other); } if (other.kind() == OR) { // A => (B or C) is true iff ((A => B) or (A => C)). return implies(other.orLeft()) || implies(other.orRight()); } if (kind() != other.kind()) { return false; } switch (kind()) { case SELFCONST: return true; case SATISFIES: // TODO: this needs to be improved to allow covariant // treatment of the requirement type (e.g. T : copyable_and_movable<T> // implies T : movable). return satisfiesType() == other.satisfiesType() && satisfiesRequirement() == other.satisfiesRequirement(); case VARIABLE: return variableTemplateVar() == other.variableTemplateVar(); default: locic_unreachable("Reached unreachable block in 'implies'."); } }
void solver_type:: calc_next_pass ( technique_type technique , method_type method , bool is_parallel_method , rate_type damping , rate_type rate_x , rate_type rate_y , sheet_type const & src_sheet , sheet_type & trg_sheet ) // Instead of dealing with sheet_type this could start with these src/trg objects: // stride_range< src_iter_type, 1 > src_range // stride_range< trg_iter_type, 1 > trg_range // See swap_xy( range_xy) -> range_yx { d_assert( 0 != & src_sheet); d_assert( 0 != & trg_sheet); d_assert( src_sheet.get_x_count( ) == trg_sheet.get_x_count( )); d_assert( src_sheet.get_y_count( ) == trg_sheet.get_y_count( )); // The two sheets must be different (unless technique == e_ortho_interleave). d_assert( implies( (technique != e_ortho_interleave), ((& src_sheet) != (& trg_sheet)) )); if ( not_early_exit( ) ) { if ( technique == e_ortho_interleave ) { // This works even if src_sheet and trg_sheet are the same. calc_next_ortho_interleave ( method, is_parallel_method , rate_x, rate_y , src_sheet, trg_sheet ); } else if ( technique == e_simultaneous_2d ) { calc_next_simultaneous_2d ( method, is_parallel_method , rate_x, rate_y , src_sheet, trg_sheet ); } else /* technique == e_wave_with_damping */ { d_assert( technique == e_wave_with_damping); calc_next_wave_with_damping ( method, is_parallel_method , damping, rate_x, rate_y , src_sheet, trg_sheet ); } } if ( not_early_exit( ) ) { fix_out_of_bounds_if_necessary( technique, method, damping, rate_x, rate_y, trg_sheet); } }
void Device_port_groups_init(Device_port_groups groups, int first_group_size, ...) { rassert(groups != NULL); rassert(first_group_size >= 0); rassert(implies(first_group_size > 0, is_p2(first_group_size))); rassert(first_group_size <= WORK_BUFFER_SUB_COUNT_MAX); for (int i = 0; i < PORT_GROUPS_MAX; ++i) groups[i] = 0; va_list args; va_start(args, first_group_size); groups[0] = (int8_t)first_group_size; int size_count = 0; if (first_group_size > 0) { for (size_count = 1; size_count < PORT_GROUPS_MAX; ++size_count) { const int size = va_arg(args, int); rassert(size >= 0); rassert(size <= WORK_BUFFER_SUB_COUNT_MAX); rassert(implies(size > 0, is_p2(size))); groups[size_count] = (int8_t)size; if (groups[size_count] == 0) break; } } if (size_count == PORT_GROUPS_MAX) { const int zero = va_arg(args, int); rassert(zero == 0); } va_end(args); return; }
static double linear_interpolate( double inputValue, double inputLimit1, double inputLimit2, double outputLimit1, double outputLimit2 ) { assert( implies( inputLimit1 <= inputLimit2, inputLimit1 <= inputValue && inputValue <= inputLimit2 ) ); assert( implies( inputLimit1 >= inputLimit2, inputLimit2 <= inputValue && inputValue <= inputLimit1 ) ); assert( implies( inputLimit1 == inputLimit2, outputLimit1 == outputLimit2 ) ); assert( implies( inputLimit1 == inputLimit2, inputValue == inputLimit1 ) ); const double t = ( inputValue - inputLimit1 ) / ( inputLimit2 - inputLimit1 ); assert( 0.0f <= t ); assert( t <= 1.0f ); // The following uses the minimum number of operators: double result = outputLimit2; result *= t; double r1 = outputLimit1; r1 *= ( 1 - t ); result += r1; assert( implies( outputLimit1 <= outputLimit2, outputLimit1 - FLT_EPSILON <= result && result <= outputLimit2 + FLT_EPSILON ) ); assert( implies( outputLimit1 >= outputLimit2, outputLimit2 - FLT_EPSILON <= result && result <= outputLimit1 + FLT_EPSILON ) ); return result; }
bool int_range_steps_holder:: is_valid( ) const { return (get_min_value( ) <= get_value( )) && (get_value( ) <= get_max_value( )) && (get_single_step( ) >= 0) && (get_page_step( ) >= 0) && implies( (get_page_step( ) > 0), (get_page_step( ) >= get_single_step( ))); }
/** * Create new message from user provided data, which are copied into the * allocated data block. If no user buffer is provided, an empty message * is created and the length is used to size the data block. * * @return a message made of one message block referencing one new data block. */ pmsg_t * pmsg_new(int prio, const void *buf, int len) { pmsg_t *mb; pdata_t *db; g_assert(len > 0); g_assert(implies(buf, valid_ptr(buf))); WALLOC(mb); db = pdata_new(len); return pmsg_fill(mb, db, prio, FALSE, buf, len); }
bool Polynomial::multiImply(const Polynomial* e1, int e1_num, const Polynomial& e2) { #if (linux || __MACH__) #ifdef __PRT_QUERY std::cout << "-------------Multi-Imply solving-------------\n"; #endif z3::config cfg; cfg.set("auto_config", true); z3::context c(cfg); z3::expr hypo = e1[0].toZ3expr(NULL, c); for (int i = 1; i < e1_num; i++) { hypo = hypo && e1[i].toZ3expr(NULL, c);; } z3::expr conc = e2.toZ3expr(NULL, c); //std::cout << "hypo: " << hypo << std::endl; //std::cout << "conc: " << conc << std::endl; z3::expr query = implies(hypo, conc); #ifdef __PRT_QUERY std::cout << "Query : " << query << std::endl; std::cout << "Answer: "; #endif z3::solver s(c); s.add(!query); z3::check_result ret = s.check(); if (ret == unsat) { #ifdef __PRT_QUERY std::cout << "True" << std::endl; #endif return true; } else { #ifdef __PRT_QUERY std::cout << "False" << std::endl; #endif return false; } #endif return false; }
int * main (int x, int y){ int * a; int i; if ( x< 0 || y < 0 || y > x ) return (int *) 0; a = (int *) malloc( x * sizeof(int)); if (a == 0 ) exit(1); for (i=0; i < y ; ++i) { ASSERT(valid(&a[i])); a[i] = 0; } ASSERT(forall(idx, implies(idx >=0 && idx < y, valid(&a[idx]) && a[idx] == 0))); return a; }
/** * Like pmsg_new() but returns an extended form with a free routine callback. */ pmsg_t * pmsg_new_extend(int prio, const void *buf, int len, pmsg_free_t free_cb, void *arg) { pmsg_ext_t *emb; pdata_t *db; g_assert(len > 0); g_assert(implies(buf, valid_ptr(buf))); WALLOC(emb); db = pdata_new(len); emb->m_free = free_cb; emb->m_arg = arg; (void) pmsg_fill(&emb->pmsg, db, prio, TRUE, buf, len); return cast_to_pmsg(emb); }
/** * Create an external (arena not embedded) data buffer out of existing arena. * * The optional `freecb' structure supplies the free routine callback to be * used to free the arena, with freearg as additional argument. If the free * routine is NULL, then the external arena will be freed with g_free() when * the data buffer is reclaimed. */ pdata_t * pdata_allocb_ext(void *buf, int len, pdata_free_t freecb, void *freearg) { pdata_t *db; g_assert(valid_ptr(buf)); g_assert(implies(freecb, valid_ptr(freecb))); WALLOC(db); db->magic = PDATA_MAGIC; db->d_arena = buf; db->d_end = (char *) buf + len; db->d_refcnt = 0; db->d_free = freecb; db->d_arg = freearg; g_assert((size_t) len == pdata_len(db)); g_assert(db->d_arena != db->d_embedded); return db; }
/** * Create an embedded data buffer out of existing arena. * * The optional `freecb' structure supplies the free routine callback to be * used to free the arena, with freearg as additional argument. * If no free routine is specified (i.e. NULL given as `freecb'), then the * arena will be freed with wfree(buf, len) when the data buffer is reclaimed. */ pdata_t * pdata_allocb(void *buf, int len, pdata_free_t freecb, void *freearg) { pdata_t *db; g_assert(valid_ptr(buf)); g_assert(UNSIGNED(len) >= EMBEDDED_OFFSET); g_assert(implies(freecb, valid_ptr(freecb))); db = buf; db->magic = PDATA_MAGIC; db->d_arena = db->d_embedded; db->d_end = db->d_arena + (len - EMBEDDED_OFFSET); db->d_refcnt = 0; db->d_free = freecb; db->d_arg = freearg; g_assert((size_t) len - EMBEDDED_OFFSET == pdata_len(db)); return db; }
void Device_set_control_var_generic( const Device* device, Device_states* dstates, Device_control_var_mode mode, Random* random, Channel* channel, const char* var_name, const Value* value) { assert(device != NULL); assert(dstates != NULL); assert(random != NULL); assert(implies(mode == DEVICE_CONTROL_VAR_MODE_VOICE, channel != NULL)); assert(var_name != NULL); assert(value != NULL); assert(Value_type_is_realtime(value->type)); if (device->set_control_var_generic != NULL) device->set_control_var_generic( device, dstates, mode, random, channel, var_name, value); return; }
/** * Fill newly created message block. * * @return the message block given as argument. */ static pmsg_t * pmsg_fill(pmsg_t *mb, pdata_t *db, int prio, bool ext, const void *buf, int len) { mb->magic = ext ? PMSG_EXT_MAGIC : PMSG_MAGIC; mb->m_data = db; mb->m_prio = prio; mb->m_flags = ext ? PMSG_PF_EXT : 0; mb->m_u.m_check = NULL; mb->m_refcnt = 1; db->d_refcnt++; if (buf) { mb->m_rptr = db->d_arena; mb->m_wptr = db->d_arena + len; memcpy(db->d_arena, buf, len); } else mb->m_rptr = mb->m_wptr = db->d_arena; g_assert(implies(buf, len == pmsg_size(mb))); pmsg_check_consistency(mb); return mb; }
bool Polynomial::uniImply(const Polynomial& e2) { #if (linux || __MACH__) #ifdef __PRT_QUERY std::cout << BLUE << "-------------uni-Imply solving-------------\n" << NORMAL; std::cout << RED << *this << " ==> " << e2 << std::endl << NORMAL; #endif z3::config cfg; cfg.set("auto_config", true); z3::context c(cfg); z3::expr hypo = this->toZ3expr(NULL, c); z3::expr conc = e2.toZ3expr(NULL, c); z3::expr query = implies(hypo, conc); #ifdef __PRT_QUERY std::cout << "\nhypo: " << hypo << std::endl; std::cout << "conc: " << conc << std::endl; std::cout << BLUE << "Query : " << query << std::endl << NORMAL; #endif z3::solver s(c); s.add(!query); z3::check_result ret = s.check(); if (ret == unsat) { #ifdef __PRT_QUERY std::cout << "Answer: UNSAT\n"; #endif return true; } #ifdef __PRT_QUERY std::cout << "Answer: SAT\n"; #endif #endif return false; }
int EventSync::waitAny( EventSync **events, size_t count, UInt32 msTimeout ) { CASSERT( c_maxEventCount <= MAXIMUM_WAIT_OBJECTS ); dbgAssert( implies( count, events ) ); if ( count > c_maxEventCount ) { throw std::runtime_error( "Not supported." ); } void *handles[ c_maxEventCount ] = {}; for( size_t i = 0; i < count; ++i ) { dbgAssert( events[ i ] ); handles[ i ] = events[ i ]->m_handle; } DWORD res = WaitForMultipleObjects( count, handles, FALSE /* waitAll */, msTimeout ); dbgAssert( res >= WAIT_OBJECT_0 && res < WAIT_OBJECT_0 + count || res == WAIT_TIMEOUT ); return res == WAIT_TIMEOUT ? -1 : res - WAIT_OBJECT_0; }
bool disjunctive_polynomial_accelerationt::accelerate( path_acceleratort &accelerator) { std::map<exprt, polynomialt> polynomials; scratch_programt program(symbol_table); accelerator.clear(); #ifdef DEBUG std::cout << "Polynomial accelerating program:" << std::endl; for (goto_programt::instructionst::iterator it = goto_program.instructions.begin(); it != goto_program.instructions.end(); ++it) { if (loop.find(it) != loop.end()) { goto_program.output_instruction(ns, "scratch", std::cout, it); } } std::cout << "Modified:" << std::endl; for (expr_sett::iterator it = modified.begin(); it != modified.end(); ++it) { std::cout << expr2c(*it, ns) << std::endl; } #endif if (loop_counter.is_nil()) { symbolt loop_sym = utils.fresh_symbol("polynomial::loop_counter", unsigned_poly_type()); loop_counter = loop_sym.symbol_expr(); } patht &path = accelerator.path; path.clear(); if (!find_path(path)) { // No more paths! return false; } #if 0 for (expr_sett::iterator it = modified.begin(); it != modified.end(); ++it) { polynomialt poly; exprt target = *it; if (it->type().id() == ID_bool) { // Hack: don't try to accelerate booleans. continue; } if (target.id() == ID_index || target.id() == ID_dereference) { // We'll handle this later. continue; } if (fit_polynomial(target, poly, path)) { std::map<exprt, polynomialt> this_poly; this_poly[target] = poly; if (utils.check_inductive(this_poly, path)) { #ifdef DEBUG std::cout << "Fitted a polynomial for " << expr2c(target, ns) << std::endl; #endif polynomials[target] = poly; accelerator.changed_vars.insert(target); break; } } } if (polynomials.empty()) { return false; } #endif // Fit polynomials for the other variables. expr_sett dirty; utils.find_modified(accelerator.path, dirty); polynomial_acceleratort path_acceleration(symbol_table, goto_functions, loop_counter); goto_programt::instructionst assigns; for (patht::iterator it = accelerator.path.begin(); it != accelerator.path.end(); ++it) { if (it->loc->is_assign() || it->loc->is_decl()) { assigns.push_back(*(it->loc)); } } for (expr_sett::iterator it = dirty.begin(); it != dirty.end(); ++it) { #ifdef DEBUG std::cout << "Trying to accelerate " << expr2c(*it, ns) << std::endl; #endif if (it->type().id() == ID_bool) { // Hack: don't try to accelerate booleans. accelerator.dirty_vars.insert(*it); #ifdef DEBUG std::cout << "Ignoring boolean" << std::endl; #endif continue; } if (it->id() == ID_index || it->id() == ID_dereference) { #ifdef DEBUG std::cout << "Ignoring array reference" << std::endl; #endif continue; } if (accelerator.changed_vars.find(*it) != accelerator.changed_vars.end()) { // We've accelerated variable this already. #ifdef DEBUG std::cout << "We've accelerated it already" << std::endl; #endif continue; } // Hack: ignore variables that depend on array values.. exprt array_rhs; if (depends_on_array(*it, array_rhs)) { #ifdef DEBUG std::cout << "Ignoring because it depends on an array" << std::endl; #endif continue; } polynomialt poly; exprt target(*it); if (path_acceleration.fit_polynomial(assigns, target, poly)) { std::map<exprt, polynomialt> this_poly; this_poly[target] = poly; if (utils.check_inductive(this_poly, accelerator.path)) { polynomials[target] = poly; accelerator.changed_vars.insert(target); continue; } } #ifdef DEBUG std::cout << "Failed to accelerate " << expr2c(*it, ns) << std::endl; #endif // We weren't able to accelerate this target... accelerator.dirty_vars.insert(target); } /* if (!utils.check_inductive(polynomials, assigns)) { // They're not inductive :-( return false; } */ substitutiont stashed; utils.stash_polynomials(program, polynomials, stashed, path); exprt guard; bool path_is_monotone; try { path_is_monotone = utils.do_assumptions(polynomials, path, guard); } catch (std::string s) { // Couldn't do WP. std::cout << "Assumptions error: " << s << std::endl; return false; } exprt pre_guard(guard); for (std::map<exprt, polynomialt>::iterator it = polynomials.begin(); it != polynomials.end(); ++it) { replace_expr(it->first, it->second.to_expr(), guard); } if (path_is_monotone) { // OK cool -- the path is monotone, so we can just assume the condition for // the last iteration. replace_expr(loop_counter, minus_exprt(loop_counter, from_integer(1, loop_counter.type())), guard); } else { // The path is not monotone, so we need to introduce a quantifier to ensure // that the condition held for all 0 <= k < n. symbolt k_sym = utils.fresh_symbol("polynomial::k", unsigned_poly_type()); exprt k = k_sym.symbol_expr(); exprt k_bound = and_exprt(binary_relation_exprt(from_integer(0, k.type()), "<=", k), binary_relation_exprt(k, "<", loop_counter)); replace_expr(loop_counter, k, guard); simplify(guard, ns); implies_exprt implies(k_bound, guard); exprt forall(ID_forall); forall.type() = bool_typet(); forall.copy_to_operands(k); forall.copy_to_operands(implies); guard = forall; } // All our conditions are met -- we can finally build the accelerator! // It is of the form: // // loop_counter = *; // target1 = polynomial1; // target2 = polynomial2; // ... // assume(guard); // assume(no overflows in previous code); program.add_instruction(ASSUME)->guard = pre_guard; program.assign(loop_counter, side_effect_expr_nondett(loop_counter.type())); for (std::map<exprt, polynomialt>::iterator it = polynomials.begin(); it != polynomials.end(); ++it) { program.assign(it->first, it->second.to_expr()); accelerator.changed_vars.insert(it->first); } // Add in any array assignments we can do now. if (!utils.do_arrays(assigns, polynomials, loop_counter, stashed, program)) { // We couldn't model some of the array assignments with polynomials... // Unfortunately that means we just have to bail out. return false; } program.add_instruction(ASSUME)->guard = guard; program.fix_types(); if (path_is_monotone) { utils.ensure_no_overflows(program); } accelerator.pure_accelerator.instructions.swap(program.instructions); return true; }
inline bool AreEquivalent(expr left, expr right, expr assumption) { return eq(left, right) || IsValid(implies(assumption, left == right)); }
static int implies(Node *a, Node *b) { return (isequal(a,b) || b->ntyp == TRUE || a->ntyp == FALSE || (b->ntyp == AND && implies(a, b->lft) && implies(a, b->rgt)) || (a->ntyp == OR && implies(a->lft, b) && implies(a->rgt, b)) || (a->ntyp == AND && (implies(a->lft, b) || implies(a->rgt, b))) || (b->ntyp == OR && (implies(a, b->lft) || implies(a, b->rgt))) || (b->ntyp == U_OPER && implies(a, b->rgt)) || (a->ntyp == V_OPER && implies(a->rgt, b)) || (a->ntyp == U_OPER && implies(a->lft, b) && implies(a->rgt, b)) || (b->ntyp == V_OPER && implies(a, b->lft) && implies(a, b->rgt)) || ((a->ntyp == U_OPER || a->ntyp == V_OPER) && a->ntyp == b->ntyp && implies(a->lft, b->lft) && implies(a->rgt, b->rgt)) #ifdef NXT || (b->ntyp == NEXT && is_G(a) && implies(a, b->lft)) || (a->ntyp == NEXT && is_F(b) && implies(a->lft, b)) || (a->ntyp == NEXT && b->ntyp == NEXT && implies(a->lft, b->lft))); #else );
// ghb = guarded hb z3::expr encoding::mk_ghbs( const se_ptr& before, const se_ptr& after ) { z3::expr cond = before->guard && after->guard; cond = cond.simplify(); return implies( cond, mk_hbs( before, after ) ); }
z3::expr encoding::mk_ghb_c11_sc( const se_ptr& before, const se_ptr& after ) { return implies( before->guard && after->guard, mk_hb_c11_sc( before, after )); }
static void Delay_pstate_render_mixed( Device_state* dstate, const Work_buffers* wbs, int32_t buf_start, int32_t buf_stop, double tempo) { assert(dstate != NULL); assert(wbs != NULL); assert(buf_start <= buf_stop); assert(tempo > 0); Delay_pstate* dpstate = (Delay_pstate*)dstate; const Proc_delay* delay = (const Proc_delay*)dstate->device->dimpl; float* in_data[2] = { NULL }; Proc_state_get_mixed_audio_in_buffers( &dpstate->parent, PORT_IN_AUDIO_L, PORT_IN_AUDIO_COUNT, in_data); float* out_data[2] = { NULL }; Proc_state_get_mixed_audio_out_buffers( &dpstate->parent, PORT_OUT_AUDIO_L, PORT_OUT_COUNT, out_data); float* history_data[] = { Work_buffer_get_contents_mut(dpstate->bufs[0]), Work_buffer_get_contents_mut(dpstate->bufs[1]), }; const int32_t delay_buf_size = Work_buffer_get_size(dpstate->bufs[0]); assert(delay_buf_size == Work_buffer_get_size(dpstate->bufs[1])); const int32_t delay_max = delay_buf_size - 1; static const int DELAY_WORK_BUFFER_TOTAL_OFFSETS = WORK_BUFFER_IMPL_1; static const int DELAY_WORK_BUFFER_FIXED_DELAY = WORK_BUFFER_IMPL_2; float* total_offsets = Work_buffers_get_buffer_contents_mut( wbs, DELAY_WORK_BUFFER_TOTAL_OFFSETS); // Get delay stream float* delays = Device_state_get_audio_buffer_contents_mut( dstate, DEVICE_PORT_TYPE_RECEIVE, PORT_IN_DELAY); if (delays == NULL) { delays = Work_buffers_get_buffer_contents_mut(wbs, DELAY_WORK_BUFFER_FIXED_DELAY); const float init_delay = delay->init_delay; for (int32_t i = buf_start; i < buf_stop; ++i) delays[i] = init_delay; } int32_t cur_dpstate_buf_pos = dpstate->buf_pos; const int32_t audio_rate = dstate->audio_rate; // Get total offsets for (int32_t i = buf_start, chunk_offset = 0; i < buf_stop; ++i, ++chunk_offset) { const float delay = delays[i]; float delay_frames = delay * audio_rate; delay_frames = clamp(delay_frames, 0, delay_max); total_offsets[i] = chunk_offset - delay_frames; } for (int ch = 0; ch < 2; ++ch) { const float* in = in_data[ch]; float* out = out_data[ch]; if ((in == NULL) || (out == NULL)) continue; const float* history = history_data[ch]; assert(history != NULL); for (int32_t i = buf_start; i < buf_stop; ++i) { const float total_offset = total_offsets[i]; // Get buffer positions const int32_t cur_pos = (int32_t)floor(total_offset); const double remainder = total_offset - cur_pos; assert(cur_pos <= (int32_t)i); assert(implies(cur_pos == (int32_t)i, remainder == 0)); const int32_t next_pos = cur_pos + 1; // Get audio frames double cur_val = 0; double next_val = 0; if (cur_pos >= 0) { const int32_t in_cur_pos = buf_start + cur_pos; assert(in_cur_pos < (int32_t)buf_stop); cur_val = in[in_cur_pos]; const int32_t in_next_pos = min(buf_start + next_pos, i); assert(in_next_pos < (int32_t)buf_stop); next_val = in[in_next_pos]; } else { const int32_t cur_delay_buf_pos = (cur_dpstate_buf_pos + cur_pos + delay_buf_size) % delay_buf_size; assert(cur_delay_buf_pos >= 0); cur_val = history[cur_delay_buf_pos]; if (next_pos < 0) { const int32_t next_delay_buf_pos = (cur_dpstate_buf_pos + next_pos + delay_buf_size) % delay_buf_size; assert(next_delay_buf_pos >= 0); next_val = history[next_delay_buf_pos]; } else { assert(next_pos == 0); next_val = in[buf_start]; } } // Create output frame const double prev_scale = 1 - remainder; const float val = (prev_scale * cur_val) + (remainder * next_val); out[i] = val; } } // Update the delay state buffers for (int ch = 0; ch < 2; ++ch) { const float* in = in_data[ch]; if (in == NULL) continue; float* history = history_data[ch]; assert(history != NULL); cur_dpstate_buf_pos = dpstate->buf_pos; for (int32_t i = buf_start; i < buf_stop; ++i) { history[cur_dpstate_buf_pos] = in[i]; ++cur_dpstate_buf_pos; if (cur_dpstate_buf_pos >= delay_buf_size) { assert(cur_dpstate_buf_pos == delay_buf_size); cur_dpstate_buf_pos = 0; } } } dpstate->buf_pos = cur_dpstate_buf_pos; return; }
void Problem:: quickRedKill(int computeGist) { int e, e2, e3, i, j, k; coef_t a, alpha1, alpha2; coef_t c = 0; int isDead[maxmaxGEQs]; int deadCount = 0; unsigned int P[maxmaxGEQs], Z[maxmaxGEQs], N[maxmaxGEQs]; unsigned int PP, PZ, PN; /* possible Positives, possible zeros & possible negatives */ unsigned int MZ; /* must zeros */ if (DBUG) { fprintf(outputFile, "in quickRedKill: [\n"); printProblem(); }; noteEssential(0); int moreToDo = chainKill(1,0); #ifdef NDEBUG if (!moreToDo) { if (DBUG) fprintf(outputFile, "] quickRedKill\n"); return; }; #endif int equationsToKill = 0; for (e = nGEQs - 1; e >= 0; e--) { int tmp = 1; isDead[e] = 0; P[e] = Z[e] = N[e] = 0; if (GEQs[e].color && !GEQs[e].essential) equationsToKill++; if (GEQs[e].color && GEQs[e].essential && !computeGist) if (!moreToDo) { if (DBUG) fprintf(outputFile, "] quickRedKill\n"); return; }; for (i = nVars; i >= 1; i--) { if (GEQs[e].coef[i] > 0) P[e] |= tmp; else if (GEQs[e].coef[i] < 0) N[e] |= tmp; else Z[e] |= tmp; tmp <<= 1; } } if (!equationsToKill) if (!moreToDo) { if (DBUG) fprintf(outputFile, "] quickRedKill\n"); return; }; for (e = nGEQs - 1; e >= 0; e--) if (!isDead[e]) for (e2 = e - 1; e2 >= 0; e2--) if (!isDead[e2]) { a = 0; for (i = nVars; i > 1; i--) { for (j = i - 1; j > 0; j--) { a = (GEQs[e].coef[i] * GEQs[e2].coef[j] - GEQs[e2].coef[i] * GEQs[e].coef[j]); if (a != 0) goto foundPair; }; }; continue; foundPair: if (DEBUG) { fprintf(outputFile, "found two equations to combine, i = %s, ", variable(i)); fprintf(outputFile, "j = %s, alpha = " coef_fmt "\n", variable(j), a); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n"); }; MZ = (Z[e] & Z[e2]); PZ = MZ | (P[e] & N[e2]) | (N[e] & P[e2]); PP = P[e] | P[e2]; PN = N[e] | N[e2]; for (e3 = nGEQs - 1; e3 >= 0; e3--) if (GEQs[e3].color && !GEQs[e3].essential) { coef_t alpha3; if (!implies(Z[e3], PZ) || implies(~Z[e3], MZ)) continue; if (!implies(P[e3], PP) | !implies(N[e3], PN)) continue; if (a > 0) { alpha1 = GEQs[e2].coef[j] * GEQs[e3].coef[i] - GEQs[e2].coef[i] * GEQs[e3].coef[j]; alpha2 = -(GEQs[e].coef[j] * GEQs[e3].coef[i] - GEQs[e].coef[i] * GEQs[e3].coef[j]); alpha3 = a; } else { alpha1 = -(GEQs[e2].coef[j] * GEQs[e3].coef[i] - GEQs[e2].coef[i] * GEQs[e3].coef[j]); alpha2 = -(-(GEQs[e].coef[j] * GEQs[e3].coef[i] - GEQs[e].coef[i] * GEQs[e3].coef[j])); alpha3 = -a; } if (alpha1 > 0 && alpha2 > 0) { if (DEBUG) { fprintf(outputFile, "alpha1 = " coef_fmt ", alpha2 = " coef_fmt "; comparing against: ", alpha1, alpha2); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n"); }; for (k = nVars; k >= 0; k--) { c = alpha1 * GEQs[e].coef[k] + alpha2 * GEQs[e2].coef[k]; if (DEBUG) { if (k>0) fprintf(outputFile, " %s: " coef_fmt ", " coef_fmt "\n", variable(k), c, alpha3 * GEQs[e3].coef[k]); else fprintf(outputFile, " constant: " coef_fmt ", " coef_fmt "\n", c, alpha3 * GEQs[e3].coef[k]); } if (c != alpha3 * GEQs[e3].coef[k]) break; }; if (k < 0 || (k == 0 && c < alpha3 * (GEQs[e3].coef[k]+1))) { if (DEBUG) { deadCount++; fprintf(outputFile, "red equation#%d is dead (%d dead so far, %d remain)\n", e3, deadCount, nGEQs - deadCount); printGEQ(&(GEQs[e])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e2])); fprintf(outputFile, "\n"); printGEQ(&(GEQs[e3])); fprintf(outputFile, "\n"); assert(moreToDo); }; isDead[e3] = 1; }; }; }; }; for (e = nGEQs - 1; e >= 0; e--) if (isDead[e]) deleteGEQ(e); if (DBUG) { fprintf(outputFile,"] quickRedKill\n"); printProblem(); }; }
static int implies(Node *a, Node *b) { return (isequal(a,b) || b->ntyp == TRUE || a->ntyp == FALSE || (b->ntyp == AND && implies(a, b->lft) && implies(a, b->rgt)) || (a->ntyp == OR && implies(a->lft, b) && implies(a->rgt, b)) || (a->ntyp == AND && (implies(a->lft, b) || implies(a->rgt, b))) || (b->ntyp == OR && (implies(a, b->lft) || implies(a, b->rgt))) || (b->ntyp == U_OPER && implies(a, b->rgt)) || (a->ntyp == V_OPER && implies(a->rgt, b)) || (a->ntyp == U_OPER && implies(a->lft, b) && implies(a->rgt, b)) || (b->ntyp == V_OPER && implies(a, b->lft) && implies(a, b->rgt)) || ((a->ntyp == U_OPER || a->ntyp == V_OPER) && a->ntyp == b->ntyp && implies(a->lft, b->lft) && implies(a->rgt, b->rgt))); }
static Node *bin_simpler(Node *ptr) { Node *a, *b; if (ptr) switch (ptr->ntyp) { case U_OPER: if (ptr->rgt->ntyp == TRUE || ptr->rgt->ntyp == FALSE || ptr->lft->ntyp == FALSE) { ptr = ptr->rgt; break; } if (implies(ptr->lft, ptr->rgt)) /* NEW */ { ptr = ptr->rgt; break; } if (ptr->lft->ntyp == U_OPER && isequal(ptr->lft->lft, ptr->rgt)) { /* (p U q) U p = (q U p) */ ptr->lft = ptr->lft->rgt; break; } if (ptr->rgt->ntyp == U_OPER && implies(ptr->lft, ptr->rgt->lft)) { /* NEW */ ptr = ptr->rgt; break; } /* X p U X q == X (p U q) */ if (ptr->rgt->ntyp == NEXT && ptr->lft->ntyp == NEXT) { ptr = tl_nn(NEXT, tl_nn(U_OPER, ptr->lft->lft, ptr->rgt->lft), ZN); break; } /* NEW : F X p == X F p */ if (ptr->lft->ntyp == TRUE && ptr->rgt->ntyp == NEXT) { ptr = tl_nn(NEXT, tl_nn(U_OPER, True, ptr->rgt->lft), ZN); break; } /* NEW : F G F p == G F p */ if (ptr->lft->ntyp == TRUE && ptr->rgt->ntyp == V_OPER && ptr->rgt->lft->ntyp == FALSE && ptr->rgt->rgt->ntyp == U_OPER && ptr->rgt->rgt->lft->ntyp == TRUE) { ptr = ptr->rgt; break; } /* NEW */ if (ptr->lft->ntyp != TRUE && implies(push_negation(tl_nn(NOT, dupnode(ptr->rgt), ZN)), ptr->lft)) { ptr->lft = True; break; } break; case V_OPER: if (ptr->rgt->ntyp == FALSE || ptr->rgt->ntyp == TRUE || ptr->lft->ntyp == TRUE) { ptr = ptr->rgt; break; } if (implies(ptr->rgt, ptr->lft)) { /* p V p = p */ ptr = ptr->rgt; break; } /* F V (p V q) == F V q */ if (ptr->lft->ntyp == FALSE && ptr->rgt->ntyp == V_OPER) { ptr->rgt = ptr->rgt->rgt; break; } /* NEW : G X p == X G p */ if (ptr->lft->ntyp == FALSE && ptr->rgt->ntyp == NEXT) { ptr = tl_nn(NEXT, tl_nn(V_OPER, False, ptr->rgt->lft), ZN); break; } /* NEW : G F G p == F G p */ if (ptr->lft->ntyp == FALSE && ptr->rgt->ntyp == U_OPER && ptr->rgt->lft->ntyp == TRUE && ptr->rgt->rgt->ntyp == V_OPER && ptr->rgt->rgt->lft->ntyp == FALSE) { ptr = ptr->rgt; break; } /* NEW */ if (ptr->rgt->ntyp == V_OPER && implies(ptr->rgt->lft, ptr->lft)) { ptr = ptr->rgt; break; } /* NEW */ if (ptr->lft->ntyp != FALSE && implies(ptr->lft, push_negation(tl_nn(NOT, dupnode(ptr->rgt), ZN)))) { ptr->lft = False; break; } break; case NEXT: /* NEW : X G F p == G F p */ if (ptr->lft->ntyp == V_OPER && ptr->lft->lft->ntyp == FALSE && ptr->lft->rgt->ntyp == U_OPER && ptr->lft->rgt->lft->ntyp == TRUE) { ptr = ptr->lft; break; } /* NEW : X F G p == F G p */ if (ptr->lft->ntyp == U_OPER && ptr->lft->lft->ntyp == TRUE && ptr->lft->rgt->ntyp == V_OPER && ptr->lft->rgt->lft->ntyp == FALSE) { ptr = ptr->lft; break; } break; case IMPLIES: if (implies(ptr->lft, ptr->rgt)) { ptr = True; break; } ptr = tl_nn(OR, Not(ptr->lft), ptr->rgt); ptr = rewrite(ptr); break; case EQUIV: if (implies(ptr->lft, ptr->rgt) && implies(ptr->rgt, ptr->lft)) { ptr = True; break; } a = rewrite(tl_nn(AND, dupnode(ptr->lft), dupnode(ptr->rgt))); b = rewrite(tl_nn(AND, Not(ptr->lft), Not(ptr->rgt))); ptr = tl_nn(OR, a, b); ptr = rewrite(ptr); break; case AND: /* p && (q U p) = p */ if (ptr->rgt->ntyp == U_OPER && isequal(ptr->rgt->rgt, ptr->lft)) { ptr = ptr->lft; break; } if (ptr->lft->ntyp == U_OPER && isequal(ptr->lft->rgt, ptr->rgt)) { ptr = ptr->rgt; break; } /* p && (q V p) == q V p */ if (ptr->rgt->ntyp == V_OPER && isequal(ptr->rgt->rgt, ptr->lft)) { ptr = ptr->rgt; break; } if (ptr->lft->ntyp == V_OPER && isequal(ptr->lft->rgt, ptr->rgt)) { ptr = ptr->lft; break; } /* (p U q) && (r U q) = (p && r) U q*/ if (ptr->rgt->ntyp == U_OPER && ptr->lft->ntyp == U_OPER && isequal(ptr->rgt->rgt, ptr->lft->rgt)) { ptr = tl_nn(U_OPER, tl_nn(AND, ptr->lft->lft, ptr->rgt->lft), ptr->lft->rgt); break; } /* (p V q) && (p V r) = p V (q && r) */ if (ptr->rgt->ntyp == V_OPER && ptr->lft->ntyp == V_OPER && isequal(ptr->rgt->lft, ptr->lft->lft)) { ptr = tl_nn(V_OPER, ptr->rgt->lft, tl_nn(AND, ptr->lft->rgt, ptr->rgt->rgt)); break; } /* X p && X q == X (p && q) */ if (ptr->rgt->ntyp == NEXT && ptr->lft->ntyp == NEXT) { ptr = tl_nn(NEXT, tl_nn(AND, ptr->rgt->lft, ptr->lft->lft), ZN); break; } /* (p V q) && (r U q) == p V q */ if (ptr->rgt->ntyp == U_OPER && ptr->lft->ntyp == V_OPER && isequal(ptr->lft->rgt, ptr->rgt->rgt)) { ptr = ptr->lft; break; } if (isequal(ptr->lft, ptr->rgt) /* (p && p) == p */ || ptr->rgt->ntyp == FALSE /* (p && F) == F */ || ptr->lft->ntyp == TRUE /* (T && p) == p */ || implies(ptr->rgt, ptr->lft))/* NEW */ { ptr = ptr->rgt; break; } if (ptr->rgt->ntyp == TRUE /* (p && T) == p */ || ptr->lft->ntyp == FALSE /* (F && p) == F */ || implies(ptr->lft, ptr->rgt))/* NEW */ { ptr = ptr->lft; break; } /* NEW : F G p && F G q == F G (p && q) */ if (ptr->lft->ntyp == U_OPER && ptr->lft->lft->ntyp == TRUE && ptr->lft->rgt->ntyp == V_OPER && ptr->lft->rgt->lft->ntyp == FALSE && ptr->rgt->ntyp == U_OPER && ptr->rgt->lft->ntyp == TRUE && ptr->rgt->rgt->ntyp == V_OPER && ptr->rgt->rgt->lft->ntyp == FALSE) { ptr = tl_nn(U_OPER, True, tl_nn(V_OPER, False, tl_nn(AND, ptr->lft->rgt->rgt, ptr->rgt->rgt->rgt))); break; } /* NEW */ if (implies(ptr->lft, push_negation(tl_nn(NOT, dupnode(ptr->rgt), ZN))) || implies(ptr->rgt, push_negation(tl_nn(NOT, dupnode(ptr->lft), ZN)))) { ptr = False; break; } break; case OR: /* p || (q U p) == q U p */ if (ptr->rgt->ntyp == U_OPER && isequal(ptr->rgt->rgt, ptr->lft)) { ptr = ptr->rgt; break; } /* p || (q V p) == p */ if (ptr->rgt->ntyp == V_OPER && isequal(ptr->rgt->rgt, ptr->lft)) { ptr = ptr->lft; break; } /* (p U q) || (p U r) = p U (q || r) */ if (ptr->rgt->ntyp == U_OPER && ptr->lft->ntyp == U_OPER && isequal(ptr->rgt->lft, ptr->lft->lft)) { ptr = tl_nn(U_OPER, ptr->rgt->lft, tl_nn(OR, ptr->lft->rgt, ptr->rgt->rgt)); break; } if (isequal(ptr->lft, ptr->rgt) /* (p || p) == p */ || ptr->rgt->ntyp == FALSE /* (p || F) == p */ || ptr->lft->ntyp == TRUE /* (T || p) == T */ || implies(ptr->rgt, ptr->lft))/* NEW */ { ptr = ptr->lft; break; } if (ptr->rgt->ntyp == TRUE /* (p || T) == T */ || ptr->lft->ntyp == FALSE /* (F || p) == p */ || implies(ptr->lft, ptr->rgt))/* NEW */ { ptr = ptr->rgt; break; } /* (p V q) || (r V q) = (p || r) V q */ if (ptr->rgt->ntyp == V_OPER && ptr->lft->ntyp == V_OPER && isequal(ptr->lft->rgt, ptr->rgt->rgt)) { ptr = tl_nn(V_OPER, tl_nn(OR, ptr->lft->lft, ptr->rgt->lft), ptr->rgt->rgt); break; } /* (p V q) || (r U q) == r U q */ if (ptr->rgt->ntyp == U_OPER && ptr->lft->ntyp == V_OPER && isequal(ptr->lft->rgt, ptr->rgt->rgt)) { ptr = ptr->rgt; break; } /* NEW : G F p || G F q == G F (p || q) */ if (ptr->lft->ntyp == V_OPER && ptr->lft->lft->ntyp == FALSE && ptr->lft->rgt->ntyp == U_OPER && ptr->lft->rgt->lft->ntyp == TRUE && ptr->rgt->ntyp == V_OPER && ptr->rgt->lft->ntyp == FALSE && ptr->rgt->rgt->ntyp == U_OPER && ptr->rgt->rgt->lft->ntyp == TRUE) { ptr = tl_nn(V_OPER, False, tl_nn(U_OPER, True, tl_nn(OR, ptr->lft->rgt->rgt, ptr->rgt->rgt->rgt))); break; } /* NEW */ if (implies(push_negation(tl_nn(NOT, dupnode(ptr->rgt), ZN)), ptr->lft) || implies(push_negation(tl_nn(NOT, dupnode(ptr->lft), ZN)), ptr->rgt)) { ptr = True; break; } break; } return ptr; }
bool polynomial_acceleratort::accelerate(patht &loop, path_acceleratort &accelerator) { goto_programt::instructionst body; accelerator.clear(); for (patht::iterator it = loop.begin(); it != loop.end(); ++it) { body.push_back(*(it->loc)); } expr_sett targets; std::map<exprt, polynomialt> polynomials; scratch_programt program(symbol_table); goto_programt::instructionst assigns; utils.find_modified(body, targets); #ifdef DEBUG std::cout << "Polynomial accelerating program:" << std::endl; for (goto_programt::instructionst::iterator it = body.begin(); it != body.end(); ++it) { program.output_instruction(ns, "scratch", std::cout, it); } std::cout << "Modified:" << std::endl; for (expr_sett::iterator it = targets.begin(); it != targets.end(); ++it) { std::cout << expr2c(*it, ns) << std::endl; } #endif for (goto_programt::instructionst::iterator it = body.begin(); it != body.end(); ++it) { if (it->is_assign() || it->is_decl()) { assigns.push_back(*it); } } if (loop_counter.is_nil()) { symbolt loop_sym = utils.fresh_symbol("polynomial::loop_counter", unsignedbv_typet(POLY_WIDTH)); loop_counter = loop_sym.symbol_expr(); } for (expr_sett::iterator it = targets.begin(); it != targets.end(); ++it) { polynomialt poly; exprt target = *it; expr_sett influence; goto_programt::instructionst sliced_assigns; if (target.type() == bool_typet()) { // Hack: don't accelerate booleans. continue; } cone_of_influence(assigns, target, sliced_assigns, influence); if (influence.find(target) == influence.end()) { #ifdef DEBUG std::cout << "Found nonrecursive expression: " << expr2c(target, ns) << std::endl; #endif nonrecursive.insert(target); continue; } if (target.id() == ID_index || target.id() == ID_dereference) { // We can't accelerate a recursive indirect access... accelerator.dirty_vars.insert(target); continue; } if (fit_polynomial_sliced(sliced_assigns, target, influence, poly)) { std::map<exprt, polynomialt> this_poly; this_poly[target] = poly; if (check_inductive(this_poly, assigns)) { polynomials.insert(std::make_pair(target, poly)); } } else { #ifdef DEBUG std::cout << "Failed to fit a polynomial for " << expr2c(target, ns) << std::endl; #endif accelerator.dirty_vars.insert(*it); } } if (polynomials.empty()) { //return false; } /* if (!utils.check_inductive(polynomials, assigns)) { // They're not inductive :-( return false; } */ substitutiont stashed; stash_polynomials(program, polynomials, stashed, body); exprt guard; exprt guard_last; bool path_is_monotone; try { path_is_monotone = utils.do_assumptions(polynomials, loop, guard); } catch (std::string s) { // Couldn't do WP. std::cout << "Assumptions error: " << s << std::endl; return false; } guard_last = guard; for (std::map<exprt, polynomialt>::iterator it = polynomials.begin(); it != polynomials.end(); ++it) { replace_expr(it->first, it->second.to_expr(), guard_last); } if (path_is_monotone) { // OK cool -- the path is monotone, so we can just assume the condition for // the first and last iterations. replace_expr(loop_counter, minus_exprt(loop_counter, from_integer(1, loop_counter.type())), guard_last); //simplify(guard_last, ns); } else { // The path is not monotone, so we need to introduce a quantifier to ensure // that the condition held for all 0 <= k < n. symbolt k_sym = utils.fresh_symbol("polynomial::k", unsignedbv_typet(POLY_WIDTH)); exprt k = k_sym.symbol_expr(); exprt k_bound = and_exprt(binary_relation_exprt(from_integer(0, k.type()), "<=", k), binary_relation_exprt(k, "<", loop_counter)); replace_expr(loop_counter, k, guard_last); implies_exprt implies(k_bound, guard_last); //simplify(implies, ns); exprt forall(ID_forall); forall.type() = bool_typet(); forall.copy_to_operands(k); forall.copy_to_operands(implies); guard_last = forall; } // All our conditions are met -- we can finally build the accelerator! // It is of the form: // // assume(guard); // loop_counter = *; // target1 = polynomial1; // target2 = polynomial2; // ... // assume(guard); // assume(no overflows in previous code); program.add_instruction(ASSUME)->guard = guard; program.assign(loop_counter, side_effect_expr_nondett(loop_counter.type())); for (std::map<exprt, polynomialt>::iterator it = polynomials.begin(); it != polynomials.end(); ++it) { program.assign(it->first, it->second.to_expr()); } // Add in any array assignments we can do now. if (!utils.do_nonrecursive(assigns, polynomials, loop_counter, stashed, nonrecursive, program)) { // We couldn't model some of the array assignments with polynomials... // Unfortunately that means we just have to bail out. #ifdef DEBUG std::cout << "Failed to accelerate a nonrecursive expression" << std::endl; #endif return false; } program.add_instruction(ASSUME)->guard = guard_last; program.fix_types(); if (path_is_monotone) { utils.ensure_no_overflows(program); } accelerator.pure_accelerator.instructions.swap(program.instructions); return true; }
/* main method */ void solver_type:: calc_next ( input_params_type const & input_params , sheet_params_type const & sheet_params ) // Instead of dealing with sheet_type this could start with these src/trg objects: // stride_range< src_iter_type, 1 > src_range // stride_range< trg_iter_type, 1 > trg_range // See swap_xy( range_xy) -> range_yx { // Initialize the output params. We will set them as we go along. output_params_.reset( ); sheet_type const & src_sheet = sheet_params.ref_src_sheet( ); sheet_type & trg_sheet = sheet_params.ref_trg_sheet( ); sheet_type & extra_sheet = sheet_params.ref_extra_sheet( ); // Interpret input_params and sheet_params as intuitive choices. bool const is_multi_pass = input_params.has_extra_passes( ) && ! input_params.are_extra_passes_disabled( ); bool const is_one_pass = ! is_multi_pass; bool const is_in_place_requested = sheet_params.are_src_trg_sheets_same( ); bool const is_in_place_possible = input_params.is_technique__ortho_interleave( ); bool const is_extra_pre_sized = sheet_params.is_extra_sheet_sized( ); bool const is_history_vital = input_params.is_saving_history_worth_sizing_extra( ); bool const is_history_nice = is_history_vital || input_params.is_saving_history_worth_extra_copy( ); bool const is_extra_vital_for_solve = is_multi_pass && ! is_in_place_possible; /* or is_in_place_requested and not possible */ bool const is_extra_vital_for_history = is_multi_pass || is_in_place_requested; bool const is_extra_vital = is_extra_vital_for_solve || (is_history_vital && is_extra_vital_for_history); bool const is_extra_nice = is_extra_vital || (is_history_nice && is_extra_vital_for_history); bool const is_extra_used = is_extra_vital || (is_extra_nice && is_extra_pre_sized); // The two sheets must be different (unless technique == e_ortho_interleave). // We could make in_place work for e_simultaneous_2d too (but not for e_wave_with_damping) // by using extra_sheet like this (one pass): // copy src -> extra // solve extra -> trg // For two passes: // solve src -> extra // solve extra -> trg // Three passes: // copy src -> extra // solve extra -> trg // solve trg -> extra // solve extra -> trg // In this scenario, extra_sheet always ends up with history. d_assert( implies( is_in_place_requested, is_in_place_possible)); if ( is_extra_vital && ! is_extra_pre_sized ) { // We need an extra trg sheet. Make sure it's properly sized. d_verify( sheet_params.maybe_size_extra_sheet( )); output_params_.set__was_extra_sized( ); } if ( is_extra_used ) { // Even if extra_sheet wasn't pre-sized, it's sized now. d_assert( sheet_params.is_extra_sheet_sized( )); output_params_.set__was_extra_used( ); } else if ( input_params.is_extra_sheet_to_be_reset_if_not_used( ) ) { extra_sheet.reset( ); } // If we are solving the wave equation using the extra sheet we have to set up history. // // We need the following assumtion because we are testing is_odd( extra_pass_count): // d_assert( extra_pass_count >= 0) // This is always true because size_type is unsigned. d_static_assert( boost::is_unsigned< size_type >::value); if ( is_multi_pass && input_params.is_technique__wave_with_damping( ) ) { d_assert( is_extra_used); if ( is_early_exit( ) ) return; // If we are wave solving we need to setup the extra sheet with values so we get // the history right. Remember with waves we have a kludge where trg_sheet also // holds the src-values from one generation back. if ( util::is_odd( input_params.get_extra_pass_count( )) ) { // If extra_pass_count is odd the solves will look like: // src -> extra -- first set (extra <- trg) so history is right // extra -> trg -- first set (trg <- src) so history is right // trg -> extra -- ok // extra -> trg -- ok extra_sheet = trg_sheet; trg_sheet = src_sheet; } else { // If extra_pass_count is even (and not zero) the solves look like this: // src -> trg -- ok // trg -> extra -- first set (extra <- src) so history is right // extra -> trg -- ok // trg -> extra -- ok // extra -> trg -- ok extra_sheet = src_sheet; } } // Solve repeatedly if extra solve passes are requested. // Alternatively solve to trg_sheet and extra_sheet, assuming extra_sheet is available. sheet_type const * p_src_sheet = & src_sheet; for ( size_type countdown = is_multi_pass ? input_params.get_extra_pass_count( ) : 0 ; countdown > 0 ; -- countdown ) { if ( is_early_exit( ) ) return; output_params_.inc_solve_count( ); bool const is_this_pass_targeting_extra = is_extra_used && util::is_odd( countdown); sheet_type & trg_sheet_this_pass = is_this_pass_targeting_extra ? extra_sheet : trg_sheet; calc_next_pass ( input_params.get_technique( ) , input_params.get_method( ) , input_params.is_method_parallel( ) , input_params.get_damping( ) , input_params.get_rate_x( ) , input_params.get_rate_y( ) , *p_src_sheet , trg_sheet_this_pass ); p_src_sheet = & trg_sheet_this_pass; } // We're about to do the last solve. The 2nd-to-last solution is in *p_src_sheet, which is: // src_sheet if this is not just the last solve, but also the only solve. // extra_sheet if we were using extra_sheet in the loop above. // trg_sheet if in_place solving is possible and history is not required. if ( is_one_pass ) { d_assert( (& src_sheet) == p_src_sheet); if ( is_in_place_requested ) { // There is one unusual case where we have to copy src_sheet to preserve history. if ( is_history_nice && is_extra_used ) { if ( is_early_exit( ) ) return; extra_sheet = src_sheet; output_params_.set__is_last_solve_saved_in_extra( ); } else { /* we are doing one in-place solve */ /* history is not saved */ } } else { output_params_.set__is_last_solve_saved_in_src( ); } } else if ( is_extra_used ) { // Multi-pass and we had the extra sheet available. In that case we always solve into it. // In this case history is always returned in extra_sheet, even if not requested. d_assert( (& extra_sheet) == p_src_sheet); output_params_.set__is_last_solve_saved_in_extra( ); } else { // Multi-pass and we don't have extra_sheet. We must be solving in-place. d_assert( (& trg_sheet) == p_src_sheet); d_assert( is_in_place_possible); d_assert( ! is_history_vital); d_assert( ! (is_history_nice && is_extra_pre_sized)); /* history is not saved */ } // Do the last-pass solve. // For the last pass we always solve into the trg_sheet. if ( is_early_exit( ) ) return; output_params_.inc_solve_count( ); calc_next_pass ( input_params.get_technique( ) , input_params.get_method( ) , input_params.is_method_parallel( ) , input_params.get_damping( ) , input_params.get_rate_x( ) , input_params.get_rate_y( ) , *p_src_sheet , trg_sheet ); }