SQLamarr
The stand-alone ultra-fast simulation option for the LHCb experiment
custom_sql_functions.cpp
1 // (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration.
2 //
3 // This software is distributed under the terms of the GNU General Public
4 // Licence version 3 (GPL Version 3), copied verbatim in the file "LICENCE".
5 //
6 // In applying this licence, CERN does not waive the privileges and immunities
7 // granted to it by virtue of its status as an Intergovernmental Organization
8 // or submit itself to any jurisdiction.
9 
10 
11 #include <stddef.h>
12 #include <math.h>
13 #include <random>
14 #include "sqlite3.h"
15 #include "SQLamarr/custom_sql_functions.h"
16 #include "SQLamarr/GlobalPRNG.h"
17 
18 
19 //==============================================================================
20 // sqlamarr_create_sql_functions: define all the other functions in SQL
21 //==============================================================================
22 void sqlamarr_create_sql_functions (sqlite3 *db)
23 {
24  int nPars;
25 
26  sqlite3_create_function(db,
27  "log", 1,
28  SQLITE_UTF8, NULL, &_sqlamarr_sql_log, NULL, NULL
29  );
30 
31  sqlite3_create_function(db,
32  "norm2", 3,
33  SQLITE_UTF8, NULL, &_sqlamarr_sql_norm2, NULL, NULL
34  );
35 
36  sqlite3_create_function(db,
37  "pseudorapidity", 3,
38  SQLITE_UTF8, NULL, &_sqlamarr_sql_pseudorapidity, NULL, NULL
39  );
40 
41  sqlite3_create_function(db,
42  "azimuthal", 3,
43  SQLITE_UTF8, NULL, &_sqlamarr_sql_azimuthal, NULL, NULL
44  );
45 
46  sqlite3_create_function(db,
47  "polar", 3,
48  SQLITE_UTF8, NULL, &_sqlamarr_sql_polar, NULL, NULL
49  );
50 
51  sqlite3_create_function(db,
52  "propagation_charge", 1,
53  SQLITE_UTF8, NULL, &_sqlamarr_sql_propagation_charge, NULL, NULL
54  );
55 
56  sqlite3_create_function(db,
57  "slopes_to_cartesian", 4,
58  SQLITE_UTF8, NULL, &_sqlamarr_sql_slopes_to_cartesian, NULL, NULL
59  );
60 
61  sqlite3_create_function(db,
62  "random_uniform", 0,
63  SQLITE_UTF8, NULL, &_sqlamarr_sql_random_uniform, NULL, NULL
64  );
65 
66  sqlite3_create_function(db,
67  "random_normal", 0,
68  SQLITE_UTF8, NULL, &_sqlamarr_sql_random_normal, NULL, NULL
69  );
70 
71  for (nPars = 1; nPars < 10; ++nPars)
72  sqlite3_create_function(db,
73  "random_category", nPars,
74  SQLITE_UTF8, NULL, &_sqlamarr_sql_random_category, NULL, NULL
75  );
76 
77  sqlite3_create_function(db,
78  "z_closest_to_beam", 5,
79  SQLITE_UTF8, NULL, &_sqlamarr_sql_z_closest_to_beam, NULL, NULL
80  );
81 
82 }
83 
84 //==============================================================================
85 // log
86 //==============================================================================
87 void _sqlamarr_sql_log (
88  sqlite3_context *context,
89  int /*argc*/,
90  sqlite3_value **argv
91  )
92 {
93  double res = 0;
94  res = log(sqlite3_value_double(argv[0]));
95  sqlite3_result_double(context, res);
96 }
97 
98 //==============================================================================
99 // norm2
100 //==============================================================================
101 void _sqlamarr_sql_norm2 (
102  sqlite3_context *context,
103  int argc,
104  sqlite3_value **argv
105  )
106 {
107  double res = 0;
108  int iPar = 0;
109  double buf;
110 
111  for (iPar = 0; iPar < argc; ++iPar)
112  {
113  buf = sqlite3_value_double(argv[iPar]);
114  res += buf*buf;
115  }
116  res = sqrt(res);
117 
118  sqlite3_result_double(context, res);
119 }
120 
121 //==============================================================================
122 // z_closest_to_beam
123 //==============================================================================
124 void _sqlamarr_sql_z_closest_to_beam (
125  sqlite3_context *context,
126  int argc,
127  sqlite3_value **argv
128  )
129 {
130  if (argc != 5)
131  {
132  sqlite3_result_null(context);
133  return;
134  }
135 
136  int i = 0;
137  const double x0 = sqlite3_value_double(argv[i++]);
138  const double y0 = sqlite3_value_double(argv[i++]);
139  const double z0 = sqlite3_value_double(argv[i++]);
140  const double tx = sqlite3_value_double(argv[i++]);
141  const double ty = sqlite3_value_double(argv[i++]);
142 
143  const double ctb_z = (tx*tx*z0 - tx*x0 + ty*ty*z0 - ty*y0)/(tx*tx + ty*ty);
144 
145  sqlite3_result_double(context, ctb_z);
146 }
147 
148 
149 //==============================================================================
150 // pseudorapidity
151 //==============================================================================
152 void _sqlamarr_sql_pseudorapidity (
153  sqlite3_context *context,
154  int argc,
155  sqlite3_value **argv
156  )
157 {
158  double x, y, z, theta, eta;
159 
160  if (argc != 3)
161  {
162  sqlite3_result_null(context);
163  return;
164  }
165 
166  x = sqlite3_value_double(argv[0]);
167  y = sqlite3_value_double(argv[1]);
168  z = sqlite3_value_double(argv[2]);
169 
170  theta = atan2(sqrt(x*x + y*y), z);
171  eta = -log(tan(0.5*theta));
172 
173  sqlite3_result_double(context, eta);
174 }
175 
176 //==============================================================================
177 // azimuthal
178 //==============================================================================
179 void _sqlamarr_sql_azimuthal (
180  sqlite3_context *context,
181  int argc,
182  sqlite3_value **argv
183  )
184 {
185  double x, y/*, z*/;
186 
187  if (argc != 3)
188  {
189  sqlite3_result_null(context);
190  return;
191  }
192 
193  x = sqlite3_value_double(argv[0]);
194  y = sqlite3_value_double(argv[1]);
195  /* z is unused but it is expected for interface consistency
196  z = sqlite3_value_double(argv[2]);
197  */
198 
199  sqlite3_result_double(context, atan2(y, x));
200 }
201 
202 //==============================================================================
203 // polar
204 //==============================================================================
205 void _sqlamarr_sql_polar (
206  sqlite3_context *context,
207  int argc,
208  sqlite3_value **argv
209  )
210 {
211  double x, y, z;
212 
213  if (argc != 3)
214  {
215  sqlite3_result_null(context);
216  return;
217  }
218 
219  x = sqlite3_value_double(argv[0]);
220  y = sqlite3_value_double(argv[1]);
221  z = sqlite3_value_double(argv[2]);
222 
223  sqlite3_result_double(context, atan2(x*x + y*y, z));
224 }
225 
226 //==============================================================================
227 // propagation_charge
228 //==============================================================================
229 void _sqlamarr_sql_propagation_charge (
230  sqlite3_context *context,
231  int argc,
232  sqlite3_value **argv
233  )
234 {
235  long int pid;
236 
237  if (argc != 1)
238  {
239  sqlite3_result_null(context);
240  return;
241  }
242 
243  pid = sqlite3_value_int(argv[0]);
244 
245  // Leptons
246  if (abs(pid) == 11 || abs(pid) == 13 || abs(pid) == 15)
247  sqlite3_result_int(context, (pid > 0) ? -1 : +1);
248 
249  // Hadron Tracks
250  else if (abs(pid) == 211 || abs(pid) == 321 || abs(pid) == 2212)
251  sqlite3_result_int(context, (pid > 0) ? +1 : -1);
252 
253  // Photons and neutrons
254  else if (abs(pid) == 22 || abs(pid) == 2112)
255  sqlite3_result_int(context, 0);
256 
257  else
258  sqlite3_result_null(context);
259 }
260 
261 //==============================================================================
262 // slopes_to_cartesian
263 //==============================================================================
264 void _sqlamarr_sql_slopes_to_cartesian (
265  sqlite3_context *context,
266  int argc,
267  sqlite3_value **argv
268  )
269 {
270  int coord;
271  double norm, tx, ty;
272  double ret[3];
273 
274  if (argc != 4)
275  {
276  sqlite3_result_null(context);
277  return;
278  }
279 
280  coord = sqlite3_value_int(argv[0]);
281  if (coord < 0 or coord > 2)
282  {
283  sqlite3_result_error(context, "Invalid coord. Choose 012 for xyz.", -1);
284  return;
285  }
286 
287  norm = sqlite3_value_double(argv[1]);
288  if (norm < 0)
289  {
290  sqlite3_result_error(context, "Negative norm", -1);
291  return;
292  }
293 
294  tx = sqlite3_value_double(argv[2]);
295  ty = sqlite3_value_double(argv[3]);
296 
297  ret[2] = norm/sqrt(1 + tx*tx + ty*ty);
298  ret[0] = ret[2]*tx;
299  ret[1] = ret[2]*ty;
300 
301  sqlite3_result_double(context, ret[coord]);
302 }
303 
304 
305 //==============================================================================
306 // random_uniform
307 //==============================================================================
308 void _sqlamarr_sql_random_uniform (
309  sqlite3_context *context,
310  int /*argc*/,
311  sqlite3_value ** /*argv*/
312  )
313 {
314  auto generator = SQLamarr::GlobalPRNG::get_or_create(context);
315  std::uniform_real_distribution<double> uniform;
316 
317  sqlite3_result_double(context, uniform(*generator));
318 }
319 
320 //==============================================================================
321 // random_normal
322 //==============================================================================
323 void _sqlamarr_sql_random_normal (
324  sqlite3_context *context,
325  int /*argc*/,
326  sqlite3_value ** /*argv*/
327  )
328 {
329  auto generator = SQLamarr::GlobalPRNG::get_or_create(context);
330  std::normal_distribution<double> gaussian;
331 
332  sqlite3_result_double(context, gaussian(*generator));
333 }
334 
335 //==============================================================================
336 // random_category
337 //==============================================================================
338 void _sqlamarr_sql_random_category (
339  sqlite3_context *context,
340  int argc,
341  sqlite3_value **argv
342  )
343 {
344  auto generator = SQLamarr::GlobalPRNG::get_or_create(context);
345  std::uniform_real_distribution<float> uniform;
346  float sum = 0;
347  float r = uniform(*generator);
348  int iArg;
349  int ret = argc;
350 
351  // Check probability is non-negative
352  for (iArg = 0; iArg < argc; ++iArg)
353  if (sqlite3_value_double(argv[iArg]) < 0)
354  {
355  sqlite3_result_error(context, "Negative probability", -1);
356  return;
357  }
358 
359  // Compute cumulative and corresponding category
360  for (iArg = 0; iArg < argc; ++iArg)
361  {
362  sum += static_cast<float>(sqlite3_value_double(argv[iArg]));
363  if (r < sum && ret == argc) ret = iArg;
364  }
365  // Check sum of probabilities is normalized or normalizable
366  if (sum > 1.)
367  sqlite3_result_error(context, "Sum of probabilities larger than 1", -1);
368  else
369  sqlite3_result_int(context, ret);
370 }
static PRNG * get_or_create(const sqlite3_context *db, uint64_t seed=no_seed)
Return a pointer to an initialized generator.
Definition: GlobalPRNG.h:99