1 /*
2 Internal library functions and definitions
3 Copyright (C) 2007 by Andrew Zabolotny
4 */
5
6 #ifndef __LENSFUNPRV_H__
7 #define __LENSFUNPRV_H__
8
9 #include <glib.h>
10 #include <string.h>
11 #include <vector>
12
13 #define MEMBER_OFFSET(s,f) ((unsigned int)(char *)&((s *)0)->f)
14 #define ARRAY_LEN(a) (sizeof (a) / sizeof (a [0]))
15 #define cbool int
16
17 // This epsilon is in image coordinate space, where 1.0 is
18 // half of the smallest image dimension (width or height)
19 // adjusted for the lens calibration data/camera crop factors.
20 #define NEWTON_EPS 0.00001
21
22 class lfFuzzyStrCmp;
23
24 /**
25 * @brief Return the absolute value of a number.
26 * @param x
27 * A number
28 * @return
29 * The absolute value of x
30 */
absolute(T x)31 template<typename T> static inline T absolute (T x)
32 {
33 return (x < 0) ? -x : x;
34 }
35
36 /**
37 * @brief Return the square of the argument.
38 * @param x
39 * A floating-point number.
40 */
square(T x)41 template<typename T> static inline T square (T x)
42 {
43 return x * x;
44 }
45
46 /**
47 * @brief Clamp a double value between 0 and max, then convert to given type.
48 * @param x
49 * The number to clamp.
50 * @param min
51 * The minimal value.
52 * @param max
53 * The maximal value. If equal to 0, no clamping by upper boundary is done.
54 * @return
55 * The clamped value.
56 */
clampd(double x,double min,double max)57 template<typename T> static inline T clampd (double x, double min, double max)
58 {
59 if (x < min)
60 return static_cast<T> (min);
61 else if (max != 0.0 && x > max)
62 return static_cast<T> (max);
63 return static_cast<T> (x);
64 }
65
66 /**
67 * @brief Make a copy of given value into given variable using g_strdup,
68 * freeing the old value if defined.
69 * @param var
70 * The variable to copy value into
71 * @param val
72 * The value to assign to the variable
73 */
74 extern void _lf_setstr (gchar **var, const gchar *val);
75
76 /**
77 * @brief Appends a formatted string to a dynamically-growing string
78 * using g_markup_printf_escaped() internally.
79 * @param output
80 * The output array.
81 * @param format
82 * The format string.
83 */
84 extern void _lf_xml_printf (GString *output, const char *format, ...);
85
86 /**
87 * @brief Output a multi-language value to output string.
88 *
89 * Outputs a number of lines which looks like:
90 *
91 * \Verbatim
92 * ${prefix}<${element}>${val}</${element}>
93 * ${prefix}<${element} lang="xxx">${val[xxx]}</${element}>
94 * ...
95 * \EndVerbatim
96 * @param output
97 * The output array.
98 * @param prefix
99 * The prefix at the start of every line of output.
100 * @param element
101 * The name of the element to output.
102 * @param val
103 * The value of the multi-language string.
104 */
105 extern void _lf_xml_printf_mlstr (GString *output, const char *prefix,
106 const char *element, const lfMLstr val);
107
108 /**
109 * @brief Something like a very advanced strcmp().
110 *
111 * It doesn't segfault if one or both strings are NULL:
112 * NULL is considered to be less than any string.
113 * Actually this function does a fuzzy comparison of the strings,
114 * ignoring spaces at both ends of the string, compressing multiple
115 * spaces into one and ignoring character case.
116 */
117 extern int _lf_strcmp (const char *s1, const char *s2);
118
119 /**
120 * @brief Same as _lf_strcmp(), but compares a string with a multi-language
121 * string.
122 *
123 * If it equals any of the translations, 0 is returned, otherwise
124 * the result of strcmp() with the first (default) string is returned.
125 */
126 extern int _lf_mlstrcmp (const char *s1, const lfMLstr s2);
127
128 /**
129 * @brief Comparison helper function for lens sorting and finding.
130 *
131 * This function compares the numerical parameters of the lenses: MinFocal,
132 * MaxFocal, and MinAperture, in this order. Since it is not meant to be used
133 * as a sorting key function directly, it doesn't take generic pointers as
134 * parameters. Instead, it is supposed to be used by such sorting key
135 * functions like _lf_lens_compare.
136 * @param i1
137 * A pointer to first lfLens object.
138 * @param i2
139 * A pointer to second lfLens object.
140 * @return
141 * Positive if i1 > i2, negative if i1 < i2, zero if they are equal.
142 */
143 extern gint _lf_lens_parameters_compare (const lfLens *i1, const lfLens *i2);
144
145 /**
146 * @brief Comparison helper function for lens sorting and finding.
147 *
148 * This function compares the names of the lenses: Maker and Model, in this
149 * order. Since it is not meant to be used as a sorting key function directly,
150 * it doesn't take generic pointers as parameters. Instead, it is supposed to
151 * be used by such sorting key functions like _lf_lens_compare.
152 * @param i1
153 * A pointer to first lfLens object.
154 * @param i2
155 * A pointer to second lfLens object.
156 * @return
157 * Positive if i1 > i2, negative if i1 < i2, zero if they are equal.
158 */
159 extern gint _lf_lens_name_compare (const lfLens *i1, const lfLens *i2);
160
161 /**
162 * @brief Get an interpolated value.
163 *
164 * Currently this uses a kind of Catmull-Rom splines with linear
165 * interpolation at the ends, allowing for non-evenly spaced values
166 * and handling the extreme cases correctly (the one at the start
167 * of spline and at the end of spline). The region of interest is
168 * from y2 to y3, selected by values of t from 0.0 to 1.0.
169 * @param y1
170 * The Y coordinate of the first spline point.
171 * If equal to FLT_MAX, the first point is considered non-existent.
172 * @param y2
173 * The Y coordinate of the second spline point.
174 * @param y3
175 * The Y coordinate of the third spline point.
176 * @param y4
177 * The Y coordinate of the fourth spline point.
178 * If equal to FLT_MAX, the fourth point is considered non-existent.
179 * @param t
180 * Value from 0.0 to 1.0 selects a point on spline on the interval
181 * between points 2 and 3.
182 */
183 extern float _lf_interpolate (float y1, float y2, float y3, float y4, float t);
184
185 enum
186 {
187 LF_CPU_FLAG_MMX = 0x00000001,
188 LF_CPU_FLAG_SSE = 0x00000002,
189 LF_CPU_FLAG_CMOV = 0x00000004,
190 LF_CPU_FLAG_3DNOW = 0x00000008,
191 LF_CPU_FLAG_3DNOW_EXT = 0x00000010,
192 LF_CPU_FLAG_AMD_ISSE = 0x00000020,
193 LF_CPU_FLAG_SSE2 = 0x00000040,
194 LF_CPU_FLAG_SSE3 = 0x00000080,
195 LF_CPU_FLAG_SSSE3 = 0x00000100,
196 LF_CPU_FLAG_SSE4_1 = 0x00000200,
197 LF_CPU_FLAG_SSE4_2 = 0x00000400
198 };
199
200 /**
201 * @brief Detect supported CPU features (used for runtime selection of accelerated
202 * functions for specific architecture extensions).
203 */
204 extern guint _lf_detect_cpu_features ();
205
206 /**
207 * @brief Google-in-your-pocket: a fuzzy string comparator.
208 *
209 * This has been designed for comparing lens and camera model names.
210 * At construction the pattern is split into words and then the component
211 * words from target are matched against them.
212 */
213 class lfFuzzyStrCmp
214 {
215 GPtrArray *pattern_words;
216 GPtrArray *match_words;
217 bool match_all_words;
218
219 void Split (const char *str, GPtrArray *dest);
220 void Free (GPtrArray *dest);
221
222 public:
223 /**
224 * @param pattern
225 * The pattern which will be compared against a number of strings.
226 * This is typically what was found in the EXIF data.
227 * @param allwords
228 * If true, all words of the pattern must be present in the
229 * target string. If not, a looser result will be accepted,
230 * although this will be reflected in the match score.
231 */
232 lfFuzzyStrCmp (const char *pattern, bool allwords);
233 ~lfFuzzyStrCmp ();
234
235 /**
236 * @brief Fuzzy compare the pattern with a string.
237 * @param match
238 * The string to match against. This is typically taken from the
239 * Lensfun database.
240 * @return
241 * Returns a score in range 0-100. If the match succedes, this score
242 * is the number of matched words divided by the mean word count of
243 * pattern and string, given as a percentage. If it fails, it is 0.
244 * It fails if no words could be matched, of if allwords was set to
245 * true and one word in pattern could not be found in match.
246 */
247 int Compare (const char *match);
248
249 /**
250 * @brief Compares the pattern with a multi-language string.
251 *
252 * This function returns the largest score as compared against
253 * every of the translated strings.
254 * @param match
255 * The multi-language string to match against. This is typically taken
256 * from the Lensfun database.
257 * @return
258 * Returns the maximal score in range 0-100. For every component of
259 * the multi-language string, a score is computed: If the match
260 * succedes, the score is the number of matched words divided by the
261 * mean word count of pattern and string, given as a percentage. If it
262 * fails, it is 0. It fails if no words could be matched, of if
263 * allwords was set to true and one word in pattern could not be found
264 * in match.
265 */
266 int Compare (const lfMLstr match);
267 };
268
269 template <class T>
_lf_terminate_vec(std::vector<T> & v)270 void _lf_terminate_vec(std::vector<T> &v)
271 {
272 int size = v.size();
273 v.reserve(size+1);
274 v.data()[size] = NULL;
275 }
276
277 // `dvector`, `matrix`, and `svg` are declared here to be able to test `svd` in
278 // unit tests.
279
280 typedef std::vector<double> dvector;
281 typedef std::vector<dvector> matrix;
282
283 dvector svd (matrix M);
284
285 #endif /* __LENSFUNPRV_H__ */
286