File indexing completed on 2024-05-12 16:23:28
0001 /*************************************************************************** 0002 * Copyright (C) 2013 by Linuxstopmotion contributors; * 0003 * see the AUTHORS file for details. * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "random.h" 0022 0023 #include <stdlib.h> 0024 #include <string.h> 0025 #include <assert.h> 0026 0027 namespace { 0028 const char alphanumericCharacters[] = 0029 "04 aqBZ\"'\\\xC3\x91\xC3\xA9"; 0030 } 0031 0032 // This is not thread safe, but could easily be made so 0033 class RandomImpl { 0034 ~RandomImpl() { 0035 if (nextChunk) 0036 nextChunk->delRef(); 0037 nextChunk = 0; 0038 } 0039 RandomImpl() : refCount(1), nextIndex(0), nextChunk(0) { 0040 } 0041 RandomImpl(const RandomImpl&); // unimplemented 0042 RandomImpl& operator=(const RandomImpl&); // unimplemented 0043 enum { 0044 chunkSize = 10 0045 }; 0046 int chunk[chunkSize]; 0047 int refCount; 0048 int nextIndex; 0049 RandomImpl* nextChunk; 0050 public: 0051 static RandomImpl* create() { 0052 return new RandomImpl; 0053 } 0054 void addRef() { 0055 ++refCount; 0056 } 0057 void delRef() { 0058 --refCount; 0059 if (refCount == 0) 0060 delete this; 0061 } 0062 static int get(RandomImpl*& pImpl, int& index) { 0063 if (index == chunkSize) { 0064 if (!pImpl->nextChunk) { 0065 pImpl->nextChunk = create(); 0066 } 0067 RandomImpl* nc = pImpl->nextChunk; 0068 nc->addRef(); 0069 pImpl->delRef(); 0070 pImpl = nc; 0071 index = 0; 0072 } 0073 if (pImpl->nextIndex == index) { 0074 pImpl->chunk[index] = rand(); 0075 ++pImpl->nextIndex; 0076 } 0077 int val = pImpl->chunk[index]; 0078 ++index; 0079 return val; 0080 } 0081 }; 0082 0083 RandomSource::RandomSource() : impl(RandomImpl::create()), index(0) { 0084 } 0085 0086 RandomSource::RandomSource(const RandomSource& other) 0087 : impl(other.impl), index(other.index) { 0088 impl->addRef(); 0089 } 0090 0091 RandomSource::~RandomSource() { 0092 impl->delRef(); 0093 } 0094 0095 RandomSource& RandomSource::operator=(const RandomSource& other) { 0096 other.impl->addRef(); 0097 impl->delRef(); 0098 impl = other.impl; 0099 index = other.index; 0100 return*this; 0101 } 0102 0103 int RandomSource::get() { 0104 return RandomImpl::get(impl, index); 0105 } 0106 0107 int32_t RandomSource::getUniform(int32_t min, int32_t max) { 0108 int64_t r = get(); 0109 return r * (max + 1 - min) / ((int64_t) RAND_MAX + 1) + min; 0110 } 0111 0112 int32_t RandomSource::getUniform(int32_t max) { 0113 return getUniform(0, max); 0114 } 0115 0116 int32_t RandomSource::getLogInt(int32_t p) { 0117 assert(0 < p && p < 100); 0118 int32_t r = 0; 0119 while (getUniform(0,99) < r) { 0120 ++r; 0121 } 0122 return r; 0123 } 0124 0125 void RandomSource::appendString(std::string& out, 0126 const char* characters, bool allowNulls) { 0127 int n = strlen(characters) + (allowNulls? 1 : 0); 0128 while (true) { 0129 int r = getUniform(n); 0130 if (n == r) 0131 return; 0132 out.append(1, characters[r]); 0133 } 0134 } 0135 0136 void RandomSource::appendAlphanumeric(std::string& out) { 0137 appendString(out, alphanumericCharacters, false); 0138 } 0139 0140 char RandomSource::getCharacter() { 0141 int u = getUniform(sizeof(alphanumericCharacters) - 2); 0142 return alphanumericCharacters[u]; 0143 }