1 /* $Id: $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's offical duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================*/
25 
26 /*****************************************************************************
27 
28 File name: njn_dynprogprob.cpp
29 
30 Author: John Spouge
31 
32 Contents:
33 
34 ******************************************************************************/
35 
36 #include <assert.h>
37 
38 #include "njn_dynprogprob.hpp"
39 #include "njn_memutil.hpp"
40 
41 using namespace Njn;
42 
43 
44 const size_t DynProgProb::ARRAY_CAPACITY = 256;
45 
init(size_t arrayCapacity_)46 void DynProgProb::init (size_t arrayCapacity_) // range for d_array_p [0,1][0...arrayCapacity_ - 1]
47 {
48     if (arrayCapacity_ > 0)
49     {
50 	for (size_t i = 0; i < 2; i++)
51 	{
52 	    d_array_p [i] = new double [arrayCapacity_];
53 	    MemUtil::memZero (d_array_p [i], sizeof (double) * arrayCapacity_);
54 	}
55     }
56 
57     d_arrayCapacity = arrayCapacity_;
58 }
59 
free2()60 void DynProgProb::free2 ()
61 {
62     if (getArrayCapacity () > 0)
63     {
64 	for (size_t i = 0; i < 2; i++)
65 	{
66 	    delete [] d_array_p [i]; d_array_p [i] = 0;
67 	}
68     }
69 
70     d_arrayCapacity = 0;
71 }
72 
clear(long int valueBegin_,size_t arrayCapacity_)73 void DynProgProb::clear (
74 long int valueBegin_, // lower limit for long int values in the array (an offset)
75 size_t arrayCapacity_) // new array capacity
76 // resets the computation
77 {
78     free2 ();
79     init (arrayCapacity_);
80     d_valueBegin = valueBegin_;
81     d_step = 0;
82 }
83 
clear(long int valueLower_,long int valueUpper_,const double * prob_)84 void DynProgProb::clear ( // initializes the "probabilities" with non-negative weights
85 long int valueLower_, // lower long int value corresponding to the "probability" array
86 long int valueUpper_, // one beyond present upper long int value corresponding to the "probability" array
87 const double *prob_) // "probabilities" prob [valueLower_, valueUpper_) corresponding to the long ints
88 {
89 	assert ((! prob_ && valueLower_ <= 0 && 0 <= valueUpper_) ||
90 		/*sls added "("*/(prob_ && valueLower_ < valueUpper_)/*sls added ")"*/ );
91 
92     if (prob_)
93     {
94 	for (size_t i = 0; i < static_cast <size_t> (valueUpper_ - valueLower_); i++)
95 	{
96 	    assert (0.0 <= prob_ [i]);
97 	}
98 
99 	clear (valueLower_, static_cast <size_t> (valueUpper_ - valueLower_));
100 
101 	d_valueLower = valueLower_;
102 	d_valueUpper = valueUpper_;
103 	MemUtil::memCpy (d_array_p [0], prob_, sizeof (double) * getArrayCapacity ());
104 
105 	return;
106     }
107 
108     if (valueLower_ == 0 && valueUpper_ == 0)
109     {
110 	clear (-static_cast <long int> (ARRAY_CAPACITY / 2) + 1, ARRAY_CAPACITY);
111     }
112     else
113     {
114 	clear (valueLower_, static_cast <size_t> (valueUpper_ - valueLower_));
115     }
116 
117     d_valueLower = 0;
118     d_valueUpper = 1;
119     d_array_p [0][getArrayPos (0)] = 1.0;
120 
121     return;
122 }
123 
copy(size_t step_,const double * const * array_,size_t arrayCapacity_,long int valueBegin_,long int valueLower_,long int valueUpper_,ValueFct * newStateFct_,size_t dimInputProb_,const double * inputProb_)124 void DynProgProb::copy (
125 size_t step_, // current index : starts at 0
126 const double *const *array_, // two corresponding arrays of probabilities
127 size_t arrayCapacity_, // present capacity of the array
128 long int valueBegin_, // lower limit for long int values in the array (an offset)
129 long int valueLower_, // present lower long int value in the array
130 long int valueUpper_, // one beyond present upper long int value in the array
131 ValueFct *newStateFct_, // function for updating dynamic programming values
132 size_t dimInputProb_,
133 const double *inputProb_) // array of input states : d_inputProb_p [0...dimStateProb - 1]
134 {
135     if (arrayCapacity_ != getArrayCapacity ())
136     {
137 	free2 ();
138 	init (arrayCapacity_);
139     }
140 
141     d_step = step_;
142     for (size_t i = 0; i < 2; i++)
143     {
144 	if (getArrayCapacity () > 0) MemUtil::memCpy (d_array_p [i], array_ [i], sizeof (double) * getArrayCapacity ());
145     }
146 
147     d_valueBegin = valueBegin_;
148     d_valueLower = valueLower_;
149     d_valueUpper = valueUpper_;
150 
151     setValueFct (newStateFct_);
152     setInput (dimInputProb_, inputProb_);
153 }
154 
initInput(size_t dimInputProb_)155 void DynProgProb::initInput (size_t dimInputProb_) // array of input states : d_inputProb_p [0...dimStateProb - 1]
156 {
157     if (dimInputProb_ > 0)
158     {
159 	d_inputProb_p = new double [dimInputProb_];
160 	MemUtil::memZero (d_inputProb_p, sizeof (double) * dimInputProb_);
161     }
162 
163     d_dimInputProb = dimInputProb_;
164 }
165 
freeInput()166 void DynProgProb::freeInput ()
167 {
168     if (getDimInputProb () > 0)
169     {
170 	delete [] d_inputProb_p; d_inputProb_p = 0;
171     }
172 
173     d_dimInputProb = 0;
174 }
175 
setInput(size_t dimInputProb_,const double * inputProb_)176 void DynProgProb::setInput (
177 size_t dimInputProb_,
178 const double *inputProb_) // array of input states : d_inputProb_p [0...dimStateProb - 1]
179 {
180     if (dimInputProb_ != getDimInputProb ())
181     {
182 	freeInput ();
183 	initInput (dimInputProb_);
184     }
185 
186     if (getDimInputProb () > 0) MemUtil::memCpy (d_inputProb_p, inputProb_, sizeof (double) * getDimInputProb ());
187 }
188 
update()189 void DynProgProb::update () // updates dynamic prog probs
190 {
191     assert (getValueFct ());
192     assert (getDimInputProb ());
193     assert (getInputProb ());
194 
195     const size_t ARRAY_FAC = 2;
196     assert (1 < ARRAY_FAC);
197 
198     long int i = 0;
199     size_t j = 0;
200 
201     const double *oldArray = 0;
202     double *array = 0;
203     long int value = 0;
204     long int valueBegin = 0;
205     long int valueLower = 0;
206     long int valueUpper = 0;
207     /*sls deleted size_t arrayPos = 0;*/
208 
209     oldArray = d_array_p [d_step % 2];
210     array = d_array_p [(d_step + 1) % 2];
211     valueLower = LONG_MAX;
212     valueUpper = LONG_MIN;
213 
214     MemUtil::memZero (array, sizeof (double) * getArrayCapacity ());
215 
216     for (i = getValueLower (); i < getValueUpper (); i++)
217     {
218 	if (oldArray [getArrayPos (i)] == 0.0) continue;
219 
220 	for (j = 0; j < getDimInputProb (); j++)
221 	{
222 	    if (getInputProb () [j] == 0.0) continue;
223 
224 	    // adjust the reserve, if necessary
225 	    value = getValueFct () (i, j);
226 	    while (value < getValueBegin () || getValueEnd () <= value) {
227 	    valueBegin = getValueBegin ();
228 	    if (value < getValueBegin ()) valueBegin -= (ARRAY_FAC - 1) * getArrayCapacity ();
229 	    reserve (ARRAY_FAC * getArrayCapacity ());
230 	    setValueBegin (valueBegin);
231 	    oldArray = d_array_p [d_step % 2];
232 	    array = d_array_p [(d_step + 1) % 2];
233 	    }
234 
235 	    if (value < valueLower) valueLower = value;
236 	    if (valueUpper < value) valueUpper = value;
237 
238 	    // add the probability
239 	    assert (getValueBegin () <= i);
240 	    assert (i < getValueEnd ());
241 	    array [getArrayPos (value)] += oldArray [getArrayPos (i)] * getInputProb () [j];
242 	}
243     }
244 
245     d_valueLower = valueLower;
246     d_valueUpper = valueUpper + 1;
247     d_step++;
248 }
249 
reserve(size_t arrayCapacity_)250 void DynProgProb::reserve (size_t arrayCapacity_) // new array capacity
251 // increases capacity of and copies d_array_p, while updating other variables
252 {
253     assert (getArrayCapacity () < arrayCapacity_);
254 
255     double *array = new double [getArrayCapacity ()];
256 
257     for (size_t i = 0; i < 2; i++)
258     {
259 	MemUtil::memCpy (array, d_array_p [i], sizeof (double) * getArrayCapacity ());
260 	delete [] d_array_p [i]; d_array_p [i] = 0;
261 	d_array_p [i] = new double [arrayCapacity_];
262 	MemUtil::memZero (d_array_p [i], sizeof (double) * arrayCapacity_);
263 	MemUtil::memCpy (d_array_p [i], array, sizeof (double) * getArrayCapacity ());
264     }
265 
266     d_arrayCapacity = arrayCapacity_;
267 
268     delete [] array; array = 0;
269 }
270 
setValueBegin(long int valueBegin_)271 void DynProgProb::setValueBegin (long int valueBegin_)
272 // resets the offset d_valueBegin
273 // assert (valueBegin_ <= getValueBegin ()) : enlarge the array only
274 // assert (offSet < getArrayCapacity ());
275 {
276     assert (valueBegin_ <= getValueBegin ());
277     size_t offSet = static_cast <size_t> (getValueBegin () - valueBegin_);
278     if (offSet == 0) return; // nothing to do
279 
280     assert (offSet < getArrayCapacity ());
281 
282     double *array = new double [getArrayCapacity ()];
283 
284     for (size_t i = 0; i < 2; i++)
285     {
286 	MemUtil::memCpy (array, d_array_p [i], sizeof (double) * getArrayCapacity ());
287 	MemUtil::memZero (d_array_p [i], sizeof (double) * getArrayCapacity ());
288 	MemUtil::memCpy (d_array_p [i] + offSet, array, sizeof (double) * (getArrayCapacity () - offSet));
289     }
290 
291     delete [] array; array = 0;
292 
293     d_valueBegin = valueBegin_;
294 }
295 
296