int /* 0 okay, 1 error */ adj_systime( double now /* adjustment (s) */ ) { struct timeval adjtv; /* new adjustment */ struct timeval oadjtv; /* residual adjustment */ double dtemp; long ticks; int isneg = 0; os_trace("Adjust: %f", now); /* * Most Unix adjtime() implementations adjust the system clock * in microsecond quanta, but some adjust in 10-ms quanta. We * carefully round the adjustment to the nearest quantum, then * adjust in quanta and keep the residue for later. */ dtemp = now + sys_residual; if (dtemp < 0) { isneg = 1; dtemp = -dtemp; } adjtv.tv_sec = (long)dtemp; dtemp -= adjtv.tv_sec; ticks = (long)(dtemp / sys_tick + .5); adjtv.tv_usec = (long)(ticks * sys_tick * 1e6); dtemp -= adjtv.tv_usec / 1e6; sys_residual = dtemp; /* * Convert to signed seconds and microseconds for the Unix * adjtime() system call. Note we purposely lose the adjtime() * leftover. */ if (isneg) { adjtv.tv_sec = -adjtv.tv_sec; adjtv.tv_usec = -adjtv.tv_usec; sys_residual = -sys_residual; } if (adjtv.tv_sec != 0 || adjtv.tv_usec != 0) { if (adjtime(&adjtv, &oadjtv) < 0) { msyslog(LOG_ERR, "adj_systime: %m"); return (0); } } return (1); }
/* * set_freq - set clock frequency */ static void set_freq( double freq /* frequency update */ ) { char tbuf[80]; if (freq != drift_comp) { os_trace("drift PPM:%.3f -> %.3f", drift_comp * 1e6, freq * 1e6); msyslog(LOG_NOTICE, "drift PPM:%.3f -> %.3f", drift_comp * 1e6, freq * 1e6); } drift_comp = freq; #ifdef KERNEL_PLL /* * If the kernel is enabled, update the kernel frequency. */ if (pll_control && kern_enable) { memset(&ntv, 0, sizeof(ntv)); ntv.modes = MOD_FREQUENCY; ntv.freq = DTOFREQ(drift_comp); ntp_adjtime(&ntv); snprintf(tbuf, sizeof(tbuf), "kernel %.3f PPM", drift_comp * 1e6); report_event(EVNT_FSET, NULL, tbuf); } else { snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM", drift_comp * 1e6); report_event(EVNT_FSET, NULL, tbuf); } #else /* KERNEL_PLL */ snprintf(tbuf, sizeof(tbuf), "ntpd %.3f PPM", drift_comp * 1e6); report_event(EVNT_FSET, NULL, tbuf); #endif /* KERNEL_PLL */ }
//============================================================================ double AccountValue::Solve (mcenum_solve_type a_SolveType ,int a_SolveBeginYear ,int a_SolveEndYear ,mcenum_solve_target a_SolveTarget ,double a_SolveTargetCsv ,int a_SolveTargetYear ,mcenum_gen_basis a_SolveGenBasis ,mcenum_sep_basis a_SolveSepBasis ) { SolveBeginYear_ = a_SolveBeginYear; SolveEndYear_ = a_SolveEndYear; SolveTarget_ = a_SolveTarget; SolveTargetCsv_ = a_SolveTargetCsv; SolveTargetDuration_ = a_SolveTargetYear; SolveGenBasis_ = a_SolveGenBasis; SolveSepBasis_ = a_SolveSepBasis; LMI_ASSERT(0 <= SolveBeginYear_); LMI_ASSERT( SolveBeginYear_ <= SolveEndYear_); LMI_ASSERT( SolveEndYear_ <= BasicValues::GetLength()); LMI_ASSERT(0 < SolveTargetDuration_); LMI_ASSERT( SolveTargetDuration_ <= BasicValues::GetLength()); // Defaults: may be overridden by some cases // We aren't interested in negative solve results double lower_bound = 0.0; double upper_bound = 0.0; root_bias bias = mce_solve_for_tax_basis == SolveTarget_ ? bias_lower : bias_higher ; int decimals = 0; // Many things don't plausibly exceed max input face for(int j = 0; j < SolveTargetDuration_; j++) { upper_bound = std::max (upper_bound ,DeathBfts_->specamt()[j] + yare_input_.TermRiderAmount ); } // TODO ?? Wait--initial premium may exceed input face, so // for now we'll bail out with this: no amount solved for can // plausibly reach one billion dollars. upper_bound = 999999999.99; switch(a_SolveType) { case mce_solve_specamt: { // This: // upper_bound = 1000000.0 * Outlay_->GetPmts()[0]; // is not satisfactory; what would be better? solve_set_fn = &AccountValue::SolveSetSpecAmt; decimals = round_specamt().decimals(); // TODO ?? Respect minimum specamt? } break; case mce_solve_ee_prem: { solve_set_fn = &AccountValue::SolveSetEePrem; decimals = round_gross_premium().decimals(); } break; case mce_solve_er_prem: { solve_set_fn = &AccountValue::SolveSetErPrem; decimals = round_gross_premium().decimals(); } break; case mce_solve_loan: { solve_set_fn = &AccountValue::SolveSetLoan; decimals = round_loan().decimals(); } break; case mce_solve_wd: { // TODO ?? Is minimum wd respected? solve_set_fn = &AccountValue::SolveSetWD; decimals = round_withdrawal().decimals(); if(yare_input_.WithdrawToBasisThenLoan) { // Withdrawals and loans might be rounded differently. // To obtain a level income as a mixture of loans and // withdrawals, both should be rounded to the less // precise number of decimals normally used for either. decimals = std::min (round_withdrawal().decimals() ,round_loan ().decimals() ); } } break; default: { fatal_error() << "Case " << a_SolveType << " not found." << LMI_FLUSH ; } } std::ostream os_trace(status().rdbuf()); std::ofstream ofs_trace; if(contains(yare_input_.Comments, "idiosyncrasyT") && !SolvingForGuarPremium) { ofs_trace.open("trace.txt", ios_out_app_binary()); os_trace.rdbuf(ofs_trace.rdbuf()); } SolveHelper solve_helper(*this); root_type solution = decimal_root (lower_bound ,upper_bound ,bias ,decimals ,solve_helper ,false ,os_trace ); if(root_not_bracketed == solution.second) { solution.first = 0.0; // Don't want this firing continually in census runs. if(!SolvingForGuarPremium) { warning() << "Solution not found: using zero instead." << LMI_FLUSH; // TODO ?? What can we do when no solution exists for guar prem? } } // The account and ledger values set as a side effect of solving // aren't necessarily what we need, for two reasons: // - find_root() need not return the last iterand tested; and // - the 'Solving' flag has side effects. // The first issue could be overcome easily enough in find_root(), // but the second cannot. Therefore, the final solve parameters // are stored now, and values are regenerated downstream. Solving = false; (this->*solve_set_fn)(solution.first); return solution.first; }
/* * step_systime - step the system clock. */ int step_systime( double now ) { struct timeval timetv, adjtv, oldtimetv; int isneg = 0; double dtemp; #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) struct timespec ts; #endif os_trace("step: %f", now); dtemp = sys_residual + now; if (dtemp < 0) { isneg = 1; dtemp = - dtemp; adjtv.tv_sec = (int32)dtemp; adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) * 1e6 + .5); } else { adjtv.tv_sec = (int32)dtemp; adjtv.tv_usec = (u_int32)((dtemp - (double)adjtv.tv_sec) * 1e6 + .5); } #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_GETCLOCK) # ifdef HAVE_CLOCK_GETTIME (void) clock_gettime(CLOCK_REALTIME, &ts); # else (void) getclock(TIMEOFDAY, &ts); # endif timetv.tv_sec = ts.tv_sec; timetv.tv_usec = ts.tv_nsec / 1000; #else /* not HAVE_GETCLOCK */ (void) GETTIMEOFDAY(&timetv, (struct timezone *)0); #endif /* not HAVE_GETCLOCK */ oldtimetv = timetv; #ifdef DEBUG if (debug) printf("step_systime: step %.6f residual %.6f\n", now, sys_residual); #endif if (isneg) { timetv.tv_sec -= adjtv.tv_sec; timetv.tv_usec -= adjtv.tv_usec; if (timetv.tv_usec < 0) { timetv.tv_sec--; timetv.tv_usec += 1000000; } } else { timetv.tv_sec += adjtv.tv_sec; timetv.tv_usec += adjtv.tv_usec; if (timetv.tv_usec >= 1000000) { timetv.tv_sec++; timetv.tv_usec -= 1000000; } } if (ntp_set_tod(&timetv, NULL) != 0) { msyslog(LOG_ERR, "step-systime: %m"); return (0); } sys_residual = 0; #ifdef NEED_HPUX_ADJTIME /* * CHECKME: is this correct when called by ntpdate????? */ _clear_adjtime(); #endif /* * FreeBSD, for example, has: * struct utmp { * char ut_line[UT_LINESIZE]; * char ut_name[UT_NAMESIZE]; * char ut_host[UT_HOSTSIZE]; * long ut_time; * }; * and appends line="|", name="date", host="", time for the OLD * and appends line="{", name="date", host="", time for the NEW * to _PATH_WTMP . * * Some OSes have utmp, some have utmpx. */ /* * Write old and new time entries in utmp and wtmp if step * adjustment is greater than one second. * * This might become even Uglier... */ if (oldtimetv.tv_sec != timetv.tv_sec) { #ifdef HAVE_UTMP_H struct utmp ut; #endif #ifdef HAVE_UTMPX_H struct utmpx utx; #endif #ifdef HAVE_UTMP_H memset((char *)&ut, 0, sizeof(ut)); #endif #ifdef HAVE_UTMPX_H memset((char *)&utx, 0, sizeof(utx)); #endif /* UTMP */ #ifdef UPDATE_UTMP # ifdef HAVE_PUTUTLINE ut.ut_type = OLD_TIME; (void)strcpy(ut.ut_line, OTIME_MSG); ut.ut_time = oldtimetv.tv_sec; pututline(&ut); setutent(); ut.ut_type = NEW_TIME; (void)strcpy(ut.ut_line, NTIME_MSG); ut.ut_time = timetv.tv_sec; pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_UTMP */ /* UTMPX */ #ifdef UPDATE_UTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; (void)strcpy(utx.ut_line, OTIME_MSG); utx.ut_tv = oldtimetv; pututxline(&utx); setutxent(); utx.ut_type = NEW_TIME; (void)strcpy(utx.ut_line, NTIME_MSG); utx.ut_tv = timetv; pututxline(&utx); endutxent(); # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_UTMPX */ /* WTMP */ #ifdef UPDATE_WTMP # ifdef HAVE_PUTUTLINE utmpname(WTMP_FILE); ut.ut_type = OLD_TIME; (void)strcpy(ut.ut_line, OTIME_MSG); ut.ut_time = oldtimetv.tv_sec; pututline(&ut); ut.ut_type = NEW_TIME; (void)strcpy(ut.ut_line, NTIME_MSG); ut.ut_time = timetv.tv_sec; pututline(&ut); endutent(); # else /* not HAVE_PUTUTLINE */ # endif /* not HAVE_PUTUTLINE */ #endif /* UPDATE_WTMP */ /* WTMPX */ #ifdef UPDATE_WTMPX # ifdef HAVE_PUTUTXLINE utx.ut_type = OLD_TIME; utx.ut_tv = oldtimetv; (void)strcpy(utx.ut_line, OTIME_MSG); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ # ifdef HAVE_PUTUTXLINE utx.ut_type = NEW_TIME; utx.ut_tv = timetv; (void)strcpy(utx.ut_line, NTIME_MSG); # ifdef HAVE_UPDWTMPX updwtmpx(WTMPX_FILE, &utx); # else /* not HAVE_UPDWTMPX */ # endif /* not HAVE_UPDWTMPX */ # else /* not HAVE_PUTUTXLINE */ # endif /* not HAVE_PUTUTXLINE */ #endif /* UPDATE_WTMPX */ } return (1); }