Blender  V3.3
math_statistics.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2015 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_math.h"
11 #include "BLI_task.h"
12 #include "BLI_utildefines.h"
13 
14 #include "BLI_strict_flags.h"
15 
16 /********************************** Covariance Matrices *********************************/
17 
18 typedef struct CovarianceData {
19  const float *cos_vn;
20  const float *center;
21  float *r_covmat;
22  float covfac;
23  int n;
26 
27 static void covariance_m_vn_ex_task_cb(void *__restrict userdata,
28  const int a,
29  const TaskParallelTLS *__restrict UNUSED(tls))
30 {
31  CovarianceData *data = userdata;
32  const float *cos_vn = data->cos_vn;
33  const float *center = data->center;
34  float *r_covmat = data->r_covmat;
35  const int n = data->n;
36  const int cos_vn_num = data->cos_vn_num;
37 
38  int k;
39 
40  /* Covariance matrices are always symmetrical, so we can compute only one half of it,
41  * and mirror it to the other half (at the end of the func).
42  *
43  * This allows using a flat loop of n*n with same results as imbricated one over half the matrix:
44  *
45  * for (i = 0; i < n; i++) {
46  * for (j = i; j < n; j++) {
47  * ...
48  * }
49  * }
50  */
51  const int i = a / n;
52  const int j = a % n;
53  if (j < i) {
54  return;
55  }
56 
57  if (center) {
58  for (k = 0; k < cos_vn_num; k++) {
59  r_covmat[a] += (cos_vn[k * n + i] - center[i]) * (cos_vn[k * n + j] - center[j]);
60  }
61  }
62  else {
63  for (k = 0; k < cos_vn_num; k++) {
64  r_covmat[a] += cos_vn[k * n + i] * cos_vn[k * n + j];
65  }
66  }
67  r_covmat[a] *= data->covfac;
68  if (j != i) {
69  /* Mirror result to other half... */
70  r_covmat[j * n + i] = r_covmat[a];
71  }
72 }
73 
74 void BLI_covariance_m_vn_ex(const int n,
75  const float *cos_vn,
76  const int cos_vn_num,
77  const float *center,
78  const bool use_sample_correction,
79  float *r_covmat)
80 {
81  /* Note about that division: see https://en.wikipedia.org/wiki/Bessel%27s_correction.
82  * In a nutshell, it must be 1 / (n - 1) for 'sample data', and 1 / n for 'population data'...
83  */
84  const float covfac = 1.0f / (float)(use_sample_correction ? cos_vn_num - 1 : cos_vn_num);
85 
86  memset(r_covmat, 0, sizeof(*r_covmat) * (size_t)(n * n));
87 
89  .cos_vn = cos_vn,
90  .center = center,
91  .r_covmat = r_covmat,
92  .covfac = covfac,
93  .n = n,
94  .cos_vn_num = cos_vn_num,
95  };
96 
97  TaskParallelSettings settings;
99  settings.use_threading = ((cos_vn_num * n * n) >= 10000);
101 }
102 
103 void BLI_covariance_m3_v3n(const float (*cos_v3)[3],
104  const int cos_v3_num,
105  const bool use_sample_correction,
106  float r_covmat[3][3],
107  float r_center[3])
108 {
109  float center[3];
110  const float mean_fac = 1.0f / (float)cos_v3_num;
111  int i;
112 
113  zero_v3(center);
114  for (i = 0; i < cos_v3_num; i++) {
115  /* Applying mean_fac here rather than once at the end reduce compute errors... */
116  madd_v3_v3fl(center, cos_v3[i], mean_fac);
117  }
118 
119  if (r_center) {
120  copy_v3_v3(r_center, center);
121  }
122 
124  3, (const float *)cos_v3, cos_v3_num, center, use_sample_correction, (float *)r_covmat);
125 }
typedef float(TangentPoint)[2]
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
#define UNUSED(x)
NSNotificationCenter * center
Read Guarded memory(de)allocation.
static void covariance_m_vn_ex_task_cb(void *__restrict userdata, const int a, const TaskParallelTLS *__restrict UNUSED(tls))
struct CovarianceData CovarianceData
void BLI_covariance_m3_v3n(const float(*cos_v3)[3], const int cos_v3_num, const bool use_sample_correction, float r_covmat[3][3], float r_center[3])
Compute the covariance matrix of given set of 3D coordinates.
void BLI_covariance_m_vn_ex(const int n, const float *cos_vn, const int cos_vn_num, const float *center, const bool use_sample_correction, float *r_covmat)
Compute the covariance matrix of given set of nD coordinates.
static unsigned a[3]
Definition: RandGen.cpp:78
const float * cos_vn
const float * center