CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
local/hash_code.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_HASH_CODE_HPP
2 # define CPPAD_LOCAL_HASH_CODE_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 # include <cppad/core/base_hash.hpp>
15 /*!
16 \file local/hash_code.hpp
17 CppAD hashing utility.
18 */
19 
20 
21 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
22 /*!
23 General purpose hash code for an arbitrary value.
24 
25 \tparam Value
26 is the type of the argument being hash coded.
27 It should be a plain old data class; i.e.,
28 the values included in the equality operator in the object and
29 not pointed to by the object.
30 
31 \param value
32 the value that we are generating a hash code for.
33 All of the fields in value should have been set before the hash code
34 is computed (otherwise undefined values are used).
35 
36 \return
37 is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
38 
39 \par Checked Assertions
40 \li \c std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE
41 \li \c sizeof(value) is even
42 \li \c sizeof(unsigned short) == 2
43 */
44 template <class Value>
45 unsigned short local_hash_code(const Value& value)
47  std::numeric_limits<unsigned short>::max()
48  >=
50  );
51  CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );
52  CPPAD_ASSERT_UNKNOWN( sizeof(value) % 2 == 0 );
53  //
54  const unsigned short* v
55  = reinterpret_cast<const unsigned short*>(& value);
56  //
57  size_t i = sizeof(value) / 2 - 1;
58  //
59  size_t sum = v[i];
60  //
61  while(i--)
62  sum += v[i];
63  //
64  unsigned short code = static_cast<unsigned short>(
66  );
67  return code;
68 }
69 
70 /*!
71 Specialized hash code for a CppAD operator and its arguments.
72 
73 \param op
74 is the operator that we are computing a hash code for.
75 If it is not one of the following operartors, the operator is not
76 hash coded and zero is returned:
77 
78 \li unary operators:
79 AbsOp, AcosOp, AcoshOp, AsinOp, AsinhOp, AtanOp, AtanhOp, CosOp, CoshOp
80 ExpOp, Expm1Op, LogOp, Log1pOp, SinOp, SinhOp, SqrtOp, TanOp, TanhOp
81 
82 \li binary operators where first argument is a parameter:
83 AddpvOp, DivpvOp, MulpvOp, PowpvOp, SubpvOp, ZmulpvOp
84 
85 \li binary operators where second argument is a parameter:
86 DivvpOp, PowvpOp, SubvpOp, Zmulvp
87 
88 \li binary operators where first is an index and second is a variable:
89 DisOp
90 
91 \li binary operators where both arguments are variables:
92 AddvvOp, DivvvOp, MulvvOp, PowvvOp, SubvvOp, ZmulvvOp
93 
94 \param arg
95 is a vector of length \c NumArg(op) or 2 (which ever is smaller),
96 containing the corresponding argument indices for this operator.
97 
98 \param npar
99 is the number of parameters corresponding to this operation sequence.
100 
101 \param par
102 is a vector of length \a npar containing the parameters
103 for this operation sequence; i.e.,
104 given a parameter index of \c i, the corresponding parameter value is
105 \a par[i].
106 
107 
108 \return
109 is a hash code that is between zero and CPPAD_HASH_TABLE_SIZE - 1.
110 
111 \par Checked Assertions
112 \c op must be one of the operators specified above. In addition,
113 \li \c std::numeric_limits<unsigned short>::max() >= CPPAD_HASH_TABLE_SIZE
114 \li \c sizeof(size_t) is even
115 \li \c sizeof(Base) is even
116 \li \c sizeof(unsigned short) == 2
117 \li \c size_t(op) < size_t(NumberOp) <= CPPAD_HASH_TABLE_SIZE
118 \li if the j-th argument for this operation is a parameter, arg[j] < npar.
119 */
120 
121 template <class Base>
122 unsigned short local_hash_code(
123  OpCode op ,
124  const addr_t* arg ,
125  size_t npar ,
126  const Base* par )
128  std::numeric_limits<unsigned short>::max()
129  >=
131  );
132  CPPAD_ASSERT_UNKNOWN( size_t (op) < size_t(NumberOp) );
133  CPPAD_ASSERT_UNKNOWN( sizeof(unsigned short) == 2 );
134  CPPAD_ASSERT_UNKNOWN( sizeof(addr_t) % 2 == 0 );
135  CPPAD_ASSERT_UNKNOWN( sizeof(Base) % 2 == 0 );
136  unsigned short op_fac = static_cast<unsigned short> (
137  CPPAD_HASH_TABLE_SIZE / static_cast<unsigned short>(NumberOp)
138  );
139  CPPAD_ASSERT_UNKNOWN( op_fac > 0 );
140 
141  // number of shorts per addr_t value
142  size_t short_addr_t = sizeof(addr_t) / 2;
143 
144  // number of shorts per Base value
145  size_t short_base = sizeof(Base) / 2;
146 
147  // initialize with value that separates operators as much as possible
148  unsigned short code = static_cast<unsigned short>(
149  static_cast<unsigned short>(op) * op_fac
150  );
151 
152  // now code in the operands
153  size_t i;
154  const unsigned short* v;
155 
156  // first argument
157  switch(op)
158  { // Binary operators where first arugment is a parameter.
159  // Code parameters by value instead of
160  // by index for two reasons. One, it gives better separation.
161  // Two, different indices can be same parameter value.
162  case AddpvOp:
163  case DivpvOp:
164  case MulpvOp:
165  case PowpvOp:
166  case SubpvOp:
167  case ZmulpvOp:
168  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
169  v = reinterpret_cast<const unsigned short*>(par + arg[0]);
170  i = short_base;
171  while(i--)
172  code += v[i];
173  v = reinterpret_cast<const unsigned short*>(arg + 1);
174  i = short_addr_t;
175  while(i--)
176  code += v[i];
177  break;
178 
179  // Binary operator where first argument is an index and
180  // second is a variable (same as both variables).
181  case DisOp:
182 
183  // Binary operators where both arguments are variables
184  case AddvvOp:
185  case DivvvOp:
186  case MulvvOp:
187  case PowvvOp:
188  case SubvvOp:
189  case ZmulvvOp:
190  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
191  v = reinterpret_cast<const unsigned short*>(arg + 0);
192  i = 2 * short_addr_t;
193  while(i--)
194  code += v[i];
195  break;
196 
197  // Binary operators where second arugment is a parameter.
198  case DivvpOp:
199  case PowvpOp:
200  case SubvpOp:
201  case ZmulvpOp:
202  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 2 );
203  v = reinterpret_cast<const unsigned short*>(arg + 0);
204  i = short_addr_t;
205  while(i--)
206  code += v[i];
207  v = reinterpret_cast<const unsigned short*>(par + arg[1]);
208  i = short_base;
209  while(i--)
210  code += v[i];
211  break;
212 
213  // Unary operators
214  case AbsOp:
215  case AcosOp:
216  case AcoshOp:
217  case AsinOp:
218  case AsinhOp:
219  case AtanOp:
220  case AtanhOp:
221  case CosOp:
222  case CoshOp:
223  case ErfOp:
224  case ExpOp:
225  case Expm1Op:
226  case LogOp:
227  case Log1pOp:
228  case SignOp:
229  case SinOp:
230  case SinhOp:
231  case SqrtOp:
232  case TanOp:
233  case TanhOp:
234  CPPAD_ASSERT_UNKNOWN( NumArg(op) == 1 || op == ErfOp );
235  v = reinterpret_cast<const unsigned short*>(arg + 0);
236  i = short_addr_t;
237  while(i--)
238  code += v[i];
239  break;
240 
241  // should have been one of he cases above
242  default:
243  CPPAD_ASSERT_UNKNOWN(false);
244  }
245 
246  return code % CPPAD_HASH_TABLE_SIZE;
247 }
248 
249 } } // END_CPPAD_LOCAL_NAMESPACE
250 
251 # endif
CPPAD_TAPE_ADDR_TYPE addr_t
Definition: declare_ad.hpp:44
size_t NumArg(OpCode op)
Number of arguments for a specified operator.
Definition: op_code.hpp:175
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION Base Value(const AD< Base > &x)
Definition: value.hpp:82
unsigned short local_hash_code(const Value &value)
General purpose hash code for an arbitrary value.
OpCode
Type used to distinguish different AD&lt; Base &gt; atomic operations.
Definition: op_code.hpp:49
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
#define CPPAD_HASH_TABLE_SIZE
the codes retruned by hash_code are between zero and CPPAD_HASH_TABLE_SIZE minus one.
Definition: base_hash.hpp:82