/* * Copyright 2008-2012 NVIDIA Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include namespace thrust { namespace random { template subtract_with_carry_engine ::subtract_with_carry_engine(result_type value) { seed(value); } // end subtract_with_carry_engine::subtract_with_carry_engine() template void subtract_with_carry_engine ::seed(result_type value) { thrust::random::linear_congruential_engine e(value == 0u ? default_seed : value); // initialize state for(size_t i = 0; i < long_lag; ++i) { m_x[i] = detail::mod(e()); } // end for i m_carry = (m_x[long_lag-1] == 0); m_k = 0; } // end subtract_with_carry_engine::seed() template typename subtract_with_carry_engine::result_type subtract_with_carry_engine ::operator()(void) { // XXX we probably need to cache these m_x[m_k] in a register // maybe we need to cache the use of all member variables int short_index = m_k - short_lag; if(short_index < 0) short_index += long_lag; result_type xi; if (m_x[short_index] >= m_x[m_k] + m_carry) { // x(n) >= 0 xi = m_x[short_index] - m_x[m_k] - m_carry; m_carry = 0; } else { // x(n) < 0 xi = modulus - m_x[m_k] - m_carry + m_x[short_index]; m_carry = 1; } m_x[m_k] = xi; ++m_k; if(m_k >= long_lag) m_k = 0; return xi; } // end subtract_with_carry_engine::operator()() template void subtract_with_carry_engine ::discard(unsigned long long z) { for(; z > 0; --z) { this->operator()(); } // end for } // end subtract_with_carry_engine::discard() template template std::basic_ostream& subtract_with_carry_engine ::stream_out(std::basic_ostream &os) const { typedef std::basic_ostream ostream_type; typedef typename ostream_type::ios_base ios_base; const typename ios_base::fmtflags flags = os.flags(); const CharT fill = os.fill(); const CharT space = os.widen(' '); os.flags(ios_base::dec | ios_base::fixed | ios_base::left); os.fill(space); const UIntType long_lag = r; for(size_t i = 0; i < r; ++i) os << m_x[(i + m_k) % long_lag] << space; os << m_carry; os.flags(flags); os.fill(fill); return os; } template template std::basic_istream& subtract_with_carry_engine ::stream_in(std::basic_istream &is) { typedef std::basic_istream istream_type; typedef typename istream_type::ios_base ios_base; const typename ios_base::fmtflags flags = is.flags(); is.flags(ios_base::dec | ios_base::skipws); for(size_t i = 0; i < r; ++i) is >> m_x[i]; is >> m_carry; m_k = 0; is.flags(flags); return is; } template bool subtract_with_carry_engine ::equal(const subtract_with_carry_engine &rhs) const { const UIntType long_lag = r; bool result = true; for(size_t i = 0; i < r; ++i) { result &= (m_x[(i + m_k) % long_lag] == rhs.m_x[(i + rhs.m_k) % long_lag]); } // XXX not sure if this last check is necessary result &= (m_carry == rhs.m_carry); return result; } template std::basic_ostream& operator<<(std::basic_ostream &os, const subtract_with_carry_engine &e) { return thrust::random::detail::random_core_access::stream_out(os,e); } template std::basic_istream& operator>>(std::basic_istream &is, subtract_with_carry_engine &e) { return thrust::random::detail::random_core_access::stream_in(is,e); } template bool operator==(const subtract_with_carry_engine &lhs, const subtract_with_carry_engine &rhs) { return thrust::random::detail::random_core_access::equal(lhs,rhs); } template bool operator!=(const subtract_with_carry_engine &lhs, const subtract_with_carry_engine &rhs) { return !(lhs == rhs); } } // end random } // end thrust