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