• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/benchmark/Android.mk b/benchmark/Android.mk
2new file mode 100755
3index 00000000..d48e0d8e
4--- /dev/null
5+++ b/benchmark/Android.mk
6@@ -0,0 +1,53 @@
7+local_target_dir := $(TARGET_OUT_DATA)/local/tmp
8+
9+LOCAL_PATH:= $(call my-dir)
10+
11+include $(CLEAR_VARS)
12+
13+LOCAL_C_INCLUDES := \
14+    $(LOCAL_PATH)/feature_mos/src \
15+    $(LOCAL_PATH)/feature_stab/src \
16+    $(LOCAL_PATH)/feature_stab/db_vlvm
17+
18+LOCAL_SRC_FILES := benchmark.cpp \
19+	feature_mos/src/mosaic/ImageUtils.cpp \
20+    feature_mos/src/mosaic/Mosaic.cpp \
21+    feature_mos/src/mosaic/AlignFeatures.cpp \
22+    feature_mos/src/mosaic/Blend.cpp \
23+    feature_mos/src/mosaic/Pyramid.cpp \
24+    feature_mos/src/mosaic/trsMatrix.cpp \
25+    feature_mos/src/mosaic/Delaunay.cpp \
26+    feature_mos/src/mosaic_renderer/Renderer.cpp \
27+    feature_mos/src/mosaic_renderer/WarpRenderer.cpp \
28+    feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp \
29+    feature_mos/src/mosaic_renderer/YVURenderer.cpp \
30+    feature_mos/src/mosaic_renderer/FrameBuffer.cpp \
31+    feature_stab/db_vlvm/db_rob_image_homography.cpp \
32+    feature_stab/db_vlvm/db_feature_detection.cpp \
33+    feature_stab/db_vlvm/db_image_homography.cpp \
34+    feature_stab/db_vlvm/db_framestitching.cpp \
35+    feature_stab/db_vlvm/db_feature_matching.cpp \
36+    feature_stab/db_vlvm/db_utilities.cpp \
37+    feature_stab/db_vlvm/db_utilities_camera.cpp \
38+    feature_stab/db_vlvm/db_utilities_indexing.cpp \
39+    feature_stab/db_vlvm/db_utilities_linalg.cpp \
40+    feature_stab/db_vlvm/db_utilities_poly.cpp \
41+    feature_stab/src/dbreg/dbstabsmooth.cpp \
42+    feature_stab/src/dbreg/dbreg.cpp \
43+    feature_stab/src/dbreg/vp_motionmodel.c
44+
45+LOCAL_CFLAGS := -O3 -DNDEBUG -Wno-unused-parameter -Wno-maybe-uninitialized
46+LOCAL_CFLAGS += $(CFLAGS_FOR_BENCH_SUITE)
47+LOCAL_LDFLAGS := $(LDFLAGS_FOR_BENCH_SUITE)
48+LOCAL_CPPFLAGS := -std=c++98
49+LOCAL_MODULE_TAGS := tests
50+LOCAL_MODULE := panorama_bench
51+LOCAL_MODULE_STEM_32 := panorama_bench
52+LOCAL_MODULE_STEM_64 := panorama_bench64
53+LOCAL_MULTILIB := both
54+LOCAL_MODULE_PATH := $(local_target_dir)
55+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
56+LOCAL_FORCE_STATIC_EXECUTABLE := true
57+LOCAL_STATIC_LIBRARIES := libc libm
58+
59+include $(BUILD_EXECUTABLE)
60diff --git a/benchmark/NOTICE b/benchmark/NOTICE
61new file mode 100644
62index 00000000..7317ae2a
63--- /dev/null
64+++ b/benchmark/NOTICE
65@@ -0,0 +1,190 @@
66+
67+   Copyright (c) 2005-2011, The Android Open Source Project
68+
69+   Licensed under the Apache License, Version 2.0 (the "License");
70+   you may not use this file except in compliance with the License.
71+
72+   Unless required by applicable law or agreed to in writing, software
73+   distributed under the License is distributed on an "AS IS" BASIS,
74+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75+   See the License for the specific language governing permissions and
76+   limitations under the License.
77+
78+
79+                                 Apache License
80+                           Version 2.0, January 2004
81+                        http://www.apache.org/licenses/
82+
83+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
84+
85+   1. Definitions.
86+
87+      "License" shall mean the terms and conditions for use, reproduction,
88+      and distribution as defined by Sections 1 through 9 of this document.
89+
90+      "Licensor" shall mean the copyright owner or entity authorized by
91+      the copyright owner that is granting the License.
92+
93+      "Legal Entity" shall mean the union of the acting entity and all
94+      other entities that control, are controlled by, or are under common
95+      control with that entity. For the purposes of this definition,
96+      "control" means (i) the power, direct or indirect, to cause the
97+      direction or management of such entity, whether by contract or
98+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
99+      outstanding shares, or (iii) beneficial ownership of such entity.
100+
101+      "You" (or "Your") shall mean an individual or Legal Entity
102+      exercising permissions granted by this License.
103+
104+      "Source" form shall mean the preferred form for making modifications,
105+      including but not limited to software source code, documentation
106+      source, and configuration files.
107+
108+      "Object" form shall mean any form resulting from mechanical
109+      transformation or translation of a Source form, including but
110+      not limited to compiled object code, generated documentation,
111+      and conversions to other media types.
112+
113+      "Work" shall mean the work of authorship, whether in Source or
114+      Object form, made available under the License, as indicated by a
115+      copyright notice that is included in or attached to the work
116+      (an example is provided in the Appendix below).
117+
118+      "Derivative Works" shall mean any work, whether in Source or Object
119+      form, that is based on (or derived from) the Work and for which the
120+      editorial revisions, annotations, elaborations, or other modifications
121+      represent, as a whole, an original work of authorship. For the purposes
122+      of this License, Derivative Works shall not include works that remain
123+      separable from, or merely link (or bind by name) to the interfaces of,
124+      the Work and Derivative Works thereof.
125+
126+      "Contribution" shall mean any work of authorship, including
127+      the original version of the Work and any modifications or additions
128+      to that Work or Derivative Works thereof, that is intentionally
129+      submitted to Licensor for inclusion in the Work by the copyright owner
130+      or by an individual or Legal Entity authorized to submit on behalf of
131+      the copyright owner. For the purposes of this definition, "submitted"
132+      means any form of electronic, verbal, or written communication sent
133+      to the Licensor or its representatives, including but not limited to
134+      communication on electronic mailing lists, source code control systems,
135+      and issue tracking systems that are managed by, or on behalf of, the
136+      Licensor for the purpose of discussing and improving the Work, but
137+      excluding communication that is conspicuously marked or otherwise
138+      designated in writing by the copyright owner as "Not a Contribution."
139+
140+      "Contributor" shall mean Licensor and any individual or Legal Entity
141+      on behalf of whom a Contribution has been received by Licensor and
142+      subsequently incorporated within the Work.
143+
144+   2. Grant of Copyright License. Subject to the terms and conditions of
145+      this License, each Contributor hereby grants to You a perpetual,
146+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
147+      copyright license to reproduce, prepare Derivative Works of,
148+      publicly display, publicly perform, sublicense, and distribute the
149+      Work and such Derivative Works in Source or Object form.
150+
151+   3. Grant of Patent License. Subject to the terms and conditions of
152+      this License, each Contributor hereby grants to You a perpetual,
153+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
154+      (except as stated in this section) patent license to make, have made,
155+      use, offer to sell, sell, import, and otherwise transfer the Work,
156+      where such license applies only to those patent claims licensable
157+      by such Contributor that are necessarily infringed by their
158+      Contribution(s) alone or by combination of their Contribution(s)
159+      with the Work to which such Contribution(s) was submitted. If You
160+      institute patent litigation against any entity (including a
161+      cross-claim or counterclaim in a lawsuit) alleging that the Work
162+      or a Contribution incorporated within the Work constitutes direct
163+      or contributory patent infringement, then any patent licenses
164+      granted to You under this License for that Work shall terminate
165+      as of the date such litigation is filed.
166+
167+   4. Redistribution. You may reproduce and distribute copies of the
168+      Work or Derivative Works thereof in any medium, with or without
169+      modifications, and in Source or Object form, provided that You
170+      meet the following conditions:
171+
172+      (a) You must give any other recipients of the Work or
173+          Derivative Works a copy of this License; and
174+
175+      (b) You must cause any modified files to carry prominent notices
176+          stating that You changed the files; and
177+
178+      (c) You must retain, in the Source form of any Derivative Works
179+          that You distribute, all copyright, patent, trademark, and
180+          attribution notices from the Source form of the Work,
181+          excluding those notices that do not pertain to any part of
182+          the Derivative Works; and
183+
184+      (d) If the Work includes a "NOTICE" text file as part of its
185+          distribution, then any Derivative Works that You distribute must
186+          include a readable copy of the attribution notices contained
187+          within such NOTICE file, excluding those notices that do not
188+          pertain to any part of the Derivative Works, in at least one
189+          of the following places: within a NOTICE text file distributed
190+          as part of the Derivative Works; within the Source form or
191+          documentation, if provided along with the Derivative Works; or,
192+          within a display generated by the Derivative Works, if and
193+          wherever such third-party notices normally appear. The contents
194+          of the NOTICE file are for informational purposes only and
195+          do not modify the License. You may add Your own attribution
196+          notices within Derivative Works that You distribute, alongside
197+          or as an addendum to the NOTICE text from the Work, provided
198+          that such additional attribution notices cannot be construed
199+          as modifying the License.
200+
201+      You may add Your own copyright statement to Your modifications and
202+      may provide additional or different license terms and conditions
203+      for use, reproduction, or distribution of Your modifications, or
204+      for any such Derivative Works as a whole, provided Your use,
205+      reproduction, and distribution of the Work otherwise complies with
206+      the conditions stated in this License.
207+
208+   5. Submission of Contributions. Unless You explicitly state otherwise,
209+      any Contribution intentionally submitted for inclusion in the Work
210+      by You to the Licensor shall be under the terms and conditions of
211+      this License, without any additional terms or conditions.
212+      Notwithstanding the above, nothing herein shall supersede or modify
213+      the terms of any separate license agreement you may have executed
214+      with Licensor regarding such Contributions.
215+
216+   6. Trademarks. This License does not grant permission to use the trade
217+      names, trademarks, service marks, or product names of the Licensor,
218+      except as required for reasonable and customary use in describing the
219+      origin of the Work and reproducing the content of the NOTICE file.
220+
221+   7. Disclaimer of Warranty. Unless required by applicable law or
222+      agreed to in writing, Licensor provides the Work (and each
223+      Contributor provides its Contributions) on an "AS IS" BASIS,
224+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
225+      implied, including, without limitation, any warranties or conditions
226+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
227+      PARTICULAR PURPOSE. You are solely responsible for determining the
228+      appropriateness of using or redistributing the Work and assume any
229+      risks associated with Your exercise of permissions under this License.
230+
231+   8. Limitation of Liability. In no event and under no legal theory,
232+      whether in tort (including negligence), contract, or otherwise,
233+      unless required by applicable law (such as deliberate and grossly
234+      negligent acts) or agreed to in writing, shall any Contributor be
235+      liable to You for damages, including any direct, indirect, special,
236+      incidental, or consequential damages of any character arising as a
237+      result of this License or out of the use or inability to use the
238+      Work (including but not limited to damages for loss of goodwill,
239+      work stoppage, computer failure or malfunction, or any and all
240+      other commercial damages or losses), even if such Contributor
241+      has been advised of the possibility of such damages.
242+
243+   9. Accepting Warranty or Additional Liability. While redistributing
244+      the Work or Derivative Works thereof, You may choose to offer,
245+      and charge a fee for, acceptance of support, warranty, indemnity,
246+      or other liability obligations and/or rights consistent with this
247+      License. However, in accepting such obligations, You may act only
248+      on Your own behalf and on Your sole responsibility, not on behalf
249+      of any other Contributor, and only if You agree to indemnify,
250+      defend, and hold each Contributor harmless for any liability
251+      incurred by, or claims asserted against, such Contributor by reason
252+      of your accepting any such warranty or additional liability.
253+
254+   END OF TERMS AND CONDITIONS
255+
256diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp
257new file mode 100755
258index 00000000..2a6440f4
259--- /dev/null
260+++ b/benchmark/benchmark.cpp
261@@ -0,0 +1,131 @@
262+/*
263+ * Copyright (C) 2012 The Android Open Source Project
264+ *
265+ * Licensed under the Apache License, Version 2.0 (the "License");
266+ * you may not use this file except in compliance with the License.
267+ * You may obtain a copy of the License at
268+ *
269+ *      http://www.apache.org/licenses/LICENSE-2.0
270+ *
271+ * Unless required by applicable law or agreed to in writing, software
272+ * distributed under the License is distributed on an "AS IS" BASIS,
273+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
274+ * See the License for the specific language governing permissions and
275+ * limitations under the License.
276+ */
277+
278+#include <time.h>
279+#include <sys/types.h>
280+#include <sys/stat.h>
281+#include <unistd.h>
282+
283+#include "mosaic/Mosaic.h"
284+#include "mosaic/ImageUtils.h"
285+
286+#define MAX_FRAMES 200
287+#define KERNEL_ITERATIONS 10
288+
289+const int blendingType = Blend::BLEND_TYPE_HORZ;
290+const int stripType = Blend::STRIP_TYPE_WIDE;
291+
292+ImageType yvuFrames[MAX_FRAMES];
293+
294+int loadImages(const char* basename, int &width, int &height)
295+{
296+    char filename[512];
297+    struct stat filestat;
298+    int i;
299+
300+    for (i = 0; i < MAX_FRAMES; i++) {
301+        sprintf(filename, "%s_%03d.ppm", basename, i + 1);
302+        if (stat(filename, &filestat) != 0) break;
303+        ImageType rgbFrame = ImageUtils::readBinaryPPM(filename, width, height);
304+        yvuFrames[i] = ImageUtils::allocateImage(width, height,
305+                                ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
306+        ImageUtils::rgb2yvu(yvuFrames[i], rgbFrame, width, height);
307+        ImageUtils::freeImage(rgbFrame);
308+    }
309+    return i;
310+}
311+
312+int main(int argc, char **argv)
313+{
314+    struct timespec t1, t2, t3;
315+
316+    int width, height;
317+    float totalElapsedTime = 0;
318+
319+    const char *basename;
320+    const char *filename;
321+
322+    if (argc != 3) {
323+        printf("Usage: %s input_dir output_filename\n", argv[0]);
324+        return 0;
325+    } else {
326+        basename = argv[1];
327+        filename = argv[2];
328+    }
329+
330+    // Load the images outside the computational kernel
331+    int totalFrames = loadImages(basename, width, height);
332+
333+    if (totalFrames == 0) {
334+        printf("Image files not found. Make sure %s exists.\n",
335+               basename);
336+        return 1;
337+    }
338+
339+    printf("%d frames loaded\n", totalFrames);
340+
341+
342+    // Interesting stuff is here
343+    for (int iteration = 0; iteration < KERNEL_ITERATIONS; iteration++)  {
344+        Mosaic mosaic;
345+
346+        mosaic.initialize(blendingType, stripType, width, height, -1, false, 0);
347+
348+        clock_gettime(CLOCK_MONOTONIC, &t1);
349+        for (int i = 0; i < totalFrames; i++) {
350+            mosaic.addFrame(yvuFrames[i]);
351+        }
352+        clock_gettime(CLOCK_MONOTONIC, &t2);
353+
354+        float progress = 0.0;
355+        bool cancelComputation = false;
356+
357+        mosaic.createMosaic(progress, cancelComputation);
358+
359+        int mosaicWidth, mosaicHeight;
360+        ImageType resultYVU = mosaic.getMosaic(mosaicWidth, mosaicHeight);
361+
362+        ImageType imageRGB = ImageUtils::allocateImage(
363+            mosaicWidth, mosaicHeight, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
364+
365+        clock_gettime(CLOCK_MONOTONIC, &t3);
366+
367+        float elapsedTime =
368+            (t3.tv_sec - t1.tv_sec) + (t3.tv_nsec - t1.tv_nsec)/1e9;
369+        float addImageTime =
370+            (t2.tv_sec - t1.tv_sec) + (t2.tv_nsec - t1.tv_nsec)/1e9;
371+        float stitchImageTime =
372+            (t3.tv_sec - t2.tv_sec) + (t3.tv_nsec - t2.tv_nsec)/1e9;
373+
374+        totalElapsedTime += elapsedTime;
375+
376+        printf("Iteration %d: %dx%d moasic created: "
377+               "%.2f seconds (%.2f + %.2f)\n",
378+               iteration, mosaicWidth, mosaicHeight,
379+               elapsedTime, addImageTime, stitchImageTime);
380+
381+        // Write the output only once for correctness check
382+        if (iteration == 0) {
383+            ImageUtils::yvu2rgb(imageRGB, resultYVU, mosaicWidth,
384+                                mosaicHeight);
385+            ImageUtils::writeBinaryPPM(imageRGB, filename, mosaicWidth,
386+                                       mosaicHeight);
387+        }
388+    }
389+    printf("Total elapsed time: %.2f seconds\n", totalElapsedTime);
390+
391+    return 0;
392+}
393diff --git a/benchmark/feature_mos/doc/Readme.txt b/benchmark/feature_mos/doc/Readme.txt
394new file mode 100644
395index 00000000..83ce165e
396--- /dev/null
397+++ b/benchmark/feature_mos/doc/Readme.txt
398@@ -0,0 +1,3 @@
399+To generate the html docs, execute
400+doxygen feature_mos_API_doxyfile
401+
402diff --git a/benchmark/feature_mos/doc/feature_mos_API_doxyfile b/benchmark/feature_mos/doc/feature_mos_API_doxyfile
403new file mode 100755
404index 00000000..dca8c8c0
405--- /dev/null
406+++ b/benchmark/feature_mos/doc/feature_mos_API_doxyfile
407@@ -0,0 +1,1557 @@
408+# Doxyfile 1.6.1
409+
410+# This file describes the settings to be used by the documentation system
411+# doxygen (www.doxygen.org) for a project
412+#
413+# All text after a hash (#) is considered a comment and will be ignored
414+# The format is:
415+#       TAG = value [value, ...]
416+# For lists items can also be appended using:
417+#       TAG += value [value, ...]
418+# Values that contain spaces should be placed between quotes (" ")
419+
420+#---------------------------------------------------------------------------
421+# Project related configuration options
422+#---------------------------------------------------------------------------
423+
424+# This tag specifies the encoding used for all characters in the config file
425+# that follow. The default is UTF-8 which is also the encoding used for all
426+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
427+# iconv built into libc) for the transcoding. See
428+# http://www.gnu.org/software/libiconv for the list of possible encodings.
429+
430+DOXYFILE_ENCODING      = UTF-8
431+
432+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
433+# by quotes) that should identify the project.
434+
435+PROJECT_NAME           =
436+
437+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
438+# This could be handy for archiving the generated documentation or
439+# if some version control system is used.
440+
441+PROJECT_NUMBER         =
442+
443+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
444+# base path where the generated documentation will be put.
445+# If a relative path is entered, it will be relative to the location
446+# where doxygen was started. If left blank the current directory will be used.
447+
448+OUTPUT_DIRECTORY       = .
449+
450+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
451+# 4096 sub-directories (in 2 levels) under the output directory of each output
452+# format and will distribute the generated files over these directories.
453+# Enabling this option can be useful when feeding doxygen a huge amount of
454+# source files, where putting all generated files in the same directory would
455+# otherwise cause performance problems for the file system.
456+
457+CREATE_SUBDIRS         = NO
458+
459+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
460+# documentation generated by doxygen is written. Doxygen will use this
461+# information to generate all constant output in the proper language.
462+# The default language is English, other supported languages are:
463+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
464+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
465+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
466+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
467+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
468+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
469+
470+OUTPUT_LANGUAGE        = English
471+
472+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
473+# include brief member descriptions after the members that are listed in
474+# the file and class documentation (similar to JavaDoc).
475+# Set to NO to disable this.
476+
477+BRIEF_MEMBER_DESC      = YES
478+
479+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
480+# the brief description of a member or function before the detailed description.
481+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
482+# brief descriptions will be completely suppressed.
483+
484+REPEAT_BRIEF           = YES
485+
486+# This tag implements a quasi-intelligent brief description abbreviator
487+# that is used to form the text in various listings. Each string
488+# in this list, if found as the leading text of the brief description, will be
489+# stripped from the text and the result after processing the whole list, is
490+# used as the annotated text. Otherwise, the brief description is used as-is.
491+# If left blank, the following values are used ("$name" is automatically
492+# replaced with the name of the entity): "The $name class" "The $name widget"
493+# "The $name file" "is" "provides" "specifies" "contains"
494+# "represents" "a" "an" "the"
495+
496+ABBREVIATE_BRIEF       = "The $name class" \
497+                         "The $name widget" \
498+                         "The $name file" \
499+                         is \
500+                         provides \
501+                         specifies \
502+                         contains \
503+                         represents \
504+                         a \
505+                         an \
506+                         the
507+
508+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
509+# Doxygen will generate a detailed section even if there is only a brief
510+# description.
511+
512+ALWAYS_DETAILED_SEC    = NO
513+
514+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
515+# inherited members of a class in the documentation of that class as if those
516+# members were ordinary class members. Constructors, destructors and assignment
517+# operators of the base classes will not be shown.
518+
519+INLINE_INHERITED_MEMB  = NO
520+
521+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
522+# path before files name in the file list and in the header files. If set
523+# to NO the shortest path that makes the file name unique will be used.
524+
525+FULL_PATH_NAMES        = YES
526+
527+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
528+# can be used to strip a user-defined part of the path. Stripping is
529+# only done if one of the specified strings matches the left-hand part of
530+# the path. The tag can be used to show relative paths in the file list.
531+# If left blank the directory from which doxygen is run is used as the
532+# path to strip.
533+
534+STRIP_FROM_PATH        = /Users/dimitri/doxygen/mail/1.5.7/doxywizard/
535+
536+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
537+# the path mentioned in the documentation of a class, which tells
538+# the reader which header file to include in order to use a class.
539+# If left blank only the name of the header file containing the class
540+# definition is used. Otherwise one should specify the include paths that
541+# are normally passed to the compiler using the -I flag.
542+
543+STRIP_FROM_INC_PATH    =
544+
545+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
546+# (but less readable) file names. This can be useful is your file systems
547+# doesn't support long names like on DOS, Mac, or CD-ROM.
548+
549+SHORT_NAMES            = NO
550+
551+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
552+# will interpret the first line (until the first dot) of a JavaDoc-style
553+# comment as the brief description. If set to NO, the JavaDoc
554+# comments will behave just like regular Qt-style comments
555+# (thus requiring an explicit @brief command for a brief description.)
556+
557+JAVADOC_AUTOBRIEF      = NO
558+
559+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
560+# interpret the first line (until the first dot) of a Qt-style
561+# comment as the brief description. If set to NO, the comments
562+# will behave just like regular Qt-style comments (thus requiring
563+# an explicit \brief command for a brief description.)
564+
565+QT_AUTOBRIEF           = NO
566+
567+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
568+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
569+# comments) as a brief description. This used to be the default behaviour.
570+# The new default is to treat a multi-line C++ comment block as a detailed
571+# description. Set this tag to YES if you prefer the old behaviour instead.
572+
573+MULTILINE_CPP_IS_BRIEF = NO
574+
575+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
576+# member inherits the documentation from any documented member that it
577+# re-implements.
578+
579+INHERIT_DOCS           = YES
580+
581+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
582+# a new page for each member. If set to NO, the documentation of a member will
583+# be part of the file/class/namespace that contains it.
584+
585+SEPARATE_MEMBER_PAGES  = NO
586+
587+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
588+# Doxygen uses this value to replace tabs by spaces in code fragments.
589+
590+TAB_SIZE               = 8
591+
592+# This tag can be used to specify a number of aliases that acts
593+# as commands in the documentation. An alias has the form "name=value".
594+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
595+# put the command \sideeffect (or @sideeffect) in the documentation, which
596+# will result in a user-defined paragraph with heading "Side Effects:".
597+# You can put \n's in the value part of an alias to insert newlines.
598+
599+ALIASES                =
600+
601+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
602+# sources only. Doxygen will then generate output that is more tailored for C.
603+# For instance, some of the names that are used will be different. The list
604+# of all members will be omitted, etc.
605+
606+OPTIMIZE_OUTPUT_FOR_C  = NO
607+
608+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
609+# sources only. Doxygen will then generate output that is more tailored for
610+# Java. For instance, namespaces will be presented as packages, qualified
611+# scopes will look different, etc.
612+
613+OPTIMIZE_OUTPUT_JAVA   = NO
614+
615+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
616+# sources only. Doxygen will then generate output that is more tailored for
617+# Fortran.
618+
619+OPTIMIZE_FOR_FORTRAN   = NO
620+
621+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
622+# sources. Doxygen will then generate output that is tailored for
623+# VHDL.
624+
625+OPTIMIZE_OUTPUT_VHDL   = NO
626+
627+# Doxygen selects the parser to use depending on the extension of the files it parses.
628+# With this tag you can assign which parser to use for a given extension.
629+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
630+# The format is ext=language, where ext is a file extension, and language is one of
631+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
632+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
633+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
634+# use: inc=Fortran f=C. Note that for custom extensions you also need to set
635+# FILE_PATTERNS otherwise the files are not read by doxygen.
636+
637+EXTENSION_MAPPING      =
638+
639+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
640+# to include (a tag file for) the STL sources as input, then you should
641+# set this tag to YES in order to let doxygen match functions declarations and
642+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
643+# func(std::string) {}). This also make the inheritance and collaboration
644+# diagrams that involve STL classes more complete and accurate.
645+
646+BUILTIN_STL_SUPPORT    = NO
647+
648+# If you use Microsoft's C++/CLI language, you should set this option to YES to
649+# enable parsing support.
650+
651+CPP_CLI_SUPPORT        = NO
652+
653+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
654+# Doxygen will parse them like normal C++ but will assume all classes use public
655+# instead of private inheritance when no explicit protection keyword is present.
656+
657+SIP_SUPPORT            = NO
658+
659+# For Microsoft's IDL there are propget and propput attributes to indicate getter
660+# and setter methods for a property. Setting this option to YES (the default)
661+# will make doxygen to replace the get and set methods by a property in the
662+# documentation. This will only work if the methods are indeed getting or
663+# setting a simple type. If this is not the case, or you want to show the
664+# methods anyway, you should set this option to NO.
665+
666+IDL_PROPERTY_SUPPORT   = YES
667+
668+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
669+# tag is set to YES, then doxygen will reuse the documentation of the first
670+# member in the group (if any) for the other members of the group. By default
671+# all members of a group must be documented explicitly.
672+
673+DISTRIBUTE_GROUP_DOC   = NO
674+
675+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
676+# the same type (for instance a group of public functions) to be put as a
677+# subgroup of that type (e.g. under the Public Functions section). Set it to
678+# NO to prevent subgrouping. Alternatively, this can be done per class using
679+# the \nosubgrouping command.
680+
681+SUBGROUPING            = YES
682+
683+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
684+# is documented as struct, union, or enum with the name of the typedef. So
685+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
686+# with name TypeT. When disabled the typedef will appear as a member of a file,
687+# namespace, or class. And the struct will be named TypeS. This can typically
688+# be useful for C code in case the coding convention dictates that all compound
689+# types are typedef'ed and only the typedef is referenced, never the tag name.
690+
691+TYPEDEF_HIDES_STRUCT   = NO
692+
693+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
694+# determine which symbols to keep in memory and which to flush to disk.
695+# When the cache is full, less often used symbols will be written to disk.
696+# For small to medium size projects (<1000 input files) the default value is
697+# probably good enough. For larger projects a too small cache size can cause
698+# doxygen to be busy swapping symbols to and from disk most of the time
699+# causing a significant performance penality.
700+# If the system has enough physical memory increasing the cache will improve the
701+# performance by keeping more symbols in memory. Note that the value works on
702+# a logarithmic scale so increasing the size by one will rougly double the
703+# memory usage. The cache size is given by this formula:
704+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
705+# corresponding to a cache size of 2^16 = 65536 symbols
706+
707+SYMBOL_CACHE_SIZE      = 0
708+
709+#---------------------------------------------------------------------------
710+# Build related configuration options
711+#---------------------------------------------------------------------------
712+
713+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
714+# documentation are documented, even if no documentation was available.
715+# Private class members and static file members will be hidden unless
716+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
717+
718+EXTRACT_ALL            = NO
719+
720+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
721+# will be included in the documentation.
722+
723+EXTRACT_PRIVATE        = NO
724+
725+# If the EXTRACT_STATIC tag is set to YES all static members of a file
726+# will be included in the documentation.
727+
728+EXTRACT_STATIC         = NO
729+
730+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
731+# defined locally in source files will be included in the documentation.
732+# If set to NO only classes defined in header files are included.
733+
734+EXTRACT_LOCAL_CLASSES  = YES
735+
736+# This flag is only useful for Objective-C code. When set to YES local
737+# methods, which are defined in the implementation section but not in
738+# the interface are included in the documentation.
739+# If set to NO (the default) only methods in the interface are included.
740+
741+EXTRACT_LOCAL_METHODS  = NO
742+
743+# If this flag is set to YES, the members of anonymous namespaces will be
744+# extracted and appear in the documentation as a namespace called
745+# 'anonymous_namespace{file}', where file will be replaced with the base
746+# name of the file that contains the anonymous namespace. By default
747+# anonymous namespace are hidden.
748+
749+EXTRACT_ANON_NSPACES   = NO
750+
751+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
752+# undocumented members of documented classes, files or namespaces.
753+# If set to NO (the default) these members will be included in the
754+# various overviews, but no documentation section is generated.
755+# This option has no effect if EXTRACT_ALL is enabled.
756+
757+HIDE_UNDOC_MEMBERS     = NO
758+
759+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
760+# undocumented classes that are normally visible in the class hierarchy.
761+# If set to NO (the default) these classes will be included in the various
762+# overviews. This option has no effect if EXTRACT_ALL is enabled.
763+
764+HIDE_UNDOC_CLASSES     = NO
765+
766+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
767+# friend (class|struct|union) declarations.
768+# If set to NO (the default) these declarations will be included in the
769+# documentation.
770+
771+HIDE_FRIEND_COMPOUNDS  = NO
772+
773+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
774+# documentation blocks found inside the body of a function.
775+# If set to NO (the default) these blocks will be appended to the
776+# function's detailed documentation block.
777+
778+HIDE_IN_BODY_DOCS      = NO
779+
780+# The INTERNAL_DOCS tag determines if documentation
781+# that is typed after a \internal command is included. If the tag is set
782+# to NO (the default) then the documentation will be excluded.
783+# Set it to YES to include the internal documentation.
784+
785+INTERNAL_DOCS          = NO
786+
787+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
788+# file names in lower-case letters. If set to YES upper-case letters are also
789+# allowed. This is useful if you have classes or files whose names only differ
790+# in case and if your file system supports case sensitive file names. Windows
791+# and Mac users are advised to set this option to NO.
792+
793+CASE_SENSE_NAMES       = NO
794+
795+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
796+# will show members with their full class and namespace scopes in the
797+# documentation. If set to YES the scope will be hidden.
798+
799+HIDE_SCOPE_NAMES       = NO
800+
801+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
802+# will put a list of the files that are included by a file in the documentation
803+# of that file.
804+
805+SHOW_INCLUDE_FILES     = YES
806+
807+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
808+# is inserted in the documentation for inline members.
809+
810+INLINE_INFO            = YES
811+
812+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
813+# will sort the (detailed) documentation of file and class members
814+# alphabetically by member name. If set to NO the members will appear in
815+# declaration order.
816+
817+SORT_MEMBER_DOCS       = YES
818+
819+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
820+# brief documentation of file, namespace and class members alphabetically
821+# by member name. If set to NO (the default) the members will appear in
822+# declaration order.
823+
824+SORT_BRIEF_DOCS        = NO
825+
826+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
827+# will sort the (brief and detailed) documentation of class members so that
828+# constructors and destructors are listed first. If set to NO (the default)
829+# the constructors will appear in the respective orders defined by
830+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
831+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
832+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
833+
834+SORT_MEMBERS_CTORS_1ST = NO
835+
836+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
837+# hierarchy of group names into alphabetical order. If set to NO (the default)
838+# the group names will appear in their defined order.
839+
840+SORT_GROUP_NAMES       = NO
841+
842+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
843+# sorted by fully-qualified names, including namespaces. If set to
844+# NO (the default), the class list will be sorted only by class name,
845+# not including the namespace part.
846+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
847+# Note: This option applies only to the class list, not to the
848+# alphabetical list.
849+
850+SORT_BY_SCOPE_NAME     = NO
851+
852+# The GENERATE_TODOLIST tag can be used to enable (YES) or
853+# disable (NO) the todo list. This list is created by putting \todo
854+# commands in the documentation.
855+
856+GENERATE_TODOLIST      = YES
857+
858+# The GENERATE_TESTLIST tag can be used to enable (YES) or
859+# disable (NO) the test list. This list is created by putting \test
860+# commands in the documentation.
861+
862+GENERATE_TESTLIST      = YES
863+
864+# The GENERATE_BUGLIST tag can be used to enable (YES) or
865+# disable (NO) the bug list. This list is created by putting \bug
866+# commands in the documentation.
867+
868+GENERATE_BUGLIST       = YES
869+
870+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
871+# disable (NO) the deprecated list. This list is created by putting
872+# \deprecated commands in the documentation.
873+
874+GENERATE_DEPRECATEDLIST= YES
875+
876+# The ENABLED_SECTIONS tag can be used to enable conditional
877+# documentation sections, marked by \if sectionname ... \endif.
878+
879+ENABLED_SECTIONS       =
880+
881+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
882+# the initial value of a variable or define consists of for it to appear in
883+# the documentation. If the initializer consists of more lines than specified
884+# here it will be hidden. Use a value of 0 to hide initializers completely.
885+# The appearance of the initializer of individual variables and defines in the
886+# documentation can be controlled using \showinitializer or \hideinitializer
887+# command in the documentation regardless of this setting.
888+
889+MAX_INITIALIZER_LINES  = 30
890+
891+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
892+# at the bottom of the documentation of classes and structs. If set to YES the
893+# list will mention the files that were used to generate the documentation.
894+
895+SHOW_USED_FILES        = YES
896+
897+# If the sources in your project are distributed over multiple directories
898+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
899+# in the documentation. The default is NO.
900+
901+SHOW_DIRECTORIES       = NO
902+
903+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
904+# This will remove the Files entry from the Quick Index and from the
905+# Folder Tree View (if specified). The default is YES.
906+
907+SHOW_FILES             = YES
908+
909+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
910+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
911+# and from the Folder Tree View (if specified). The default is YES.
912+
913+SHOW_NAMESPACES        = YES
914+
915+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
916+# doxygen should invoke to get the current version for each file (typically from
917+# the version control system). Doxygen will invoke the program by executing (via
918+# popen()) the command <command> <input-file>, where <command> is the value of
919+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
920+# provided by doxygen. Whatever the program writes to standard output
921+# is used as the file version. See the manual for examples.
922+
923+FILE_VERSION_FILTER    =
924+
925+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
926+# doxygen. The layout file controls the global structure of the generated output files
927+# in an output format independent way. The create the layout file that represents
928+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
929+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
930+# of the layout file.
931+
932+LAYOUT_FILE            =
933+
934+#---------------------------------------------------------------------------
935+# configuration options related to warning and progress messages
936+#---------------------------------------------------------------------------
937+
938+# The QUIET tag can be used to turn on/off the messages that are generated
939+# by doxygen. Possible values are YES and NO. If left blank NO is used.
940+
941+QUIET                  = NO
942+
943+# The WARNINGS tag can be used to turn on/off the warning messages that are
944+# generated by doxygen. Possible values are YES and NO. If left blank
945+# NO is used.
946+
947+WARNINGS               = YES
948+
949+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
950+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
951+# automatically be disabled.
952+
953+WARN_IF_UNDOCUMENTED   = YES
954+
955+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
956+# potential errors in the documentation, such as not documenting some
957+# parameters in a documented function, or documenting parameters that
958+# don't exist or using markup commands wrongly.
959+
960+WARN_IF_DOC_ERROR      = YES
961+
962+# This WARN_NO_PARAMDOC option can be abled to get warnings for
963+# functions that are documented, but have no documentation for their parameters
964+# or return value. If set to NO (the default) doxygen will only warn about
965+# wrong or incomplete parameter documentation, but not about the absence of
966+# documentation.
967+
968+WARN_NO_PARAMDOC       = NO
969+
970+# The WARN_FORMAT tag determines the format of the warning messages that
971+# doxygen can produce. The string should contain the $file, $line, and $text
972+# tags, which will be replaced by the file and line number from which the
973+# warning originated and the warning text. Optionally the format may contain
974+# $version, which will be replaced by the version of the file (if it could
975+# be obtained via FILE_VERSION_FILTER)
976+
977+WARN_FORMAT            = "$file:$line: $text"
978+
979+# The WARN_LOGFILE tag can be used to specify a file to which warning
980+# and error messages should be written. If left blank the output is written
981+# to stderr.
982+
983+WARN_LOGFILE           =
984+
985+#---------------------------------------------------------------------------
986+# configuration options related to the input files
987+#---------------------------------------------------------------------------
988+
989+# The INPUT tag can be used to specify the files and/or directories that contain
990+# documented source files. You may enter file names like "myfile.cpp" or
991+# directories like "/usr/src/myproject". Separate the files or directories
992+# with spaces.
993+
994+INPUT                  = ../src/mosaic/Mosaic.h
995+
996+# This tag can be used to specify the character encoding of the source files
997+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
998+# also the default input encoding. Doxygen uses libiconv (or the iconv built
999+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
1000+# the list of possible encodings.
1001+
1002+INPUT_ENCODING         = UTF-8
1003+
1004+# If the value of the INPUT tag contains directories, you can use the
1005+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
1006+# and *.h) to filter out the source-files in the directories. If left
1007+# blank the following patterns are tested:
1008+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
1009+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
1010+
1011+FILE_PATTERNS          = *.c \
1012+                         *.cc \
1013+                         *.cxx \
1014+                         *.cpp \
1015+                         *.c++ \
1016+                         *.d \
1017+                         *.java \
1018+                         *.ii \
1019+                         *.ixx \
1020+                         *.ipp \
1021+                         *.i++ \
1022+                         *.inl \
1023+                         *.h \
1024+                         *.hh \
1025+                         *.hxx \
1026+                         *.hpp \
1027+                         *.h++ \
1028+                         *.idl \
1029+                         *.odl \
1030+                         *.cs \
1031+                         *.php \
1032+                         *.php3 \
1033+                         *.inc \
1034+                         *.m \
1035+                         *.mm \
1036+                         *.dox \
1037+                         *.py \
1038+                         *.f90 \
1039+                         *.f \
1040+                         *.vhd \
1041+                         *.vhdl
1042+
1043+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
1044+# should be searched for input files as well. Possible values are YES and NO.
1045+# If left blank NO is used.
1046+
1047+RECURSIVE              = NO
1048+
1049+# The EXCLUDE tag can be used to specify files and/or directories that should
1050+# excluded from the INPUT source files. This way you can easily exclude a
1051+# subdirectory from a directory tree whose root is specified with the INPUT tag.
1052+
1053+EXCLUDE                =
1054+
1055+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
1056+# directories that are symbolic links (a Unix filesystem feature) are excluded
1057+# from the input.
1058+
1059+EXCLUDE_SYMLINKS       = NO
1060+
1061+# If the value of the INPUT tag contains directories, you can use the
1062+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
1063+# certain files from those directories. Note that the wildcards are matched
1064+# against the file with absolute path, so to exclude all test directories
1065+# for example use the pattern */test/*
1066+
1067+EXCLUDE_PATTERNS       =
1068+
1069+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
1070+# (namespaces, classes, functions, etc.) that should be excluded from the
1071+# output. The symbol name can be a fully qualified name, a word, or if the
1072+# wildcard * is used, a substring. Examples: ANamespace, AClass,
1073+# AClass::ANamespace, ANamespace::*Test
1074+
1075+EXCLUDE_SYMBOLS        =
1076+
1077+# The EXAMPLE_PATH tag can be used to specify one or more files or
1078+# directories that contain example code fragments that are included (see
1079+# the \include command).
1080+
1081+EXAMPLE_PATH           =
1082+
1083+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
1084+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
1085+# and *.h) to filter out the source-files in the directories. If left
1086+# blank all files are included.
1087+
1088+EXAMPLE_PATTERNS       = *
1089+
1090+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
1091+# searched for input files to be used with the \include or \dontinclude
1092+# commands irrespective of the value of the RECURSIVE tag.
1093+# Possible values are YES and NO. If left blank NO is used.
1094+
1095+EXAMPLE_RECURSIVE      = NO
1096+
1097+# The IMAGE_PATH tag can be used to specify one or more files or
1098+# directories that contain image that are included in the documentation (see
1099+# the \image command).
1100+
1101+IMAGE_PATH             =
1102+
1103+# The INPUT_FILTER tag can be used to specify a program that doxygen should
1104+# invoke to filter for each input file. Doxygen will invoke the filter program
1105+# by executing (via popen()) the command <filter> <input-file>, where <filter>
1106+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
1107+# input file. Doxygen will then use the output that the filter program writes
1108+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
1109+# ignored.
1110+
1111+INPUT_FILTER           =
1112+
1113+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
1114+# basis.  Doxygen will compare the file name with each pattern and apply the
1115+# filter if there is a match.  The filters are a list of the form:
1116+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
1117+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
1118+# is applied to all files.
1119+
1120+FILTER_PATTERNS        =
1121+
1122+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
1123+# INPUT_FILTER) will be used to filter the input files when producing source
1124+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
1125+
1126+FILTER_SOURCE_FILES    = NO
1127+
1128+#---------------------------------------------------------------------------
1129+# configuration options related to source browsing
1130+#---------------------------------------------------------------------------
1131+
1132+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
1133+# be generated. Documented entities will be cross-referenced with these sources.
1134+# Note: To get rid of all source code in the generated output, make sure also
1135+# VERBATIM_HEADERS is set to NO.
1136+
1137+SOURCE_BROWSER         = NO
1138+
1139+# Setting the INLINE_SOURCES tag to YES will include the body
1140+# of functions and classes directly in the documentation.
1141+
1142+INLINE_SOURCES         = NO
1143+
1144+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
1145+# doxygen to hide any special comment blocks from generated source code
1146+# fragments. Normal C and C++ comments will always remain visible.
1147+
1148+STRIP_CODE_COMMENTS    = YES
1149+
1150+# If the REFERENCED_BY_RELATION tag is set to YES
1151+# then for each documented function all documented
1152+# functions referencing it will be listed.
1153+
1154+REFERENCED_BY_RELATION = NO
1155+
1156+# If the REFERENCES_RELATION tag is set to YES
1157+# then for each documented function all documented entities
1158+# called/used by that function will be listed.
1159+
1160+REFERENCES_RELATION    = NO
1161+
1162+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
1163+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
1164+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
1165+# link to the source code.  Otherwise they will link to the documentation.
1166+
1167+REFERENCES_LINK_SOURCE = YES
1168+
1169+# If the USE_HTAGS tag is set to YES then the references to source code
1170+# will point to the HTML generated by the htags(1) tool instead of doxygen
1171+# built-in source browser. The htags tool is part of GNU's global source
1172+# tagging system (see http://www.gnu.org/software/global/global.html). You
1173+# will need version 4.8.6 or higher.
1174+
1175+USE_HTAGS              = NO
1176+
1177+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
1178+# will generate a verbatim copy of the header file for each class for
1179+# which an include is specified. Set to NO to disable this.
1180+
1181+VERBATIM_HEADERS       = YES
1182+
1183+#---------------------------------------------------------------------------
1184+# configuration options related to the alphabetical class index
1185+#---------------------------------------------------------------------------
1186+
1187+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
1188+# of all compounds will be generated. Enable this if the project
1189+# contains a lot of classes, structs, unions or interfaces.
1190+
1191+ALPHABETICAL_INDEX     = NO
1192+
1193+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
1194+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
1195+# in which this list will be split (can be a number in the range [1..20])
1196+
1197+COLS_IN_ALPHA_INDEX    = 5
1198+
1199+# In case all classes in a project start with a common prefix, all
1200+# classes will be put under the same header in the alphabetical index.
1201+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
1202+# should be ignored while generating the index headers.
1203+
1204+IGNORE_PREFIX          =
1205+
1206+#---------------------------------------------------------------------------
1207+# configuration options related to the HTML output
1208+#---------------------------------------------------------------------------
1209+
1210+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
1211+# generate HTML output.
1212+
1213+GENERATE_HTML          = YES
1214+
1215+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
1216+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1217+# put in front of it. If left blank `html' will be used as the default path.
1218+
1219+HTML_OUTPUT            = html
1220+
1221+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
1222+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
1223+# doxygen will generate files with .html extension.
1224+
1225+HTML_FILE_EXTENSION    = .html
1226+
1227+# The HTML_HEADER tag can be used to specify a personal HTML header for
1228+# each generated HTML page. If it is left blank doxygen will generate a
1229+# standard header.
1230+
1231+HTML_HEADER            =
1232+
1233+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
1234+# each generated HTML page. If it is left blank doxygen will generate a
1235+# standard footer.
1236+
1237+HTML_FOOTER            =
1238+
1239+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
1240+# style sheet that is used by each HTML page. It can be used to
1241+# fine-tune the look of the HTML output. If the tag is left blank doxygen
1242+# will generate a default style sheet. Note that doxygen will try to copy
1243+# the style sheet file to the HTML output directory, so don't put your own
1244+# stylesheet in the HTML output directory as well, or it will be erased!
1245+
1246+HTML_STYLESHEET        =
1247+
1248+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
1249+# files or namespaces will be aligned in HTML using tables. If set to
1250+# NO a bullet list will be used.
1251+
1252+HTML_ALIGN_MEMBERS     = YES
1253+
1254+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1255+# documentation will contain sections that can be hidden and shown after the
1256+# page has loaded. For this to work a browser that supports
1257+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
1258+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
1259+
1260+HTML_DYNAMIC_SECTIONS  = NO
1261+
1262+# If the GENERATE_DOCSET tag is set to YES, additional index files
1263+# will be generated that can be used as input for Apple's Xcode 3
1264+# integrated development environment, introduced with OSX 10.5 (Leopard).
1265+# To create a documentation set, doxygen will generate a Makefile in the
1266+# HTML output directory. Running make will produce the docset in that
1267+# directory and running "make install" will install the docset in
1268+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
1269+# it at startup.
1270+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
1271+
1272+GENERATE_DOCSET        = NO
1273+
1274+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
1275+# feed. A documentation feed provides an umbrella under which multiple
1276+# documentation sets from a single provider (such as a company or product suite)
1277+# can be grouped.
1278+
1279+DOCSET_FEEDNAME        = "Doxygen generated docs"
1280+
1281+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
1282+# should uniquely identify the documentation set bundle. This should be a
1283+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
1284+# will append .docset to the name.
1285+
1286+DOCSET_BUNDLE_ID       = org.doxygen.Project
1287+
1288+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
1289+# will be generated that can be used as input for tools like the
1290+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
1291+# of the generated HTML documentation.
1292+
1293+GENERATE_HTMLHELP      = NO
1294+
1295+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
1296+# be used to specify the file name of the resulting .chm file. You
1297+# can add a path in front of the file if the result should not be
1298+# written to the html output directory.
1299+
1300+CHM_FILE               =
1301+
1302+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
1303+# be used to specify the location (absolute path including file name) of
1304+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
1305+# the HTML help compiler on the generated index.hhp.
1306+
1307+HHC_LOCATION           =
1308+
1309+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
1310+# controls if a separate .chi index file is generated (YES) or that
1311+# it should be included in the master .chm file (NO).
1312+
1313+GENERATE_CHI           = NO
1314+
1315+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
1316+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
1317+# content.
1318+
1319+CHM_INDEX_ENCODING     =
1320+
1321+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
1322+# controls whether a binary table of contents is generated (YES) or a
1323+# normal table of contents (NO) in the .chm file.
1324+
1325+BINARY_TOC             = NO
1326+
1327+# The TOC_EXPAND flag can be set to YES to add extra items for group members
1328+# to the contents of the HTML help documentation and to the tree view.
1329+
1330+TOC_EXPAND             = NO
1331+
1332+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
1333+# are set, an additional index file will be generated that can be used as input for
1334+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
1335+# HTML documentation.
1336+
1337+GENERATE_QHP           = NO
1338+
1339+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
1340+# be used to specify the file name of the resulting .qch file.
1341+# The path specified is relative to the HTML output folder.
1342+
1343+QCH_FILE               =
1344+
1345+# The QHP_NAMESPACE tag specifies the namespace to use when generating
1346+# Qt Help Project output. For more information please see
1347+# http://doc.trolltech.com/qthelpproject.html#namespace
1348+
1349+QHP_NAMESPACE          =
1350+
1351+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
1352+# Qt Help Project output. For more information please see
1353+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
1354+
1355+QHP_VIRTUAL_FOLDER     = doc
1356+
1357+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
1358+# For more information please see
1359+# http://doc.trolltech.com/qthelpproject.html#custom-filters
1360+
1361+QHP_CUST_FILTER_NAME   =
1362+
1363+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
1364+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
1365+
1366+QHP_CUST_FILTER_ATTRS  =
1367+
1368+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
1369+# filter section matches.
1370+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
1371+
1372+QHP_SECT_FILTER_ATTRS  =
1373+
1374+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
1375+# be used to specify the location of Qt's qhelpgenerator.
1376+# If non-empty doxygen will try to run qhelpgenerator on the generated
1377+# .qhp file.
1378+
1379+QHG_LOCATION           =
1380+
1381+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
1382+# top of each HTML page. The value NO (the default) enables the index and
1383+# the value YES disables it.
1384+
1385+DISABLE_INDEX          = NO
1386+
1387+# This tag can be used to set the number of enum values (range [1..20])
1388+# that doxygen will group on one line in the generated HTML documentation.
1389+
1390+ENUM_VALUES_PER_LINE   = 4
1391+
1392+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1393+# structure should be generated to display hierarchical information.
1394+# If the tag value is set to YES, a side panel will be generated
1395+# containing a tree-like index structure (just like the one that
1396+# is generated for HTML Help). For this to work a browser that supports
1397+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
1398+# Windows users are probably better off using the HTML help feature.
1399+
1400+GENERATE_TREEVIEW      = NO
1401+
1402+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
1403+# and Class Hierarchy pages using a tree view instead of an ordered list.
1404+
1405+USE_INLINE_TREES       = NO
1406+
1407+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
1408+# used to set the initial width (in pixels) of the frame in which the tree
1409+# is shown.
1410+
1411+TREEVIEW_WIDTH         = 250
1412+
1413+# Use this tag to change the font size of Latex formulas included
1414+# as images in the HTML documentation. The default is 10. Note that
1415+# when you change the font size after a successful doxygen run you need
1416+# to manually remove any form_*.png images from the HTML output directory
1417+# to force them to be regenerated.
1418+
1419+FORMULA_FONTSIZE       = 10
1420+
1421+# When the SEARCHENGINE tag is enable doxygen will generate a search box
1422+# for the HTML output. The underlying search engine uses javascript
1423+# and DHTML and should work on any modern browser. Note that when using
1424+# HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP)
1425+# there is already a search function so this one should typically
1426+# be disabled.
1427+
1428+SEARCHENGINE           = YES
1429+
1430+#---------------------------------------------------------------------------
1431+# configuration options related to the LaTeX output
1432+#---------------------------------------------------------------------------
1433+
1434+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
1435+# generate Latex output.
1436+
1437+GENERATE_LATEX         = NO
1438+
1439+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
1440+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1441+# put in front of it. If left blank `latex' will be used as the default path.
1442+
1443+LATEX_OUTPUT           = latex
1444+
1445+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1446+# invoked. If left blank `latex' will be used as the default command name.
1447+
1448+LATEX_CMD_NAME         = latex
1449+
1450+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
1451+# generate index for LaTeX. If left blank `makeindex' will be used as the
1452+# default command name.
1453+
1454+MAKEINDEX_CMD_NAME     = makeindex
1455+
1456+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
1457+# LaTeX documents. This may be useful for small projects and may help to
1458+# save some trees in general.
1459+
1460+COMPACT_LATEX          = NO
1461+
1462+# The PAPER_TYPE tag can be used to set the paper type that is used
1463+# by the printer. Possible values are: a4, a4wide, letter, legal and
1464+# executive. If left blank a4wide will be used.
1465+
1466+PAPER_TYPE             = a4wide
1467+
1468+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
1469+# packages that should be included in the LaTeX output.
1470+
1471+EXTRA_PACKAGES         =
1472+
1473+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
1474+# the generated latex document. The header should contain everything until
1475+# the first chapter. If it is left blank doxygen will generate a
1476+# standard header. Notice: only use this tag if you know what you are doing!
1477+
1478+LATEX_HEADER           =
1479+
1480+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
1481+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
1482+# contain links (just like the HTML output) instead of page references
1483+# This makes the output suitable for online browsing using a pdf viewer.
1484+
1485+PDF_HYPERLINKS         = YES
1486+
1487+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
1488+# plain latex in the generated Makefile. Set this option to YES to get a
1489+# higher quality PDF documentation.
1490+
1491+USE_PDFLATEX           = YES
1492+
1493+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
1494+# command to the generated LaTeX files. This will instruct LaTeX to keep
1495+# running if errors occur, instead of asking the user for help.
1496+# This option is also used when generating formulas in HTML.
1497+
1498+LATEX_BATCHMODE        = NO
1499+
1500+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
1501+# include the index chapters (such as File Index, Compound Index, etc.)
1502+# in the output.
1503+
1504+LATEX_HIDE_INDICES     = NO
1505+
1506+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
1507+# source code with syntax highlighting in the LaTeX output.
1508+# Note that which sources are shown also depends on other settings
1509+# such as SOURCE_BROWSER.
1510+
1511+LATEX_SOURCE_CODE      = NO
1512+
1513+#---------------------------------------------------------------------------
1514+# configuration options related to the RTF output
1515+#---------------------------------------------------------------------------
1516+
1517+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
1518+# The RTF output is optimized for Word 97 and may not look very pretty with
1519+# other RTF readers or editors.
1520+
1521+GENERATE_RTF           = NO
1522+
1523+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
1524+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1525+# put in front of it. If left blank `rtf' will be used as the default path.
1526+
1527+RTF_OUTPUT             = rtf
1528+
1529+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
1530+# RTF documents. This may be useful for small projects and may help to
1531+# save some trees in general.
1532+
1533+COMPACT_RTF            = NO
1534+
1535+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
1536+# will contain hyperlink fields. The RTF file will
1537+# contain links (just like the HTML output) instead of page references.
1538+# This makes the output suitable for online browsing using WORD or other
1539+# programs which support those fields.
1540+# Note: wordpad (write) and others do not support links.
1541+
1542+RTF_HYPERLINKS         = NO
1543+
1544+# Load stylesheet definitions from file. Syntax is similar to doxygen's
1545+# config file, i.e. a series of assignments. You only have to provide
1546+# replacements, missing definitions are set to their default value.
1547+
1548+RTF_STYLESHEET_FILE    =
1549+
1550+# Set optional variables used in the generation of an rtf document.
1551+# Syntax is similar to doxygen's config file.
1552+
1553+RTF_EXTENSIONS_FILE    =
1554+
1555+#---------------------------------------------------------------------------
1556+# configuration options related to the man page output
1557+#---------------------------------------------------------------------------
1558+
1559+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
1560+# generate man pages
1561+
1562+GENERATE_MAN           = NO
1563+
1564+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
1565+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1566+# put in front of it. If left blank `man' will be used as the default path.
1567+
1568+MAN_OUTPUT             = man
1569+
1570+# The MAN_EXTENSION tag determines the extension that is added to
1571+# the generated man pages (default is the subroutine's section .3)
1572+
1573+MAN_EXTENSION          = .3
1574+
1575+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
1576+# then it will generate one additional man file for each entity
1577+# documented in the real man page(s). These additional files
1578+# only source the real man page, but without them the man command
1579+# would be unable to find the correct page. The default is NO.
1580+
1581+MAN_LINKS              = NO
1582+
1583+#---------------------------------------------------------------------------
1584+# configuration options related to the XML output
1585+#---------------------------------------------------------------------------
1586+
1587+# If the GENERATE_XML tag is set to YES Doxygen will
1588+# generate an XML file that captures the structure of
1589+# the code including all documentation.
1590+
1591+GENERATE_XML           = NO
1592+
1593+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
1594+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
1595+# put in front of it. If left blank `xml' will be used as the default path.
1596+
1597+XML_OUTPUT             = xml
1598+
1599+# The XML_SCHEMA tag can be used to specify an XML schema,
1600+# which can be used by a validating XML parser to check the
1601+# syntax of the XML files.
1602+
1603+XML_SCHEMA             =
1604+
1605+# The XML_DTD tag can be used to specify an XML DTD,
1606+# which can be used by a validating XML parser to check the
1607+# syntax of the XML files.
1608+
1609+XML_DTD                =
1610+
1611+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
1612+# dump the program listings (including syntax highlighting
1613+# and cross-referencing information) to the XML output. Note that
1614+# enabling this will significantly increase the size of the XML output.
1615+
1616+XML_PROGRAMLISTING     = YES
1617+
1618+#---------------------------------------------------------------------------
1619+# configuration options for the AutoGen Definitions output
1620+#---------------------------------------------------------------------------
1621+
1622+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
1623+# generate an AutoGen Definitions (see autogen.sf.net) file
1624+# that captures the structure of the code including all
1625+# documentation. Note that this feature is still experimental
1626+# and incomplete at the moment.
1627+
1628+GENERATE_AUTOGEN_DEF   = NO
1629+
1630+#---------------------------------------------------------------------------
1631+# configuration options related to the Perl module output
1632+#---------------------------------------------------------------------------
1633+
1634+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
1635+# generate a Perl module file that captures the structure of
1636+# the code including all documentation. Note that this
1637+# feature is still experimental and incomplete at the
1638+# moment.
1639+
1640+GENERATE_PERLMOD       = NO
1641+
1642+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
1643+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
1644+# to generate PDF and DVI output from the Perl module output.
1645+
1646+PERLMOD_LATEX          = NO
1647+
1648+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
1649+# nicely formatted so it can be parsed by a human reader.  This is useful
1650+# if you want to understand what is going on.  On the other hand, if this
1651+# tag is set to NO the size of the Perl module output will be much smaller
1652+# and Perl will parse it just the same.
1653+
1654+PERLMOD_PRETTY         = YES
1655+
1656+# The names of the make variables in the generated doxyrules.make file
1657+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
1658+# This is useful so different doxyrules.make files included by the same
1659+# Makefile don't overwrite each other's variables.
1660+
1661+PERLMOD_MAKEVAR_PREFIX =
1662+
1663+#---------------------------------------------------------------------------
1664+# Configuration options related to the preprocessor
1665+#---------------------------------------------------------------------------
1666+
1667+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
1668+# evaluate all C-preprocessor directives found in the sources and include
1669+# files.
1670+
1671+ENABLE_PREPROCESSING   = YES
1672+
1673+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
1674+# names in the source code. If set to NO (the default) only conditional
1675+# compilation will be performed. Macro expansion can be done in a controlled
1676+# way by setting EXPAND_ONLY_PREDEF to YES.
1677+
1678+MACRO_EXPANSION        = NO
1679+
1680+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
1681+# then the macro expansion is limited to the macros specified with the
1682+# PREDEFINED and EXPAND_AS_DEFINED tags.
1683+
1684+EXPAND_ONLY_PREDEF     = NO
1685+
1686+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
1687+# in the INCLUDE_PATH (see below) will be search if a #include is found.
1688+
1689+SEARCH_INCLUDES        = YES
1690+
1691+# The INCLUDE_PATH tag can be used to specify one or more directories that
1692+# contain include files that are not input files but should be processed by
1693+# the preprocessor.
1694+
1695+INCLUDE_PATH           =
1696+
1697+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
1698+# patterns (like *.h and *.hpp) to filter out the header-files in the
1699+# directories. If left blank, the patterns specified with FILE_PATTERNS will
1700+# be used.
1701+
1702+INCLUDE_FILE_PATTERNS  =
1703+
1704+# The PREDEFINED tag can be used to specify one or more macro names that
1705+# are defined before the preprocessor is started (similar to the -D option of
1706+# gcc). The argument of the tag is a list of macros of the form: name
1707+# or name=definition (no spaces). If the definition and the = are
1708+# omitted =1 is assumed. To prevent a macro definition from being
1709+# undefined via #undef or recursively expanded use the := operator
1710+# instead of the = operator.
1711+
1712+PREDEFINED             =
1713+
1714+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
1715+# this tag can be used to specify a list of macro names that should be expanded.
1716+# The macro definition that is found in the sources will be used.
1717+# Use the PREDEFINED tag if you want to use a different macro definition.
1718+
1719+EXPAND_AS_DEFINED      =
1720+
1721+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
1722+# doxygen's preprocessor will remove all function-like macros that are alone
1723+# on a line, have an all uppercase name, and do not end with a semicolon. Such
1724+# function macros are typically used for boiler-plate code, and will confuse
1725+# the parser if not removed.
1726+
1727+SKIP_FUNCTION_MACROS   = YES
1728+
1729+#---------------------------------------------------------------------------
1730+# Configuration::additions related to external references
1731+#---------------------------------------------------------------------------
1732+
1733+# The TAGFILES option can be used to specify one or more tagfiles.
1734+# Optionally an initial location of the external documentation
1735+# can be added for each tagfile. The format of a tag file without
1736+# this location is as follows:
1737+#   TAGFILES = file1 file2 ...
1738+# Adding location for the tag files is done as follows:
1739+#   TAGFILES = file1=loc1 "file2 = loc2" ...
1740+# where "loc1" and "loc2" can be relative or absolute paths or
1741+# URLs. If a location is present for each tag, the installdox tool
1742+# does not have to be run to correct the links.
1743+# Note that each tag file must have a unique name
1744+# (where the name does NOT include the path)
1745+# If a tag file is not located in the directory in which doxygen
1746+# is run, you must also specify the path to the tagfile here.
1747+
1748+TAGFILES               =
1749+
1750+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
1751+# a tag file that is based on the input files it reads.
1752+
1753+GENERATE_TAGFILE       =
1754+
1755+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
1756+# in the class index. If set to NO only the inherited external classes
1757+# will be listed.
1758+
1759+ALLEXTERNALS           = NO
1760+
1761+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
1762+# in the modules index. If set to NO, only the current project's groups will
1763+# be listed.
1764+
1765+EXTERNAL_GROUPS        = YES
1766+
1767+# The PERL_PATH should be the absolute path and name of the perl script
1768+# interpreter (i.e. the result of `which perl').
1769+
1770+PERL_PATH              = /usr/bin/perl
1771+
1772+#---------------------------------------------------------------------------
1773+# Configuration options related to the dot tool
1774+#---------------------------------------------------------------------------
1775+
1776+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
1777+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
1778+# or super classes. Setting the tag to NO turns the diagrams off. Note that
1779+# this option is superseded by the HAVE_DOT option below. This is only a
1780+# fallback. It is recommended to install and use dot, since it yields more
1781+# powerful graphs.
1782+
1783+CLASS_DIAGRAMS         = YES
1784+
1785+# You can define message sequence charts within doxygen comments using the \msc
1786+# command. Doxygen will then run the mscgen tool (see
1787+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
1788+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
1789+# the mscgen tool resides. If left empty the tool is assumed to be found in the
1790+# default search path.
1791+
1792+MSCGEN_PATH            =
1793+
1794+# If set to YES, the inheritance and collaboration graphs will hide
1795+# inheritance and usage relations if the target is undocumented
1796+# or is not a class.
1797+
1798+HIDE_UNDOC_RELATIONS   = YES
1799+
1800+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
1801+# available from the path. This tool is part of Graphviz, a graph visualization
1802+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
1803+# have no effect if this option is set to NO (the default)
1804+
1805+HAVE_DOT               = NO
1806+
1807+# By default doxygen will write a font called FreeSans.ttf to the output
1808+# directory and reference it in all dot files that doxygen generates. This
1809+# font does not include all possible unicode characters however, so when you need
1810+# these (or just want a differently looking font) you can specify the font name
1811+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
1812+# which can be done by putting it in a standard location or by setting the
1813+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
1814+# containing the font.
1815+
1816+DOT_FONTNAME           = FreeSans
1817+
1818+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
1819+# The default size is 10pt.
1820+
1821+DOT_FONTSIZE           = 10
1822+
1823+# By default doxygen will tell dot to use the output directory to look for the
1824+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
1825+# different font using DOT_FONTNAME you can set the path where dot
1826+# can find it using this tag.
1827+
1828+DOT_FONTPATH           =
1829+
1830+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
1831+# will generate a graph for each documented class showing the direct and
1832+# indirect inheritance relations. Setting this tag to YES will force the
1833+# the CLASS_DIAGRAMS tag to NO.
1834+
1835+CLASS_GRAPH            = YES
1836+
1837+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
1838+# will generate a graph for each documented class showing the direct and
1839+# indirect implementation dependencies (inheritance, containment, and
1840+# class references variables) of the class with other documented classes.
1841+
1842+COLLABORATION_GRAPH    = YES
1843+
1844+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
1845+# will generate a graph for groups, showing the direct groups dependencies
1846+
1847+GROUP_GRAPHS           = YES
1848+
1849+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
1850+# collaboration diagrams in a style similar to the OMG's Unified Modeling
1851+# Language.
1852+
1853+UML_LOOK               = NO
1854+
1855+# If set to YES, the inheritance and collaboration graphs will show the
1856+# relations between templates and their instances.
1857+
1858+TEMPLATE_RELATIONS     = NO
1859+
1860+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
1861+# tags are set to YES then doxygen will generate a graph for each documented
1862+# file showing the direct and indirect include dependencies of the file with
1863+# other documented files.
1864+
1865+INCLUDE_GRAPH          = YES
1866+
1867+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
1868+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
1869+# documented header file showing the documented files that directly or
1870+# indirectly include this file.
1871+
1872+INCLUDED_BY_GRAPH      = YES
1873+
1874+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
1875+# doxygen will generate a call dependency graph for every global function
1876+# or class method. Note that enabling this option will significantly increase
1877+# the time of a run. So in most cases it will be better to enable call graphs
1878+# for selected functions only using the \callgraph command.
1879+
1880+CALL_GRAPH             = NO
1881+
1882+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
1883+# doxygen will generate a caller dependency graph for every global function
1884+# or class method. Note that enabling this option will significantly increase
1885+# the time of a run. So in most cases it will be better to enable caller
1886+# graphs for selected functions only using the \callergraph command.
1887+
1888+CALLER_GRAPH           = NO
1889+
1890+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
1891+# will graphical hierarchy of all classes instead of a textual one.
1892+
1893+GRAPHICAL_HIERARCHY    = YES
1894+
1895+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
1896+# then doxygen will show the dependencies a directory has on other directories
1897+# in a graphical way. The dependency relations are determined by the #include
1898+# relations between the files in the directories.
1899+
1900+DIRECTORY_GRAPH        = YES
1901+
1902+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
1903+# generated by dot. Possible values are png, jpg, or gif
1904+# If left blank png will be used.
1905+
1906+DOT_IMAGE_FORMAT       = png
1907+
1908+# The tag DOT_PATH can be used to specify the path where the dot tool can be
1909+# found. If left blank, it is assumed the dot tool can be found in the path.
1910+
1911+DOT_PATH               =
1912+
1913+# The DOTFILE_DIRS tag can be used to specify one or more directories that
1914+# contain dot files that are included in the documentation (see the
1915+# \dotfile command).
1916+
1917+DOTFILE_DIRS           =
1918+
1919+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
1920+# nodes that will be shown in the graph. If the number of nodes in a graph
1921+# becomes larger than this value, doxygen will truncate the graph, which is
1922+# visualized by representing a node as a red box. Note that doxygen if the
1923+# number of direct children of the root node in a graph is already larger than
1924+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
1925+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
1926+
1927+DOT_GRAPH_MAX_NODES    = 50
1928+
1929+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
1930+# graphs generated by dot. A depth value of 3 means that only nodes reachable
1931+# from the root by following a path via at most 3 edges will be shown. Nodes
1932+# that lay further from the root node will be omitted. Note that setting this
1933+# option to 1 or 2 may greatly reduce the computation time needed for large
1934+# code bases. Also note that the size of a graph can be further restricted by
1935+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
1936+
1937+MAX_DOT_GRAPH_DEPTH    = 0
1938+
1939+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
1940+# background. This is disabled by default, because dot on Windows does not
1941+# seem to support this out of the box. Warning: Depending on the platform used,
1942+# enabling this option may lead to badly anti-aliased labels on the edges of
1943+# a graph (i.e. they become hard to read).
1944+
1945+DOT_TRANSPARENT        = NO
1946+
1947+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
1948+# files in one run (i.e. multiple -o and -T options on the command line). This
1949+# makes dot run faster, but since only newer versions of dot (>1.8.10)
1950+# support this, this feature is disabled by default.
1951+
1952+DOT_MULTI_TARGETS      = NO
1953+
1954+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
1955+# generate a legend page explaining the meaning of the various boxes and
1956+# arrows in the dot generated graphs.
1957+
1958+GENERATE_LEGEND        = YES
1959+
1960+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
1961+# remove the intermediate dot files that are used to generate
1962+# the various graphs.
1963+
1964+DOT_CLEANUP            = YES
1965diff --git a/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp b/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp
1966new file mode 100644
1967index 00000000..703a5ea5
1968--- /dev/null
1969+++ b/benchmark/feature_mos/src/mosaic/AlignFeatures.cpp
1970@@ -0,0 +1,233 @@
1971+/*
1972+ * Copyright (C) 2011 The Android Open Source Project
1973+ *
1974+ * Licensed under the Apache License, Version 2.0 (the "License");
1975+ * you may not use this file except in compliance with the License.
1976+ * You may obtain a copy of the License at
1977+ *
1978+ *      http://www.apache.org/licenses/LICENSE-2.0
1979+ *
1980+ * Unless required by applicable law or agreed to in writing, software
1981+ * distributed under the License is distributed on an "AS IS" BASIS,
1982+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1983+ * See the License for the specific language governing permissions and
1984+ * limitations under the License.
1985+ */
1986+
1987+///////////////////////////////////////////////////
1988+// AlignFeatures.cpp
1989+// S.O. # :
1990+// Author(s): zkira, mbansal, bsouthall, narodits
1991+// $Id: AlignFeatures.cpp,v 1.20 2011/06/17 13:35:47 mbansal Exp $
1992+
1993+#include <stdio.h>
1994+#include <string.h>
1995+
1996+#include "trsMatrix.h"
1997+#include "MatrixUtils.h"
1998+#include "AlignFeatures.h"
1999+#include "Log.h"
2000+
2001+#define LOG_TAG "AlignFeatures"
2002+
2003+const double Align::DEFAULT_MAX_DISPARITY = 0.1;
2004+
2005+Align::Align()
2006+{
2007+  width = height = 0;
2008+  frame_number = 0;
2009+  num_frames_captured = 0;
2010+  reference_frame_index = 0;
2011+  db_Identity3x3(Hcurr);
2012+  db_Identity3x3(Hprev);
2013+}
2014+
2015+Align::~Align()
2016+{
2017+  // Free gray-scale image
2018+  if (imageGray != ImageUtils::IMAGE_TYPE_NOIMAGE)
2019+    ImageUtils::freeImage(imageGray);
2020+}
2021+
2022+char* Align::getRegProfileString()
2023+{
2024+  return reg.profile_string;
2025+}
2026+
2027+int Align::initialize(int width, int height, bool _quarter_res, float _thresh_still)
2028+{
2029+  int    nr_corners = DEFAULT_NR_CORNERS;
2030+  double max_disparity = DEFAULT_MAX_DISPARITY;
2031+  int    motion_model_type = DEFAULT_MOTION_MODEL;
2032+  int nrsamples = DB_DEFAULT_NR_SAMPLES;
2033+  double scale = DB_POINT_STANDARDDEV;
2034+  int chunk_size = DB_DEFAULT_CHUNK_SIZE;
2035+  int nrhorz = width/48;  // Empirically determined number of horizontal
2036+  int nrvert = height/60; // and vertical buckets for harris corner detection.
2037+  bool linear_polish = false;
2038+  unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD;
2039+
2040+  const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = false;
2041+  bool   use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW;
2042+
2043+  quarter_res = _quarter_res;
2044+  thresh_still = _thresh_still;
2045+
2046+  frame_number = 0;
2047+  num_frames_captured = 0;
2048+  reference_frame_index = 0;
2049+  db_Identity3x3(Hcurr);
2050+  db_Identity3x3(Hprev);
2051+
2052+  if (!reg.Initialized())
2053+  {
2054+    reg.Init(width, height, motion_model_type, 20, linear_polish, quarter_res,
2055+            scale, reference_update_period, false, 0, nrsamples, chunk_size,
2056+            nr_corners, max_disparity, use_smaller_matching_window,
2057+            nrhorz, nrvert);
2058+  }
2059+  this->width = width;
2060+  this->height = height;
2061+
2062+  imageGray = ImageUtils::allocateImage(width, height, 1);
2063+
2064+  if (reg.Initialized())
2065+    return ALIGN_RET_OK;
2066+  else
2067+    return ALIGN_RET_ERROR;
2068+}
2069+
2070+int Align::addFrameRGB(ImageType imageRGB)
2071+{
2072+  ImageUtils::rgb2gray(imageGray, imageRGB, width, height);
2073+  return addFrame(imageGray);
2074+}
2075+
2076+int Align::addFrame(ImageType imageGray_)
2077+{
2078+  int ret_code = ALIGN_RET_OK;
2079+
2080+ // Obtain a vector of pointers to rows in image and pass in to dbreg
2081+  ImageType *m_rows = ImageUtils::imageTypeToRowPointers(imageGray_, width, height);
2082+
2083+  if (frame_number == 0)
2084+  {
2085+      reg.AddFrame(m_rows, Hcurr, true);    // Force this to be a reference frame
2086+      int num_corner_ref = reg.GetNrRefCorners();
2087+
2088+      if (num_corner_ref < MIN_NR_REF_CORNERS)
2089+      {
2090+          return ALIGN_RET_LOW_TEXTURE;
2091+      }
2092+  }
2093+  else
2094+  {
2095+      reg.AddFrame(m_rows, Hcurr, false);
2096+  }
2097+
2098+  // Average translation per frame =
2099+  //    [Translation from Frame0 to Frame(n-1)] / [(n-1)]
2100+  average_tx_per_frame = (num_frames_captured < 2) ? 0.0 :
2101+        Hprev[2] / (num_frames_captured - 1);
2102+
2103+  // Increment the captured frame counter if we already have a reference frame
2104+  num_frames_captured++;
2105+
2106+  if (frame_number != 0)
2107+  {
2108+    int num_inliers = reg.GetNrInliers();
2109+
2110+    if(num_inliers < MIN_NR_INLIERS)
2111+    {
2112+        ret_code = ALIGN_RET_FEW_INLIERS;
2113+
2114+        Hcurr[0] = 1.0;
2115+        Hcurr[1] = 0.0;
2116+        // Set this as the average per frame translation taking into acccount
2117+        // the separation of the current frame from the reference frame...
2118+        Hcurr[2] = -average_tx_per_frame *
2119+                (num_frames_captured - reference_frame_index);
2120+        Hcurr[3] = 0.0;
2121+        Hcurr[4] = 1.0;
2122+        Hcurr[5] = 0.0;
2123+        Hcurr[6] = 0.0;
2124+        Hcurr[7] = 0.0;
2125+        Hcurr[8] = 1.0;
2126+    }
2127+
2128+    if(fabs(Hcurr[2])<thresh_still && fabs(Hcurr[5])<thresh_still)  // Still camera
2129+    {
2130+        return ALIGN_RET_ERROR;
2131+    }
2132+
2133+    // compute the homography:
2134+    double Hinv33[3][3];
2135+    double Hprev33[3][3];
2136+    double Hcurr33[3][3];
2137+
2138+    // Invert and multiple with previous transformation
2139+    Matrix33::convert9to33(Hcurr33, Hcurr);
2140+    Matrix33::convert9to33(Hprev33, Hprev);
2141+    normProjMat33d(Hcurr33);
2142+
2143+    inv33d(Hcurr33, Hinv33);
2144+
2145+    mult33d(Hcurr33, Hprev33, Hinv33);
2146+    normProjMat33d(Hcurr33);
2147+    Matrix9::convert33to9(Hprev, Hcurr33);
2148+    // Since we have already factored the current transformation
2149+    // into Hprev, we can reset the Hcurr to identity
2150+    db_Identity3x3(Hcurr);
2151+
2152+    // Update the reference frame to be the current frame
2153+    reg.UpdateReference(m_rows,quarter_res,false);
2154+
2155+    // Update the reference frame index
2156+    reference_frame_index = num_frames_captured;
2157+  }
2158+
2159+  frame_number++;
2160+
2161+  return ret_code;
2162+}
2163+
2164+// Get current transformation
2165+int Align::getLastTRS(double trs[3][3])
2166+{
2167+  if (frame_number < 1)
2168+  {
2169+    trs[0][0] = 1.0;
2170+    trs[0][1] = 0.0;
2171+    trs[0][2] = 0.0;
2172+    trs[1][0] = 0.0;
2173+    trs[1][1] = 1.0;
2174+    trs[1][2] = 0.0;
2175+    trs[2][0] = 0.0;
2176+    trs[2][1] = 0.0;
2177+    trs[2][2] = 1.0;
2178+    return ALIGN_RET_ERROR;
2179+  }
2180+
2181+  // Note that the logic here handles the case, where a frame is not used for
2182+  // mosaicing but is captured and used in the preview-rendering.
2183+  // For these frames, we don't set Hcurr to identity in AddFrame() and the
2184+  // logic here appends their transformation to Hprev to render them with the
2185+  // correct transformation. For the frames we do use for mosaicing, we already
2186+  // append their Hcurr to Hprev in AddFrame() and then set Hcurr to identity.
2187+
2188+  double Hinv33[3][3];
2189+  double Hprev33[3][3];
2190+  double Hcurr33[3][3];
2191+
2192+  Matrix33::convert9to33(Hcurr33, Hcurr);
2193+  normProjMat33d(Hcurr33);
2194+  inv33d(Hcurr33, Hinv33);
2195+
2196+  Matrix33::convert9to33(Hprev33, Hprev);
2197+
2198+  mult33d(trs, Hprev33, Hinv33);
2199+  normProjMat33d(trs);
2200+
2201+  return ALIGN_RET_OK;
2202+}
2203+
2204diff --git a/benchmark/feature_mos/src/mosaic/AlignFeatures.h b/benchmark/feature_mos/src/mosaic/AlignFeatures.h
2205new file mode 100644
2206index 00000000..9999f575
2207--- /dev/null
2208+++ b/benchmark/feature_mos/src/mosaic/AlignFeatures.h
2209@@ -0,0 +1,93 @@
2210+/*
2211+ * Copyright (C) 2011 The Android Open Source Project
2212+ *
2213+ * Licensed under the Apache License, Version 2.0 (the "License");
2214+ * you may not use this file except in compliance with the License.
2215+ * You may obtain a copy of the License at
2216+ *
2217+ *      http://www.apache.org/licenses/LICENSE-2.0
2218+ *
2219+ * Unless required by applicable law or agreed to in writing, software
2220+ * distributed under the License is distributed on an "AS IS" BASIS,
2221+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2222+ * See the License for the specific language governing permissions and
2223+ * limitations under the License.
2224+ */
2225+
2226+///////////////////////////////////////////////////
2227+// Align.h
2228+// S.O. # :
2229+// Author(s): zkira
2230+// $Id: AlignFeatures.h,v 1.13 2011/06/17 13:35:47 mbansal Exp $
2231+
2232+#ifndef ALIGN_H
2233+#define ALIGN_H
2234+
2235+#include "dbreg/dbreg.h"
2236+#include <db_utilities_camera.h>
2237+
2238+#include "ImageUtils.h"
2239+#include "MatrixUtils.h"
2240+
2241+class Align {
2242+
2243+public:
2244+  // Types of alignment possible
2245+  static const int ALIGN_TYPE_PAN    = 1;
2246+
2247+  // Return codes
2248+  static const int ALIGN_RET_LOW_TEXTURE  = -2;
2249+  static const int ALIGN_RET_ERROR        = -1;
2250+  static const int ALIGN_RET_OK           = 0;
2251+  static const int ALIGN_RET_FEW_INLIERS  = 1;
2252+
2253+  ///// Settings for feature-based alignment
2254+  // Number of features to use from corner detection
2255+  static const int DEFAULT_NR_CORNERS=750;
2256+  static const double DEFAULT_MAX_DISPARITY;//0.4;
2257+  // Type of homography to model
2258+  static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T;
2259+// static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_PROJECTIVE;
2260+//  static const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE;
2261+  static const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=1500; //  Manual reference frame update so set this to a large number
2262+
2263+  static const int MIN_NR_REF_CORNERS = 25;
2264+  static const int MIN_NR_INLIERS = 10;
2265+
2266+  Align();
2267+  ~Align();
2268+
2269+  // Initialization of structures, etc.
2270+  int initialize(int width, int height, bool quarter_res, float thresh_still);
2271+
2272+  // Add a frame.  Note: The alignment computation is performed
2273+  // in this function
2274+  int addFrameRGB(ImageType image);
2275+  int addFrame(ImageType image);
2276+
2277+  // Obtain the TRS matrix from the last two frames
2278+  int getLastTRS(double trs[3][3]);
2279+  char* getRegProfileString();
2280+
2281+protected:
2282+
2283+  db_FrameToReferenceRegistration reg;
2284+
2285+  int frame_number;
2286+
2287+  double Hcurr[9];   // Homography from the alignment reference to the frame-t
2288+  double Hprev[9];   // Homography from frame-0 to the frame-(t-1)
2289+
2290+  int reference_frame_index; // Index of the reference frame from all captured frames
2291+  int num_frames_captured; // Total number of frames captured (different from frame_number)
2292+  double average_tx_per_frame; // Average pixel translation per captured frame
2293+
2294+  int width,height;
2295+
2296+  bool quarter_res;     // Whether to process at quarter resolution
2297+  float thresh_still;   // Translation threshold in pixels to detect still camera
2298+  ImageType imageGray;
2299+};
2300+
2301+
2302+#endif
2303diff --git a/benchmark/feature_mos/src/mosaic/Blend.cpp b/benchmark/feature_mos/src/mosaic/Blend.cpp
2304new file mode 100644
2305index 00000000..625196c6
2306--- /dev/null
2307+++ b/benchmark/feature_mos/src/mosaic/Blend.cpp
2308@@ -0,0 +1,1385 @@
2309+/*
2310+ * Copyright (C) 2011 The Android Open Source Project
2311+ *
2312+ * Licensed under the Apache License, Version 2.0 (the "License");
2313+ * you may not use this file except in compliance with the License.
2314+ * You may obtain a copy of the License at
2315+ *
2316+ *      http://www.apache.org/licenses/LICENSE-2.0
2317+ *
2318+ * Unless required by applicable law or agreed to in writing, software
2319+ * distributed under the License is distributed on an "AS IS" BASIS,
2320+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2321+ * See the License for the specific language governing permissions and
2322+ * limitations under the License.
2323+ */
2324+
2325+///////////////////////////////////////////////////
2326+// Blend.cpp
2327+// $Id: Blend.cpp,v 1.22 2011/06/24 04:22:14 mbansal Exp $
2328+
2329+#include <string.h>
2330+
2331+#include "Interp.h"
2332+#include "Blend.h"
2333+
2334+#include "Geometry.h"
2335+#include "trsMatrix.h"
2336+
2337+const float Blend::LIMIT_SIZE_MULTIPLIER = 50.f * 2.0f;
2338+const float Blend::LIMIT_HEIGHT_MULTIPLIER = 2.5f;
2339+
2340+Blend::Blend()
2341+{
2342+  m_wb.blendingType = BLEND_TYPE_NONE;
2343+}
2344+
2345+Blend::~Blend()
2346+{
2347+    if (m_pFrameVPyr) free(m_pFrameVPyr);
2348+    if (m_pFrameUPyr) free(m_pFrameUPyr);
2349+    if (m_pFrameYPyr) free(m_pFrameYPyr);
2350+}
2351+
2352+int Blend::initialize(int blendingType, int stripType, int frame_width, int frame_height)
2353+{
2354+    this->width = frame_width;
2355+    this->height = frame_height;
2356+    this->m_wb.blendingType = blendingType;
2357+    this->m_wb.stripType = stripType;
2358+
2359+    m_wb.blendRange = m_wb.blendRangeUV = BLEND_RANGE_DEFAULT;
2360+    m_wb.nlevs = m_wb.blendRange;
2361+    m_wb.nlevsC = m_wb.blendRangeUV;
2362+
2363+    if (m_wb.nlevs <= 0) m_wb.nlevs = 1; // Need levels for YUV processing
2364+    if (m_wb.nlevsC > m_wb.nlevs) m_wb.nlevsC = m_wb.nlevs;
2365+
2366+    m_wb.roundoffOverlap = 1.5;
2367+
2368+    m_pFrameYPyr = NULL;
2369+    m_pFrameUPyr = NULL;
2370+    m_pFrameVPyr = NULL;
2371+
2372+    m_pFrameYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs, (unsigned short) width, (unsigned short) height, BORDER);
2373+    m_pFrameUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER);
2374+    m_pFrameVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC, (unsigned short) (width), (unsigned short) (height), BORDER);
2375+
2376+    if (!m_pFrameYPyr || !m_pFrameUPyr || !m_pFrameVPyr)
2377+    {
2378+        return BLEND_RET_ERROR_MEMORY;
2379+    }
2380+
2381+    return BLEND_RET_OK;
2382+}
2383+
2384+inline double max(double a, double b) { return a > b ? a : b; }
2385+inline double min(double a, double b) { return a < b ? a : b; }
2386+
2387+void Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size)
2388+{
2389+    // Unwarp this frame and Warp the others to match
2390+    MosaicFrame *mb = NULL;
2391+    MosaicFrame *ref = frames[int(frames_size/2)];    // Middle frame
2392+
2393+    double invtrs[3][3];
2394+    inv33d(ref->trs, invtrs);
2395+
2396+    for(int mfit = 0; mfit < frames_size; mfit++)
2397+    {
2398+        mb = frames[mfit];
2399+        double temp[3][3];
2400+        mult33d(temp, invtrs, mb->trs);
2401+        memcpy(mb->trs, temp, sizeof(temp));
2402+        normProjMat33d(mb->trs);
2403+    }
2404+}
2405+
2406+int Blend::runBlend(MosaicFrame **oframes, MosaicFrame **rframes,
2407+        int frames_size,
2408+        ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight,
2409+        float &progress, bool &cancelComputation)
2410+{
2411+    int ret;
2412+    int numCenters;
2413+
2414+    MosaicFrame **frames;
2415+
2416+    // For THIN strip mode, accept all frames for blending
2417+    if (m_wb.stripType == STRIP_TYPE_THIN)
2418+    {
2419+        frames = oframes;
2420+    }
2421+    else // For WIDE strip mode, first select the relevant frames to blend.
2422+    {
2423+        SelectRelevantFrames(oframes, frames_size, rframes, frames_size);
2424+        frames = rframes;
2425+    }
2426+
2427+    ComputeBlendParameters(frames, frames_size, true);
2428+    numCenters = frames_size;
2429+
2430+    if (numCenters == 0)
2431+    {
2432+        return BLEND_RET_ERROR;
2433+    }
2434+
2435+    if (!(m_AllSites = m_Triangulator.allocMemory(numCenters)))
2436+    {
2437+        return BLEND_RET_ERROR_MEMORY;
2438+    }
2439+
2440+    // Bounding rectangle (real numbers) of the final mosaic computed by projecting
2441+    // each input frame into the mosaic coordinate system.
2442+    BlendRect global_rect;
2443+
2444+    global_rect.lft = global_rect.bot = 2e30; // min values
2445+    global_rect.rgt = global_rect.top = -2e30; // max values
2446+    MosaicFrame *mb = NULL;
2447+
2448+    double x0, y0, x1, y1, x2, y2, x3, y3;
2449+
2450+    // Corners of the left-most and right-most frames respectively in the
2451+    // mosaic coordinate system.
2452+    double xLeftCorners[2] = {2e30, 2e30};
2453+    double xRightCorners[2] = {-2e30, -2e30};
2454+
2455+    // Corners of the top-most and bottom-most frames respectively in the
2456+    // mosaic coordinate system.
2457+    double yTopCorners[2] = {2e30, 2e30};
2458+    double yBottomCorners[2] = {-2e30, -2e30};
2459+
2460+
2461+    // Determine the extents of the final mosaic
2462+    CSite *csite = m_AllSites ;
2463+    for(int mfit = 0; mfit < frames_size; mfit++)
2464+    {
2465+        mb = frames[mfit];
2466+
2467+        // Compute clipping for this frame's rect
2468+        FrameToMosaicRect(mb->width, mb->height, mb->trs, mb->brect);
2469+        // Clip global rect using this frame's rect
2470+        ClipRect(mb->brect, global_rect);
2471+
2472+        // Calculate the corner points
2473+        FrameToMosaic(mb->trs, 0.0,             0.0,            x0, y0);
2474+        FrameToMosaic(mb->trs, 0.0,             mb->height-1.0, x1, y1);
2475+        FrameToMosaic(mb->trs, mb->width-1.0,   mb->height-1.0, x2, y2);
2476+        FrameToMosaic(mb->trs, mb->width-1.0,   0.0,            x3, y3);
2477+
2478+        if(x0 < xLeftCorners[0] || x1 < xLeftCorners[1])    // If either of the left corners is lower
2479+        {
2480+            xLeftCorners[0] = x0;
2481+            xLeftCorners[1] = x1;
2482+        }
2483+
2484+        if(x3 > xRightCorners[0] || x2 > xRightCorners[1])    // If either of the right corners is higher
2485+        {
2486+            xRightCorners[0] = x3;
2487+            xRightCorners[1] = x2;
2488+        }
2489+
2490+        if(y0 < yTopCorners[0] || y3 < yTopCorners[1])    // If either of the top corners is lower
2491+        {
2492+            yTopCorners[0] = y0;
2493+            yTopCorners[1] = y3;
2494+        }
2495+
2496+        if(y1 > yBottomCorners[0] || y2 > yBottomCorners[1])    // If either of the bottom corners is higher
2497+        {
2498+            yBottomCorners[0] = y1;
2499+            yBottomCorners[1] = y2;
2500+        }
2501+
2502+
2503+        // Compute the centroid of the warped region
2504+        FindQuadCentroid(x0, y0, x1, y1, x2, y2, x3, y3, csite->getVCenter().x, csite->getVCenter().y);
2505+
2506+        csite->setMb(mb);
2507+        csite++;
2508+    }
2509+
2510+    // Get origin and sizes
2511+
2512+    // Bounding rectangle (int numbers) of the final mosaic computed by projecting
2513+    // each input frame into the mosaic coordinate system.
2514+    MosaicRect fullRect;
2515+
2516+    fullRect.left = (int) floor(global_rect.lft); // min-x
2517+    fullRect.top = (int) floor(global_rect.bot);  // min-y
2518+    fullRect.right = (int) ceil(global_rect.rgt); // max-x
2519+    fullRect.bottom = (int) ceil(global_rect.top);// max-y
2520+    Mwidth = (unsigned short) (fullRect.right - fullRect.left + 1);
2521+    Mheight = (unsigned short) (fullRect.bottom - fullRect.top + 1);
2522+
2523+    int xLeftMost, xRightMost;
2524+    int yTopMost, yBottomMost;
2525+
2526+    // Rounding up, so that we don't include the gray border.
2527+    xLeftMost = max(0, max(xLeftCorners[0], xLeftCorners[1]) - fullRect.left + 1);
2528+    xRightMost = min(Mwidth - 1, min(xRightCorners[0], xRightCorners[1]) - fullRect.left - 1);
2529+
2530+    yTopMost = max(0, max(yTopCorners[0], yTopCorners[1]) - fullRect.top + 1);
2531+    yBottomMost = min(Mheight - 1, min(yBottomCorners[0], yBottomCorners[1]) - fullRect.top - 1);
2532+
2533+    if (xRightMost <= xLeftMost || yBottomMost <= yTopMost)
2534+    {
2535+        return BLEND_RET_ERROR;
2536+    }
2537+
2538+    // Make sure image width is multiple of 4
2539+    Mwidth = (unsigned short) ((Mwidth + 3) & ~3);
2540+    Mheight = (unsigned short) ((Mheight + 3) & ~3);    // Round up.
2541+
2542+    ret = MosaicSizeCheck(LIMIT_SIZE_MULTIPLIER, LIMIT_HEIGHT_MULTIPLIER);
2543+    if (ret != BLEND_RET_OK)
2544+    {
2545+       return ret;
2546+    }
2547+
2548+    YUVinfo *imgMos = YUVinfo::allocateImage(Mwidth, Mheight);
2549+    if (imgMos == NULL)
2550+    {
2551+        return BLEND_RET_ERROR_MEMORY;
2552+    }
2553+
2554+    // Set the Y image to 255 so we can distinguish when frame idx are written to it
2555+    memset(imgMos->Y.ptr[0], 255, (imgMos->Y.width * imgMos->Y.height));
2556+    // Set the v and u images to black
2557+    memset(imgMos->V.ptr[0], 128, (imgMos->V.width * imgMos->V.height) << 1);
2558+
2559+    // Do the triangulation.  It returns a sorted list of edges
2560+    SEdgeVector *edge;
2561+    int n = m_Triangulator.triangulate(&edge, numCenters, width, height);
2562+    m_Triangulator.linkNeighbors(edge, n, numCenters);
2563+
2564+    // Bounding rectangle that determines the positioning of the rectangle that is
2565+    // cropped out of the computed mosaic to get rid of the gray borders.
2566+    MosaicRect cropping_rect;
2567+
2568+    if (m_wb.horizontal)
2569+    {
2570+        cropping_rect.left = xLeftMost;
2571+        cropping_rect.right = xRightMost;
2572+    }
2573+    else
2574+    {
2575+        cropping_rect.top = yTopMost;
2576+        cropping_rect.bottom = yBottomMost;
2577+    }
2578+
2579+    // Do merging and blending :
2580+    ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect,
2581+            cropping_rect, progress, cancelComputation);
2582+
2583+    if (m_wb.blendingType == BLEND_TYPE_HORZ)
2584+        CropFinalMosaic(*imgMos, cropping_rect);
2585+
2586+
2587+    m_Triangulator.freeMemory();    // note: can be called even if delaunay_alloc() wasn't successful
2588+
2589+    imageMosaicYVU = imgMos->Y.ptr[0];
2590+
2591+
2592+    if (m_wb.blendingType == BLEND_TYPE_HORZ)
2593+    {
2594+        mosaicWidth = cropping_rect.right - cropping_rect.left + 1;
2595+        mosaicHeight = cropping_rect.bottom - cropping_rect.top + 1;
2596+    }
2597+    else
2598+    {
2599+        mosaicWidth = Mwidth;
2600+        mosaicHeight = Mheight;
2601+    }
2602+
2603+    return ret;
2604+}
2605+
2606+int Blend::MosaicSizeCheck(float sizeMultiplier, float heightMultiplier) {
2607+   if (Mwidth < width || Mheight < height) {
2608+        return BLEND_RET_ERROR;
2609+    }
2610+
2611+   if ((Mwidth * Mheight) > (width * height * sizeMultiplier)) {
2612+         return BLEND_RET_ERROR;
2613+   }
2614+
2615+   // We won't do blending for the cases where users swing the device too much
2616+   // in the secondary direction. We use a short side to determine the
2617+   // secondary direction because users may hold the device in landsape
2618+   // or portrait.
2619+   int shortSide = min(Mwidth, Mheight);
2620+   if (shortSide > height * heightMultiplier) {
2621+       return BLEND_RET_ERROR;
2622+   }
2623+
2624+   return BLEND_RET_OK;
2625+}
2626+
2627+int Blend::FillFramePyramid(MosaicFrame *mb)
2628+{
2629+    ImageType mbY, mbU, mbV;
2630+    // Lay this image, centered into the temporary buffer
2631+    mbY = mb->image;
2632+    mbU = mb->getU();
2633+    mbV = mb->getV();
2634+
2635+    int h, w;
2636+
2637+    for(h=0; h<height; h++)
2638+    {
2639+        ImageTypeShort yptr = m_pFrameYPyr->ptr[h];
2640+        ImageTypeShort uptr = m_pFrameUPyr->ptr[h];
2641+        ImageTypeShort vptr = m_pFrameVPyr->ptr[h];
2642+
2643+        for(w=0; w<width; w++)
2644+        {
2645+            yptr[w] = (short) ((*(mbY++)) << 3);
2646+            uptr[w] = (short) ((*(mbU++)) << 3);
2647+            vptr[w] = (short) ((*(mbV++)) << 3);
2648+        }
2649+    }
2650+
2651+    // Spread the image through the border
2652+    PyramidShort::BorderSpread(m_pFrameYPyr, BORDER, BORDER, BORDER, BORDER);
2653+    PyramidShort::BorderSpread(m_pFrameUPyr, BORDER, BORDER, BORDER, BORDER);
2654+    PyramidShort::BorderSpread(m_pFrameVPyr, BORDER, BORDER, BORDER, BORDER);
2655+
2656+    // Generate Laplacian pyramids
2657+    if (!PyramidShort::BorderReduce(m_pFrameYPyr, m_wb.nlevs) || !PyramidShort::BorderExpand(m_pFrameYPyr, m_wb.nlevs, -1) ||
2658+            !PyramidShort::BorderReduce(m_pFrameUPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameUPyr, m_wb.nlevsC, -1) ||
2659+            !PyramidShort::BorderReduce(m_pFrameVPyr, m_wb.nlevsC) || !PyramidShort::BorderExpand(m_pFrameVPyr, m_wb.nlevsC, -1))
2660+    {
2661+        return BLEND_RET_ERROR;
2662+    }
2663+    else
2664+    {
2665+        return BLEND_RET_OK;
2666+    }
2667+}
2668+
2669+int Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite,
2670+             int width, int height, YUVinfo &imgMos, MosaicRect &rect,
2671+             MosaicRect &cropping_rect, float &progress, bool &cancelComputation)
2672+{
2673+    m_pMosaicYPyr = NULL;
2674+    m_pMosaicUPyr = NULL;
2675+    m_pMosaicVPyr = NULL;
2676+
2677+    m_pMosaicYPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevs,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
2678+    m_pMosaicUPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
2679+    m_pMosaicVPyr = PyramidShort::allocatePyramidPacked(m_wb.nlevsC,(unsigned short)rect.Width(),(unsigned short)rect.Height(),BORDER);
2680+    if (!m_pMosaicYPyr || !m_pMosaicUPyr || !m_pMosaicVPyr)
2681+    {
2682+      return BLEND_RET_ERROR_MEMORY;
2683+    }
2684+
2685+    MosaicFrame *mb;
2686+
2687+    CSite *esite = m_AllSites + nsite;
2688+    int site_idx;
2689+
2690+    // First go through each frame and for each mosaic pixel determine which frame it should come from
2691+    site_idx = 0;
2692+    for(CSite *csite = m_AllSites; csite < esite; csite++)
2693+    {
2694+        if(cancelComputation)
2695+        {
2696+            if (m_pMosaicVPyr) free(m_pMosaicVPyr);
2697+            if (m_pMosaicUPyr) free(m_pMosaicUPyr);
2698+            if (m_pMosaicYPyr) free(m_pMosaicYPyr);
2699+            return BLEND_RET_CANCELLED;
2700+        }
2701+
2702+        mb = csite->getMb();
2703+
2704+        mb->vcrect = mb->brect;
2705+        ClipBlendRect(csite, mb->vcrect);
2706+
2707+        ComputeMask(csite, mb->vcrect, mb->brect, rect, imgMos, site_idx);
2708+
2709+        site_idx++;
2710+    }
2711+
2712+    ////////// imgMos.Y, imgMos.V, imgMos.U are used as follows //////////////
2713+    ////////////////////// THIN STRIP MODE ///////////////////////////////////
2714+
2715+    // imgMos.Y is used to store the index of the image from which each pixel
2716+    // in the output mosaic can be read out for the thin-strip mode. Thus,
2717+    // there is no special handling for pixels around the seam. Also, imgMos.Y
2718+    // is set to 255 wherever we can't get its value from any input image e.g.
2719+    // in the gray border areas. imgMos.V and imgMos.U are set to 128 for the
2720+    // thin-strip mode.
2721+
2722+    ////////////////////// WIDE STRIP MODE ///////////////////////////////////
2723+
2724+    // imgMos.Y is used the same way as the thin-strip mode.
2725+    // imgMos.V is used to store the index of the neighboring image which
2726+    // should contribute to the color of an output pixel in a band around
2727+    // the seam. Thus, in this band, we will crossfade between the color values
2728+    // from the image index imgMos.Y and image index imgMos.V. imgMos.U is
2729+    // used to store the weight (multiplied by 100) that each image will
2730+    // contribute to the blending process. Thus, we start at 99% contribution
2731+    // from the first image, then go to 50% contribution from each image at
2732+    // the seam. Then, the contribution from the second image goes up to 99%.
2733+
2734+    // For WIDE mode, set the pixel masks to guide the blender to cross-fade
2735+    // between the images on either side of each seam:
2736+    if (m_wb.stripType == STRIP_TYPE_WIDE)
2737+    {
2738+        if(m_wb.horizontal)
2739+        {
2740+            // Set the number of pixels around the seam to cross-fade between
2741+            // the two component images,
2742+            int tw = STRIP_CROSS_FADE_WIDTH_PXLS;
2743+
2744+            // Proceed with the image index calculation for cross-fading
2745+            // only if the cross-fading width is larger than 0
2746+            if (tw > 0)
2747+            {
2748+                for(int y = 0; y < imgMos.Y.height; y++)
2749+                {
2750+                    // Since we compare two adjecant pixels to determine
2751+                    // whether there is a seam, the termination condition of x
2752+                    // is set to imgMos.Y.width - tw, so that x+1 below
2753+                    // won't exceed the imgMos' boundary.
2754+                    for(int x = tw; x < imgMos.Y.width - tw; )
2755+                    {
2756+                        // Determine where the seam is...
2757+                        if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y][x+1] &&
2758+                                imgMos.Y.ptr[y][x] != 255 &&
2759+                                imgMos.Y.ptr[y][x+1] != 255)
2760+                        {
2761+                            // Find the image indices on both sides of the seam
2762+                            unsigned char idx1 = imgMos.Y.ptr[y][x];
2763+                            unsigned char idx2 = imgMos.Y.ptr[y][x+1];
2764+
2765+                            for (int o = tw; o >= 0; o--)
2766+                            {
2767+                                // Set the image index to use for cross-fading
2768+                                imgMos.V.ptr[y][x - o] = idx2;
2769+                                // Set the intensity weights to use for cross-fading
2770+                                imgMos.U.ptr[y][x - o] = 50 + (99 - 50) * o / tw;
2771+                            }
2772+
2773+                            for (int o = 1; o <= tw; o++)
2774+                            {
2775+                                // Set the image index to use for cross-fading
2776+                                imgMos.V.ptr[y][x + o] = idx1;
2777+                                // Set the intensity weights to use for cross-fading
2778+                                imgMos.U.ptr[y][x + o] = imgMos.U.ptr[y][x - o];
2779+                            }
2780+
2781+                            x += (tw + 1);
2782+                        }
2783+                        else
2784+                        {
2785+                            x++;
2786+                        }
2787+                    }
2788+                }
2789+            }
2790+        }
2791+        else
2792+        {
2793+            // Set the number of pixels around the seam to cross-fade between
2794+            // the two component images,
2795+            int tw = STRIP_CROSS_FADE_WIDTH_PXLS;
2796+
2797+            // Proceed with the image index calculation for cross-fading
2798+            // only if the cross-fading width is larger than 0
2799+            if (tw > 0)
2800+            {
2801+                for(int x = 0; x < imgMos.Y.width; x++)
2802+                {
2803+                    // Since we compare two adjecant pixels to determine
2804+                    // whether there is a seam, the termination condition of y
2805+                    // is set to imgMos.Y.height - tw, so that y+1 below
2806+                    // won't exceed the imgMos' boundary.
2807+                    for(int y = tw; y < imgMos.Y.height - tw; )
2808+                    {
2809+                        // Determine where the seam is...
2810+                        if (imgMos.Y.ptr[y][x] != imgMos.Y.ptr[y+1][x] &&
2811+                                imgMos.Y.ptr[y][x] != 255 &&
2812+                                imgMos.Y.ptr[y+1][x] != 255)
2813+                        {
2814+                            // Find the image indices on both sides of the seam
2815+                            unsigned char idx1 = imgMos.Y.ptr[y][x];
2816+                            unsigned char idx2 = imgMos.Y.ptr[y+1][x];
2817+
2818+                            for (int o = tw; o >= 0; o--)
2819+                            {
2820+                                // Set the image index to use for cross-fading
2821+                                imgMos.V.ptr[y - o][x] = idx2;
2822+                                // Set the intensity weights to use for cross-fading
2823+                                imgMos.U.ptr[y - o][x] = 50 + (99 - 50) * o / tw;
2824+                            }
2825+
2826+                            for (int o = 1; o <= tw; o++)
2827+                            {
2828+                                // Set the image index to use for cross-fading
2829+                                imgMos.V.ptr[y + o][x] = idx1;
2830+                                // Set the intensity weights to use for cross-fading
2831+                                imgMos.U.ptr[y + o][x] = imgMos.U.ptr[y - o][x];
2832+                            }
2833+
2834+                            y += (tw + 1);
2835+                        }
2836+                        else
2837+                        {
2838+                            y++;
2839+                        }
2840+                    }
2841+                }
2842+            }
2843+        }
2844+
2845+    }
2846+
2847+    // Now perform the actual blending using the frame assignment determined above
2848+    site_idx = 0;
2849+    for(CSite *csite = m_AllSites; csite < esite; csite++)
2850+    {
2851+        if(cancelComputation)
2852+        {
2853+            if (m_pMosaicVPyr) free(m_pMosaicVPyr);
2854+            if (m_pMosaicUPyr) free(m_pMosaicUPyr);
2855+            if (m_pMosaicYPyr) free(m_pMosaicYPyr);
2856+            return BLEND_RET_CANCELLED;
2857+        }
2858+
2859+        mb = csite->getMb();
2860+
2861+
2862+        if(FillFramePyramid(mb)!=BLEND_RET_OK)
2863+            return BLEND_RET_ERROR;
2864+
2865+        ProcessPyramidForThisFrame(csite, mb->vcrect, mb->brect, rect, imgMos, mb->trs, site_idx);
2866+
2867+        progress += TIME_PERCENT_BLEND/nsite;
2868+
2869+        site_idx++;
2870+    }
2871+
2872+
2873+    // Blend
2874+    PerformFinalBlending(imgMos, cropping_rect);
2875+
2876+    if (cropping_rect.Width() <= 0 || cropping_rect.Height() <= 0)
2877+    {
2878+        return BLEND_RET_ERROR;
2879+    }
2880+
2881+    if (m_pMosaicVPyr) free(m_pMosaicVPyr);
2882+    if (m_pMosaicUPyr) free(m_pMosaicUPyr);
2883+    if (m_pMosaicYPyr) free(m_pMosaicYPyr);
2884+
2885+    progress += TIME_PERCENT_FINAL;
2886+
2887+    return BLEND_RET_OK;
2888+}
2889+
2890+void Blend::CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect)
2891+{
2892+    int i, j, k;
2893+    ImageType yimg;
2894+    ImageType uimg;
2895+    ImageType vimg;
2896+
2897+
2898+    yimg = imgMos.Y.ptr[0];
2899+    uimg = imgMos.U.ptr[0];
2900+    vimg = imgMos.V.ptr[0];
2901+
2902+    k = 0;
2903+    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
2904+    {
2905+        for (i = cropping_rect.left; i <= cropping_rect.right; i++)
2906+        {
2907+            yimg[k] = yimg[j*imgMos.Y.width+i];
2908+            k++;
2909+        }
2910+    }
2911+    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
2912+    {
2913+       for (i = cropping_rect.left; i <= cropping_rect.right; i++)
2914+        {
2915+            yimg[k] = vimg[j*imgMos.Y.width+i];
2916+            k++;
2917+        }
2918+    }
2919+    for (j = cropping_rect.top; j <= cropping_rect.bottom; j++)
2920+    {
2921+       for (i = cropping_rect.left; i <= cropping_rect.right; i++)
2922+        {
2923+            yimg[k] = uimg[j*imgMos.Y.width+i];
2924+            k++;
2925+        }
2926+    }
2927+}
2928+
2929+int Blend::PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect)
2930+{
2931+    if (!PyramidShort::BorderExpand(m_pMosaicYPyr, m_wb.nlevs, 1) || !PyramidShort::BorderExpand(m_pMosaicUPyr, m_wb.nlevsC, 1) ||
2932+        !PyramidShort::BorderExpand(m_pMosaicVPyr, m_wb.nlevsC, 1))
2933+    {
2934+      return BLEND_RET_ERROR;
2935+    }
2936+
2937+    ImageTypeShort myimg;
2938+    ImageTypeShort muimg;
2939+    ImageTypeShort mvimg;
2940+    ImageType yimg;
2941+    ImageType uimg;
2942+    ImageType vimg;
2943+
2944+    // 2D boolean array that contains true wherever the mosaic image data is
2945+    // invalid (i.e. in the gray border).
2946+    bool **b = new bool*[imgMos.Y.height];
2947+
2948+    for(int j=0; j<imgMos.Y.height; j++)
2949+    {
2950+        b[j] = new bool[imgMos.Y.width];
2951+    }
2952+
2953+    // Copy the resulting image into the full image using the mask
2954+    int i, j;
2955+
2956+    yimg = imgMos.Y.ptr[0];
2957+    uimg = imgMos.U.ptr[0];
2958+    vimg = imgMos.V.ptr[0];
2959+
2960+    for (j = 0; j < imgMos.Y.height; j++)
2961+    {
2962+        myimg = m_pMosaicYPyr->ptr[j];
2963+        muimg = m_pMosaicUPyr->ptr[j];
2964+        mvimg = m_pMosaicVPyr->ptr[j];
2965+
2966+        for (i = 0; i<imgMos.Y.width; i++)
2967+        {
2968+            // A final mask was set up previously,
2969+            // if the value is zero skip it, otherwise replace it.
2970+            if (*yimg <255)
2971+            {
2972+                short value = (short) ((*myimg) >> 3);
2973+                if (value < 0) value = 0;
2974+                else if (value > 255) value = 255;
2975+                *yimg = (unsigned char) value;
2976+
2977+                value = (short) ((*muimg) >> 3);
2978+                if (value < 0) value = 0;
2979+                else if (value > 255) value = 255;
2980+                *uimg = (unsigned char) value;
2981+
2982+                value = (short) ((*mvimg) >> 3);
2983+                if (value < 0) value = 0;
2984+                else if (value > 255) value = 255;
2985+                *vimg = (unsigned char) value;
2986+
2987+                b[j][i] = false;
2988+
2989+            }
2990+            else
2991+            {   // set border color in here
2992+                *yimg = (unsigned char) 96;
2993+                *uimg = (unsigned char) 128;
2994+                *vimg = (unsigned char) 128;
2995+
2996+                b[j][i] = true;
2997+            }
2998+
2999+            yimg++;
3000+            uimg++;
3001+            vimg++;
3002+            myimg++;
3003+            muimg++;
3004+            mvimg++;
3005+        }
3006+    }
3007+
3008+    if(m_wb.horizontal)
3009+    {
3010+        //Scan through each row and increment top if the row contains any gray
3011+        for (j = 0; j < imgMos.Y.height; j++)
3012+        {
3013+            for (i = cropping_rect.left; i < cropping_rect.right; i++)
3014+            {
3015+                if (b[j][i])
3016+                {
3017+                    break; // to next row
3018+                }
3019+            }
3020+
3021+            if (i == cropping_rect.right)   //no gray pixel in this row!
3022+            {
3023+                cropping_rect.top = j;
3024+                break;
3025+            }
3026+        }
3027+
3028+        //Scan through each row and decrement bottom if the row contains any gray
3029+        for (j = imgMos.Y.height-1; j >= 0; j--)
3030+        {
3031+            for (i = cropping_rect.left; i < cropping_rect.right; i++)
3032+            {
3033+                if (b[j][i])
3034+                {
3035+                    break; // to next row
3036+                }
3037+            }
3038+
3039+            if (i == cropping_rect.right)   //no gray pixel in this row!
3040+            {
3041+                cropping_rect.bottom = j;
3042+                break;
3043+            }
3044+        }
3045+    }
3046+    else // Vertical Mosaic
3047+    {
3048+        //Scan through each column and increment left if the column contains any gray
3049+        for (i = 0; i < imgMos.Y.width; i++)
3050+        {
3051+            for (j = cropping_rect.top; j < cropping_rect.bottom; j++)
3052+            {
3053+                if (b[j][i])
3054+                {
3055+                    break; // to next column
3056+                }
3057+            }
3058+
3059+            if (j == cropping_rect.bottom)   //no gray pixel in this column!
3060+            {
3061+                cropping_rect.left = i;
3062+                break;
3063+            }
3064+        }
3065+
3066+        //Scan through each column and decrement right if the column contains any gray
3067+        for (i = imgMos.Y.width-1; i >= 0; i--)
3068+        {
3069+            for (j = cropping_rect.top; j < cropping_rect.bottom; j++)
3070+            {
3071+                if (b[j][i])
3072+                {
3073+                    break; // to next column
3074+                }
3075+            }
3076+
3077+            if (j == cropping_rect.bottom)   //no gray pixel in this column!
3078+            {
3079+                cropping_rect.right = i;
3080+                break;
3081+            }
3082+        }
3083+
3084+    }
3085+
3086+    RoundingCroppingSizeToMultipleOf8(cropping_rect);
3087+
3088+    for(int j=0; j<imgMos.Y.height; j++)
3089+    {
3090+        delete b[j];
3091+    }
3092+
3093+    delete[] b;
3094+
3095+    return BLEND_RET_OK;
3096+}
3097+
3098+void Blend::RoundingCroppingSizeToMultipleOf8(MosaicRect &rect) {
3099+    int height = rect.bottom - rect.top + 1;
3100+    int residue = height & 7;
3101+    rect.bottom -= residue;
3102+
3103+    int width = rect.right - rect.left + 1;
3104+    residue = width & 7;
3105+    rect.right -= residue;
3106+}
3107+
3108+void Blend::ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx)
3109+{
3110+    PyramidShort *dptr = m_pMosaicYPyr;
3111+
3112+    int l = (int) ((vcrect.lft - rect.left));
3113+    int b = (int) ((vcrect.bot - rect.top));
3114+    int r = (int) ((vcrect.rgt - rect.left));
3115+    int t = (int) ((vcrect.top - rect.top));
3116+
3117+    if (vcrect.lft == brect.lft)
3118+        l = (l <= 0) ? -BORDER : l - BORDER;
3119+    else if (l < -BORDER)
3120+        l = -BORDER;
3121+
3122+    if (vcrect.bot == brect.bot)
3123+        b = (b <= 0) ? -BORDER : b - BORDER;
3124+    else if (b < -BORDER)
3125+        b = -BORDER;
3126+
3127+    if (vcrect.rgt == brect.rgt)
3128+        r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER;
3129+    else if (r >= dptr->width + BORDER)
3130+        r = dptr->width + BORDER - 1;
3131+
3132+    if (vcrect.top == brect.top)
3133+        t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER;
3134+    else if (t >= dptr->height + BORDER)
3135+        t = dptr->height + BORDER - 1;
3136+
3137+    // Walk the Region of interest and populate the pyramid
3138+    for (int j = b; j <= t; j++)
3139+    {
3140+        int jj = j;
3141+        double sj = jj + rect.top;
3142+
3143+        for (int i = l; i <= r; i++)
3144+        {
3145+            int ii = i;
3146+            // project point and then triangulate to neighbors
3147+            double si = ii + rect.left;
3148+
3149+            double dself = hypotSq(csite->getVCenter().x - si, csite->getVCenter().y - sj);
3150+            int inMask = ((unsigned) ii < imgMos.Y.width &&
3151+                    (unsigned) jj < imgMos.Y.height) ? 1 : 0;
3152+
3153+            if(!inMask)
3154+                continue;
3155+
3156+            // scan the neighbors to see if this is a valid position
3157+            SEdgeVector *ce;
3158+            int ecnt;
3159+            for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++)
3160+            {
3161+                double d1 = hypotSq(m_AllSites[ce->second].getVCenter().x - si,
3162+                        m_AllSites[ce->second].getVCenter().y - sj);
3163+                if (d1 < dself)
3164+                {
3165+                    break;
3166+                }
3167+            }
3168+
3169+            if (ecnt >= 0) continue;
3170+
3171+            imgMos.Y.ptr[jj][ii] = (unsigned char)site_idx;
3172+        }
3173+    }
3174+}
3175+
3176+void Blend::ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx)
3177+{
3178+    // Put the Region of interest (for all levels) into m_pMosaicYPyr
3179+    double inv_trs[3][3];
3180+    inv33d(trs, inv_trs);
3181+
3182+    // Process each pyramid level
3183+    PyramidShort *sptr = m_pFrameYPyr;
3184+    PyramidShort *suptr = m_pFrameUPyr;
3185+    PyramidShort *svptr = m_pFrameVPyr;
3186+
3187+    PyramidShort *dptr = m_pMosaicYPyr;
3188+    PyramidShort *duptr = m_pMosaicUPyr;
3189+    PyramidShort *dvptr = m_pMosaicVPyr;
3190+
3191+    int dscale = 0; // distance scale for the current level
3192+    int nC = m_wb.nlevsC;
3193+    for (int n = m_wb.nlevs; n--; dscale++, dptr++, sptr++, dvptr++, duptr++, svptr++, suptr++, nC--)
3194+    {
3195+        int l = (int) ((vcrect.lft - rect.left) / (1 << dscale));
3196+        int b = (int) ((vcrect.bot - rect.top) / (1 << dscale));
3197+        int r = (int) ((vcrect.rgt - rect.left) / (1 << dscale) + .5);
3198+        int t = (int) ((vcrect.top - rect.top) / (1 << dscale) + .5);
3199+
3200+        if (vcrect.lft == brect.lft)
3201+            l = (l <= 0) ? -BORDER : l - BORDER;
3202+        else if (l < -BORDER)
3203+            l = -BORDER;
3204+
3205+        if (vcrect.bot == brect.bot)
3206+            b = (b <= 0) ? -BORDER : b - BORDER;
3207+        else if (b < -BORDER)
3208+            b = -BORDER;
3209+
3210+        if (vcrect.rgt == brect.rgt)
3211+            r = (r >= dptr->width) ? dptr->width + BORDER - 1 : r + BORDER;
3212+        else if (r >= dptr->width + BORDER)
3213+            r = dptr->width + BORDER - 1;
3214+
3215+        if (vcrect.top == brect.top)
3216+            t = (t >= dptr->height) ? dptr->height + BORDER - 1 : t + BORDER;
3217+        else if (t >= dptr->height + BORDER)
3218+            t = dptr->height + BORDER - 1;
3219+
3220+        // Walk the Region of interest and populate the pyramid
3221+        for (int j = b; j <= t; j++)
3222+        {
3223+            int jj = (j << dscale);
3224+            double sj = jj + rect.top;
3225+
3226+            for (int i = l; i <= r; i++)
3227+            {
3228+                int ii = (i << dscale);
3229+                // project point and then triangulate to neighbors
3230+                double si = ii + rect.left;
3231+
3232+                int inMask = ((unsigned) ii < imgMos.Y.width &&
3233+                        (unsigned) jj < imgMos.Y.height) ? 1 : 0;
3234+
3235+                if(inMask && imgMos.Y.ptr[jj][ii] != site_idx &&
3236+                        imgMos.V.ptr[jj][ii] != site_idx &&
3237+                        imgMos.Y.ptr[jj][ii] != 255)
3238+                    continue;
3239+
3240+                // Setup weights for cross-fading
3241+                // Weight of the intensity already in the output pixel
3242+                double wt0 = 0.0;
3243+                // Weight of the intensity from the input pixel (current frame)
3244+                double wt1 = 1.0;
3245+
3246+                if (m_wb.stripType == STRIP_TYPE_WIDE)
3247+                {
3248+                    if(inMask && imgMos.Y.ptr[jj][ii] != 255)
3249+                    {
3250+                        // If not on a seam OR pyramid level exceeds
3251+                        // maximum level for cross-fading.
3252+                        if((imgMos.V.ptr[jj][ii] == 128) ||
3253+                            (dscale > STRIP_CROSS_FADE_MAX_PYR_LEVEL))
3254+                        {
3255+                            wt0 = 0.0;
3256+                            wt1 = 1.0;
3257+                        }
3258+                        else
3259+                        {
3260+                            wt0 = 1.0;
3261+                            wt1 = ((imgMos.Y.ptr[jj][ii] == site_idx) ?
3262+                                    (double)imgMos.U.ptr[jj][ii] / 100.0 :
3263+                                    1.0 - (double)imgMos.U.ptr[jj][ii] / 100.0);
3264+                        }
3265+                    }
3266+                }
3267+
3268+                // Project this mosaic point into the original frame coordinate space
3269+                double xx, yy;
3270+
3271+                MosaicToFrame(inv_trs, si, sj, xx, yy);
3272+
3273+                if (xx < 0.0 || yy < 0.0 || xx > width - 1.0 || yy > height - 1.0)
3274+                {
3275+                    if(inMask)
3276+                    {
3277+                        imgMos.Y.ptr[jj][ii] = 255;
3278+                        wt0 = 0.0f;
3279+                        wt1 = 1.0f;
3280+                    }
3281+                }
3282+
3283+                xx /= (1 << dscale);
3284+                yy /= (1 << dscale);
3285+
3286+
3287+                int x1 = (xx >= 0.0) ? (int) xx : (int) floor(xx);
3288+                int y1 = (yy >= 0.0) ? (int) yy : (int) floor(yy);
3289+
3290+                // Final destination in extended pyramid
3291+#ifndef LINEAR_INTERP
3292+                if(inSegment(x1, sptr->width, BORDER-1) &&
3293+                        inSegment(y1, sptr->height, BORDER-1))
3294+                {
3295+                    double xfrac = xx - x1;
3296+                    double yfrac = yy - y1;
3297+                    dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + .5 +
3298+                            wt1 * ciCalc(sptr, x1, y1, xfrac, yfrac));
3299+                    if (dvptr >= m_pMosaicVPyr && nC > 0)
3300+                    {
3301+                        duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] + .5 +
3302+                                wt1 * ciCalc(suptr, x1, y1, xfrac, yfrac));
3303+                        dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] + .5 +
3304+                                wt1 * ciCalc(svptr, x1, y1, xfrac, yfrac));
3305+                    }
3306+                }
3307+#else
3308+                if(inSegment(x1, sptr->width, BORDER) && inSegment(y1, sptr->height, BORDER))
3309+                {
3310+                    int x2 = x1 + 1;
3311+                    int y2 = y1 + 1;
3312+                    double xfrac = xx - x1;
3313+                    double yfrac = yy - y1;
3314+                    double y1val = sptr->ptr[y1][x1] +
3315+                        (sptr->ptr[y1][x2] - sptr->ptr[y1][x1]) * xfrac;
3316+                    double y2val = sptr->ptr[y2][x1] +
3317+                        (sptr->ptr[y2][x2] - sptr->ptr[y2][x1]) * xfrac;
3318+                    dptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
3319+
3320+                    if (dvptr >= m_pMosaicVPyr && nC > 0)
3321+                    {
3322+                        y1val = suptr->ptr[y1][x1] +
3323+                            (suptr->ptr[y1][x2] - suptr->ptr[y1][x1]) * xfrac;
3324+                        y2val = suptr->ptr[y2][x1] +
3325+                            (suptr->ptr[y2][x2] - suptr->ptr[y2][x1]) * xfrac;
3326+
3327+                        duptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
3328+
3329+                        y1val = svptr->ptr[y1][x1] +
3330+                            (svptr->ptr[y1][x2] - svptr->ptr[y1][x1]) * xfrac;
3331+                        y2val = svptr->ptr[y2][x1] +
3332+                            (svptr->ptr[y2][x2] - svptr->ptr[y2][x1]) * xfrac;
3333+
3334+                        dvptr->ptr[j][i] = (short) (y1val + yfrac * (y2val - y1val));
3335+                    }
3336+                }
3337+#endif
3338+                else
3339+                {
3340+                    clipToSegment(x1, sptr->width, BORDER);
3341+                    clipToSegment(y1, sptr->height, BORDER);
3342+
3343+                    dptr->ptr[j][i] = (short) (wt0 * dptr->ptr[j][i] + 0.5 +
3344+                            wt1 * sptr->ptr[y1][x1] );
3345+                    if (dvptr >= m_pMosaicVPyr && nC > 0)
3346+                    {
3347+                        dvptr->ptr[j][i] = (short) (wt0 * dvptr->ptr[j][i] +
3348+                                0.5 + wt1 * svptr->ptr[y1][x1] );
3349+                        duptr->ptr[j][i] = (short) (wt0 * duptr->ptr[j][i] +
3350+                                0.5 + wt1 * suptr->ptr[y1][x1] );
3351+                    }
3352+                }
3353+            }
3354+        }
3355+    }
3356+}
3357+
3358+void Blend::MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy)
3359+{
3360+    double X, Y, z;
3361+    if (m_wb.theta == 0.0)
3362+    {
3363+        X = x;
3364+        Y = y;
3365+    }
3366+    else if (m_wb.horizontal)
3367+    {
3368+        double alpha = x * m_wb.direction / m_wb.width;
3369+        double length = (y - alpha * m_wb.correction) * m_wb.direction + m_wb.radius;
3370+        double deltaTheta = m_wb.theta * alpha;
3371+        double sinTheta = sin(deltaTheta);
3372+        double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction;
3373+        X = length * sinTheta + m_wb.x;
3374+        Y = length * cosTheta + m_wb.y;
3375+    }
3376+    else
3377+    {
3378+        double alpha = y * m_wb.direction / m_wb.width;
3379+        double length = (x - alpha * m_wb.correction) * m_wb.direction + m_wb.radius;
3380+        double deltaTheta = m_wb.theta * alpha;
3381+        double sinTheta = sin(deltaTheta);
3382+        double cosTheta = sqrt(1.0 - sinTheta * sinTheta) * m_wb.direction;
3383+        Y = length * sinTheta + m_wb.y;
3384+        X = length * cosTheta + m_wb.x;
3385+    }
3386+    z = ProjZ(trs, X, Y, 1.0);
3387+    wx = ProjX(trs, X, Y, z, 1.0);
3388+    wy = ProjY(trs, X, Y, z, 1.0);
3389+}
3390+
3391+void Blend::FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy)
3392+{
3393+    // Project into the intermediate Mosaic coordinate system
3394+    double z = ProjZ(trs, x, y, 1.0);
3395+    double X = ProjX(trs, x, y, z, 1.0);
3396+    double Y = ProjY(trs, x, y, z, 1.0);
3397+
3398+    if (m_wb.theta == 0.0)
3399+    {
3400+        // No rotation, then this is all we need to do.
3401+        wx = X;
3402+        wy = Y;
3403+    }
3404+    else if (m_wb.horizontal)
3405+    {
3406+        double deltaX = X - m_wb.x;
3407+        double deltaY = Y - m_wb.y;
3408+        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
3409+        double deltaTheta = asin(deltaX / length);
3410+        double alpha = deltaTheta / m_wb.theta;
3411+        wx = alpha * m_wb.width * m_wb.direction;
3412+        wy = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction;
3413+    }
3414+    else
3415+    {
3416+        double deltaX = X - m_wb.x;
3417+        double deltaY = Y - m_wb.y;
3418+        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
3419+        double deltaTheta = asin(deltaY / length);
3420+        double alpha = deltaTheta / m_wb.theta;
3421+        wy = alpha * m_wb.width * m_wb.direction;
3422+        wx = (length - m_wb.radius) * m_wb.direction + alpha * m_wb.correction;
3423+    }
3424+}
3425+
3426+
3427+
3428+// Clip the region of interest as small as possible by using the Voronoi edges of
3429+// the neighbors
3430+void Blend::ClipBlendRect(CSite *csite, BlendRect &brect)
3431+{
3432+      SEdgeVector *ce;
3433+      int ecnt;
3434+      for (ce = csite->getNeighbor(), ecnt = csite->getNumNeighbors(); ecnt--; ce++)
3435+      {
3436+        // calculate the Voronoi bisector intersection
3437+        const double epsilon = 1e-5;
3438+        double dx = (m_AllSites[ce->second].getVCenter().x - m_AllSites[ce->first].getVCenter().x);
3439+        double dy = (m_AllSites[ce->second].getVCenter().y - m_AllSites[ce->first].getVCenter().y);
3440+        double xmid = m_AllSites[ce->first].getVCenter().x + dx/2.0;
3441+        double ymid = m_AllSites[ce->first].getVCenter().y + dy/2.0;
3442+        double inter;
3443+
3444+        if (dx > epsilon)
3445+        {
3446+          // neighbor is on right
3447+          if ((inter = m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) < brect.rgt)
3448+            brect.rgt = inter;
3449+        }
3450+        else if (dx < -epsilon)
3451+        {
3452+          // neighbor is on left
3453+          if ((inter = -m_wb.roundoffOverlap + xmid - dy * (((dy >= 0.0) ? brect.bot : brect.top) - ymid) / dx) > brect.lft)
3454+            brect.lft = inter;
3455+        }
3456+        if (dy > epsilon)
3457+        {
3458+          // neighbor is above
3459+          if ((inter = m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) < brect.top)
3460+            brect.top = inter;
3461+        }
3462+        else if (dy < -epsilon)
3463+        {
3464+          // neighbor is below
3465+          if ((inter = -m_wb.roundoffOverlap + ymid - dx * (((dx >= 0.0) ? brect.lft : brect.rgt) - xmid) / dy) > brect.bot)
3466+            brect.bot = inter;
3467+        }
3468+      }
3469+}
3470+
3471+void Blend::FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect)
3472+{
3473+    // We need to walk the perimeter since the borders can be bent.
3474+    brect.lft = brect.bot = 2e30;
3475+    brect.rgt = brect.top = -2e30;
3476+    double xpos, ypos;
3477+    double lasty = height - 1.0;
3478+    double lastx = width - 1.0;
3479+    int i;
3480+
3481+    for (i = width; i--;)
3482+    {
3483+
3484+        FrameToMosaic(trs, (double) i, 0.0, xpos, ypos);
3485+        ClipRect(xpos, ypos, brect);
3486+        FrameToMosaic(trs, (double) i, lasty, xpos, ypos);
3487+        ClipRect(xpos, ypos, brect);
3488+    }
3489+    for (i = height; i--;)
3490+    {
3491+        FrameToMosaic(trs, 0.0, (double) i, xpos, ypos);
3492+        ClipRect(xpos, ypos, brect);
3493+        FrameToMosaic(trs, lastx, (double) i, xpos, ypos);
3494+        ClipRect(xpos, ypos, brect);
3495+    }
3496+}
3497+
3498+void Blend::SelectRelevantFrames(MosaicFrame **frames, int frames_size,
3499+        MosaicFrame **relevant_frames, int &relevant_frames_size)
3500+{
3501+    MosaicFrame *first = frames[0];
3502+    MosaicFrame *last = frames[frames_size-1];
3503+    MosaicFrame *mb;
3504+
3505+    double midX = last->width / 2.0;
3506+    double midY = last->height / 2.0;
3507+    double z = ProjZ(first->trs, midX, midY, 1.0);
3508+    double firstX, firstY;
3509+    double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0);
3510+    double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0);
3511+
3512+    relevant_frames[0] = first; // Add first frame by default
3513+    relevant_frames_size = 1;
3514+
3515+    for (int i = 0; i < frames_size - 1; i++)
3516+    {
3517+        mb = frames[i];
3518+        double currX, currY;
3519+        z = ProjZ(mb->trs, midX, midY, 1.0);
3520+        currX = ProjX(mb->trs, midX, midY, z, 1.0);
3521+        currY = ProjY(mb->trs, midX, midY, z, 1.0);
3522+        double deltaX = currX - prevX;
3523+        double deltaY = currY - prevY;
3524+
3525+        if (fabs(deltaX) > STRIP_SEPARATION_THRESHOLD_PXLS ||
3526+                fabs(deltaY) > STRIP_SEPARATION_THRESHOLD_PXLS)
3527+        {
3528+            relevant_frames[relevant_frames_size] = mb;
3529+            relevant_frames_size++;
3530+
3531+            prevX = currX;
3532+            prevY = currY;
3533+        }
3534+    }
3535+
3536+    // Add last frame by default
3537+    relevant_frames[relevant_frames_size] = last;
3538+    relevant_frames_size++;
3539+}
3540+
3541+void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360)
3542+{
3543+    // For FULL and PAN modes, we do not unwarp the mosaic into a rectangular coordinate system
3544+    // and so we set the theta to 0 and return.
3545+    if (m_wb.blendingType != BLEND_TYPE_CYLPAN && m_wb.blendingType != BLEND_TYPE_HORZ)
3546+    {
3547+        m_wb.theta = 0.0;
3548+        return;
3549+    }
3550+
3551+    MosaicFrame *first = frames[0];
3552+    MosaicFrame *last = frames[frames_size-1];
3553+    MosaicFrame *mb;
3554+
3555+    double lxpos = last->trs[0][2], lypos = last->trs[1][2];
3556+    double fxpos = first->trs[0][2], fypos = first->trs[1][2];
3557+
3558+    // Calculate warp to produce proper stitching.
3559+    // get x, y displacement
3560+    double midX = last->width / 2.0;
3561+    double midY = last->height / 2.0;
3562+    double z = ProjZ(first->trs, midX, midY, 1.0);
3563+    double firstX, firstY;
3564+    double prevX = firstX = ProjX(first->trs, midX, midY, z, 1.0);
3565+    double prevY = firstY = ProjY(first->trs, midX, midY, z, 1.0);
3566+
3567+    double arcLength, lastTheta;
3568+    m_wb.theta = lastTheta = arcLength = 0.0;
3569+
3570+    // Step through all the frames to compute the total arc-length of the cone
3571+    // swept while capturing the mosaic (in the original conical coordinate system).
3572+    for (int i = 0; i < frames_size; i++)
3573+    {
3574+        mb = frames[i];
3575+        double currX, currY;
3576+        z = ProjZ(mb->trs, midX, midY, 1.0);
3577+        currX = ProjX(mb->trs, midX, midY, z, 1.0);
3578+        currY = ProjY(mb->trs, midX, midY, z, 1.0);
3579+        double deltaX = currX - prevX;
3580+        double deltaY = currY - prevY;
3581+
3582+        // The arcLength is computed by summing the lengths of the chords
3583+        // connecting the pairwise projected image centers of the input image frames.
3584+        arcLength += sqrt(deltaY * deltaY + deltaX * deltaX);
3585+
3586+        if (!is360)
3587+        {
3588+            double thisTheta = asin(mb->trs[1][0]);
3589+            m_wb.theta += thisTheta - lastTheta;
3590+            lastTheta = thisTheta;
3591+        }
3592+
3593+        prevX = currX;
3594+        prevY = currY;
3595+    }
3596+
3597+    // Stretch this to end at the proper alignment i.e. the width of the
3598+    // rectangle is determined by the arcLength computed above and the cone
3599+    // sector angle is determined using the rotation of the last frame.
3600+    m_wb.width = arcLength;
3601+    if (is360) m_wb.theta = asin(last->trs[1][0]);
3602+
3603+    // If there is no rotation, we're done.
3604+    if (m_wb.theta != 0.0)
3605+    {
3606+        double dx = prevX - firstX;
3607+        double dy = prevY - firstY;
3608+
3609+        // If the mosaic was captured by sweeping horizontally
3610+        if (abs(lxpos - fxpos) > abs(lypos - fypos))
3611+        {
3612+            m_wb.horizontal = 1;
3613+            // Calculate radius position to make ends exactly the same Y offset
3614+            double radiusTheta = dx / cos(3.14159 / 2.0 - m_wb.theta);
3615+            m_wb.radius = dy + radiusTheta * cos(m_wb.theta);
3616+            if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius;
3617+        }
3618+        else
3619+        {
3620+            m_wb.horizontal = 0;
3621+            // Calculate radius position to make ends exactly the same Y offset
3622+            double radiusTheta = dy / cos(3.14159 / 2.0 - m_wb.theta);
3623+            m_wb.radius = dx + radiusTheta * cos(m_wb.theta);
3624+            if (m_wb.radius < 0.0) m_wb.radius = -m_wb.radius;
3625+        }
3626+
3627+        // Determine major direction
3628+        if (m_wb.horizontal)
3629+        {
3630+            // Horizontal strip
3631+            // m_wb.x,y record the origin of the rectangle coordinate system.
3632+            if (is360) m_wb.x = firstX;
3633+            else
3634+            {
3635+                if (lxpos - fxpos < 0)
3636+                {
3637+                    m_wb.x = firstX + midX;
3638+                    z = ProjZ(last->trs, 0.0, midY, 1.0);
3639+                    prevX = ProjX(last->trs, 0.0, midY, z, 1.0);
3640+                    prevY = ProjY(last->trs, 0.0, midY, z, 1.0);
3641+                }
3642+                else
3643+                {
3644+                    m_wb.x = firstX - midX;
3645+                    z = ProjZ(last->trs, last->width - 1.0, midY, 1.0);
3646+                    prevX = ProjX(last->trs, last->width - 1.0, midY, z, 1.0);
3647+                    prevY = ProjY(last->trs, last->width - 1.0, midY, z, 1.0);
3648+                }
3649+            }
3650+            dy = prevY - firstY;
3651+            if (dy < 0.0) m_wb.direction = 1.0;
3652+            else m_wb.direction = -1.0;
3653+            m_wb.y = firstY - m_wb.radius * m_wb.direction;
3654+            if (dy * m_wb.theta > 0.0) m_wb.width = -m_wb.width;
3655+        }
3656+        else
3657+        {
3658+            // Vertical strip
3659+            if (is360) m_wb.y = firstY;
3660+            else
3661+            {
3662+                if (lypos - fypos < 0)
3663+                {
3664+                    m_wb.x = firstY + midY;
3665+                    z = ProjZ(last->trs, midX, 0.0, 1.0);
3666+                    prevX = ProjX(last->trs, midX, 0.0, z, 1.0);
3667+                    prevY = ProjY(last->trs, midX, 0.0, z, 1.0);
3668+                }
3669+                else
3670+                {
3671+                    m_wb.x = firstX - midX;
3672+                    z = ProjZ(last->trs, midX, last->height - 1.0, 1.0);
3673+                    prevX = ProjX(last->trs, midX, last->height - 1.0, z, 1.0);
3674+                    prevY = ProjY(last->trs, midX, last->height - 1.0, z, 1.0);
3675+                }
3676+            }
3677+            dx = prevX - firstX;
3678+            if (dx < 0.0) m_wb.direction = 1.0;
3679+            else m_wb.direction = -1.0;
3680+            m_wb.x = firstX - m_wb.radius * m_wb.direction;
3681+            if (dx * m_wb.theta > 0.0) m_wb.width = -m_wb.width;
3682+        }
3683+
3684+        // Calculate the correct correction factor
3685+        double deltaX = prevX - m_wb.x;
3686+        double deltaY = prevY - m_wb.y;
3687+        double length = sqrt(deltaX * deltaX + deltaY * deltaY);
3688+        double deltaTheta = (m_wb.horizontal) ? deltaX : deltaY;
3689+        deltaTheta = asin(deltaTheta / length);
3690+        m_wb.correction = ((m_wb.radius - length) * m_wb.direction) /
3691+            (deltaTheta / m_wb.theta);
3692+    }
3693+}
3694diff --git a/benchmark/feature_mos/src/mosaic/Blend.h b/benchmark/feature_mos/src/mosaic/Blend.h
3695new file mode 100644
3696index 00000000..175eacd4
3697--- /dev/null
3698+++ b/benchmark/feature_mos/src/mosaic/Blend.h
3699@@ -0,0 +1,128 @@
3700+/*
3701+ * Copyright (C) 2011 The Android Open Source Project
3702+ *
3703+ * Licensed under the Apache License, Version 2.0 (the "License");
3704+ * you may not use this file except in compliance with the License.
3705+ * You may obtain a copy of the License at
3706+ *
3707+ *      http://www.apache.org/licenses/LICENSE-2.0
3708+ *
3709+ * Unless required by applicable law or agreed to in writing, software
3710+ * distributed under the License is distributed on an "AS IS" BASIS,
3711+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3712+ * See the License for the specific language governing permissions and
3713+ * limitations under the License.
3714+ */
3715+
3716+///////////////////////////////////////////////////
3717+// Blend.h
3718+// $Id: Blend.h,v 1.23 2011/06/24 04:22:14 mbansal Exp $
3719+
3720+#ifndef BLEND_H
3721+#define BLEND_H
3722+
3723+#include "MosaicTypes.h"
3724+#include "Pyramid.h"
3725+#include "Delaunay.h"
3726+
3727+#define BLEND_RANGE_DEFAULT 6
3728+#define BORDER 8
3729+
3730+// Percent of total mosaicing time spent on each of the following operations
3731+const float TIME_PERCENT_ALIGN = 20.0;
3732+const float TIME_PERCENT_BLEND = 75.0;
3733+const float TIME_PERCENT_FINAL = 5.0;
3734+
3735+// This threshold determines the minimum separation between the image centers
3736+// of the input image frames for them to be accepted for blending in the
3737+// STRIP_TYPE_WIDE mode.
3738+const float STRIP_SEPARATION_THRESHOLD_PXLS = 10;
3739+
3740+// This threshold determines the number of pixels on either side of the strip
3741+// to cross-fade using the images contributing to each seam.
3742+const float STRIP_CROSS_FADE_WIDTH_PXLS = 2;
3743+// This specifies the maximum pyramid level to which cross-fading is applied.
3744+// The original image resolution is Level-0, half of that size is Level-1 and
3745+// so on. BLEND_RANGE_DEFAULT specifies the number of pyramid levels used by
3746+// the blending algorithm.
3747+const int STRIP_CROSS_FADE_MAX_PYR_LEVEL = 2;
3748+
3749+/**
3750+ *  Class for pyramid blending a mosaic.
3751+ */
3752+class Blend {
3753+
3754+public:
3755+
3756+  static const int BLEND_TYPE_NONE    = -1;
3757+  static const int BLEND_TYPE_FULL    = 0;
3758+  static const int BLEND_TYPE_PAN     = 1;
3759+  static const int BLEND_TYPE_CYLPAN  = 2;
3760+  static const int BLEND_TYPE_HORZ   = 3;
3761+
3762+  static const int STRIP_TYPE_THIN      = 0;
3763+  static const int STRIP_TYPE_WIDE      = 1;
3764+
3765+  static const int BLEND_RET_ERROR        = -1;
3766+  static const int BLEND_RET_OK           = 0;
3767+  static const int BLEND_RET_ERROR_MEMORY = 1;
3768+  static const int BLEND_RET_CANCELLED    = -2;
3769+
3770+  Blend();
3771+  ~Blend();
3772+
3773+  int initialize(int blendingType, int stripType, int frame_width, int frame_height);
3774+
3775+  int runBlend(MosaicFrame **frames, MosaicFrame **rframes, int frames_size, ImageType &imageMosaicYVU,
3776+        int &mosaicWidth, int &mosaicHeight, float &progress, bool &cancelComputation);
3777+
3778+protected:
3779+
3780+  PyramidShort *m_pFrameYPyr;
3781+  PyramidShort *m_pFrameUPyr;
3782+  PyramidShort *m_pFrameVPyr;
3783+
3784+  PyramidShort *m_pMosaicYPyr;
3785+  PyramidShort *m_pMosaicUPyr;
3786+  PyramidShort *m_pMosaicVPyr;
3787+
3788+  CDelaunay m_Triangulator;
3789+  CSite *m_AllSites;
3790+
3791+  BlendParams m_wb;
3792+
3793+  // Height and width of individual frames
3794+  int width, height;
3795+
3796+   // Height and width of mosaic
3797+  unsigned short Mwidth, Mheight;
3798+
3799+  // Helper functions
3800+  void FrameToMosaic(double trs[3][3], double x, double y, double &wx, double &wy);
3801+  void MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy);
3802+  void FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect);
3803+  void ClipBlendRect(CSite *csite, BlendRect &brect);
3804+  void AlignToMiddleFrame(MosaicFrame **frames, int frames_size);
3805+
3806+  int  DoMergeAndBlend(MosaicFrame **frames, int nsite,  int width, int height, YUVinfo &imgMos, MosaicRect &rect, MosaicRect &cropping_rect, float &progress, bool &cancelComputation);
3807+  void ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx);
3808+  void ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx);
3809+
3810+  int  FillFramePyramid(MosaicFrame *mb);
3811+
3812+  // TODO: need to add documentation about the parameters
3813+  void ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is360);
3814+  void SelectRelevantFrames(MosaicFrame **frames, int frames_size,
3815+        MosaicFrame **relevant_frames, int &relevant_frames_size);
3816+
3817+  int  PerformFinalBlending(YUVinfo &imgMos, MosaicRect &cropping_rect);
3818+  void CropFinalMosaic(YUVinfo &imgMos, MosaicRect &cropping_rect);
3819+
3820+private:
3821+   static const float LIMIT_SIZE_MULTIPLIER;
3822+   static const float LIMIT_HEIGHT_MULTIPLIER;
3823+   int MosaicSizeCheck(float sizeMultiplier, float heightMultiplier);
3824+   void RoundingCroppingSizeToMultipleOf8(MosaicRect& rect);
3825+};
3826+
3827+#endif
3828diff --git a/benchmark/feature_mos/src/mosaic/CSite.h b/benchmark/feature_mos/src/mosaic/CSite.h
3829new file mode 100644
3830index 00000000..928c1734
3831--- /dev/null
3832+++ b/benchmark/feature_mos/src/mosaic/CSite.h
3833@@ -0,0 +1,63 @@
3834+/*
3835+ * Copyright (C) 2011 The Android Open Source Project
3836+ *
3837+ * Licensed under the Apache License, Version 2.0 (the "License");
3838+ * you may not use this file except in compliance with the License.
3839+ * You may obtain a copy of the License at
3840+ *
3841+ *      http://www.apache.org/licenses/LICENSE-2.0
3842+ *
3843+ * Unless required by applicable law or agreed to in writing, software
3844+ * distributed under the License is distributed on an "AS IS" BASIS,
3845+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3846+ * See the License for the specific language governing permissions and
3847+ * limitations under the License.
3848+ */
3849+
3850+///////////////////////////////////////////////////
3851+// CSite.h
3852+// $Id: CSite.h,v 1.3 2011/06/17 13:35:47 mbansal Exp $
3853+
3854+#ifndef TRIDEL_H
3855+#define TRIDEL_H
3856+
3857+#include "MosaicTypes.h"
3858+
3859+typedef struct
3860+{
3861+    short first;
3862+    short second;
3863+} SEdgeVector;
3864+
3865+typedef struct
3866+{
3867+    double x;
3868+    double y;
3869+} SVec2d;
3870+
3871+class CSite
3872+{
3873+private:
3874+    MosaicFrame *mosaicFrame;
3875+    SEdgeVector *neighbor;
3876+    int numNeighbors;
3877+    SVec2d voronoiCenter;
3878+
3879+public:
3880+    CSite();
3881+    ~CSite();
3882+
3883+    inline MosaicFrame* getMb() { return mosaicFrame; }
3884+    inline SEdgeVector* getNeighbor() { return neighbor; }
3885+    inline int getNumNeighbors() { return numNeighbors; }
3886+    inline SVec2d& getVCenter() { return voronoiCenter; }
3887+    inline double X() { return voronoiCenter.x; }
3888+    inline double Y() { return voronoiCenter.y; }
3889+
3890+    inline void incrNumNeighbors() { numNeighbors++; }
3891+    inline void setNumNeighbors(int num) { numNeighbors = num; }
3892+    inline void setNeighbor(SEdgeVector *nb) { neighbor = nb; }
3893+    inline void setMb(MosaicFrame *mb) { mosaicFrame = mb; }
3894+};
3895+
3896+#endif
3897diff --git a/benchmark/feature_mos/src/mosaic/Delaunay.cpp b/benchmark/feature_mos/src/mosaic/Delaunay.cpp
3898new file mode 100644
3899index 00000000..e8015dfd
3900--- /dev/null
3901+++ b/benchmark/feature_mos/src/mosaic/Delaunay.cpp
3902@@ -0,0 +1,631 @@
3903+/*
3904+ * Copyright (C) 2011 The Android Open Source Project
3905+ *
3906+ * Licensed under the Apache License, Version 2.0 (the "License");
3907+ * you may not use this file except in compliance with the License.
3908+ * You may obtain a copy of the License at
3909+ *
3910+ *      http://www.apache.org/licenses/LICENSE-2.0
3911+ *
3912+ * Unless required by applicable law or agreed to in writing, software
3913+ * distributed under the License is distributed on an "AS IS" BASIS,
3914+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3915+ * See the License for the specific language governing permissions and
3916+ * limitations under the License.
3917+ */
3918+
3919+// Delaunay.cpp
3920+// $Id: Delaunay.cpp,v 1.10 2011/06/17 13:35:48 mbansal Exp $
3921+
3922+#include <stdio.h>
3923+#include <stdlib.h>
3924+#include <memory.h>
3925+#include "Delaunay.h"
3926+
3927+#define QQ 9   // Optimal value as determined by testing
3928+#define DM 38  // 2^(1+DM/2) element sort capability. DM=38 for >10^6 elements
3929+#define NYL -1
3930+#define valid(l) ccw(orig(basel), dest(l), dest(basel))
3931+
3932+
3933+CDelaunay::CDelaunay()
3934+{
3935+}
3936+
3937+CDelaunay::~CDelaunay()
3938+{
3939+}
3940+
3941+// Allocate storage, construct triangulation, compute voronoi corners
3942+int CDelaunay::triangulate(SEdgeVector **edges, int n_sites, int width, int height)
3943+{
3944+  EdgePointer cep;
3945+
3946+  deleteAllEdges();
3947+  buildTriangulation(n_sites);
3948+  cep = consolidateEdges();
3949+  *edges = ev;
3950+
3951+  // Note: construction_list will change ev
3952+  return constructList(cep, width, height);
3953+}
3954+
3955+// builds delaunay triangulation
3956+void CDelaunay::buildTriangulation(int size)
3957+{
3958+  int i, rows;
3959+  EdgePointer lefte, righte;
3960+
3961+  rows = (int)( 0.5 + sqrt( (double) size / log( (double) size )));
3962+
3963+  // Sort the pointers by  x-coordinate of site
3964+  for ( i=0 ; i < size ; i++ ) {
3965+    sp[i] = (SitePointer) i;
3966+  }
3967+
3968+  spsortx( sp, 0, size-1 );
3969+  build( 0, size-1, &lefte, &righte, rows );
3970+  oneBndryEdge = lefte;
3971+}
3972+
3973+// Recursive Delaunay Triangulation Procedure
3974+// Contains modifications for axis-switching division.
3975+void CDelaunay::build(int lo, int hi, EdgePointer *le, EdgePointer *re, int rows)
3976+{
3977+  EdgePointer a, b, c, ldo, rdi, ldi, rdo, maxx, minx;
3978+  int split, lowrows;
3979+  int low, high;
3980+  SitePointer s1, s2, s3;
3981+  low = lo;
3982+  high = hi;
3983+
3984+  if ( low < (high-2) ) {
3985+    // more than three elements; do recursion
3986+    minx = sp[low];
3987+    maxx = sp[high];
3988+    if (rows == 1) {    // time to switch axis of division
3989+      spsorty( sp, low, high);
3990+      rows = 65536;
3991+    }
3992+    lowrows = rows/2;
3993+    split = low - 1 + (int)
3994+      (0.5 + ((double)(high-low+1) * ((double)lowrows / (double)rows)));
3995+    build( low, split, &ldo, &ldi, lowrows );
3996+    build( split+1, high, &rdi, &rdo, (rows-lowrows) );
3997+    doMerge(&ldo, ldi, rdi, &rdo);
3998+    while (orig(ldo) != minx) {
3999+      ldo = rprev(ldo);
4000+    }
4001+    while (orig(rdo) != maxx) {
4002+      rdo = (SitePointer) lprev(rdo);
4003+    }
4004+    *le = ldo;
4005+    *re = rdo;
4006+  }
4007+  else if (low >= (high - 1)) { // two or one points
4008+    a = makeEdge(sp[low], sp[high]);
4009+    *le = a;
4010+    *re = (EdgePointer) sym(a);
4011+  } else { // three points
4012+    // 3 cases: triangles of 2 orientations, and 3 points on a line
4013+    a = makeEdge((s1 = sp[low]), (s2 = sp[low+1]));
4014+    b = makeEdge(s2, (s3 = sp[high]));
4015+    splice((EdgePointer) sym(a), b);
4016+    if (ccw(s1, s3, s2)) {
4017+      c = connectLeft(b, a);
4018+      *le = (EdgePointer) sym(c);
4019+      *re = c;
4020+    } else {
4021+      *le = a;
4022+      *re = (EdgePointer) sym(b);
4023+      if (ccw(s1, s2, s3)) {
4024+        // not colinear
4025+        c = connectLeft(b, a);
4026+      }
4027+    }
4028+  }
4029+}
4030+
4031+// Quad-edge manipulation primitives
4032+EdgePointer CDelaunay::makeEdge(SitePointer origin, SitePointer destination)
4033+{
4034+  EdgePointer temp, ans;
4035+  temp = allocEdge();
4036+  ans = temp;
4037+
4038+  onext(temp) = ans;
4039+  orig(temp) = origin;
4040+  onext(++temp) = (EdgePointer) (ans + 3);
4041+  onext(++temp) = (EdgePointer) (ans + 2);
4042+  orig(temp) = destination;
4043+  onext(++temp) = (EdgePointer) (ans + 1);
4044+
4045+  return(ans);
4046+}
4047+
4048+void CDelaunay::splice(EdgePointer a, EdgePointer b)
4049+{
4050+  EdgePointer alpha, beta, temp;
4051+  alpha = (EdgePointer) rot(onext(a));
4052+  beta = (EdgePointer) rot(onext(b));
4053+  temp = onext(alpha);
4054+  onext(alpha) = onext(beta);
4055+  onext(beta) = temp;
4056+  temp = onext(a);
4057+  onext(a) = onext(b);
4058+  onext(b) = temp;
4059+}
4060+
4061+EdgePointer CDelaunay::connectLeft(EdgePointer a, EdgePointer b)
4062+{
4063+  EdgePointer ans;
4064+  ans = makeEdge(dest(a), orig(b));
4065+  splice(ans, (EdgePointer) lnext(a));
4066+  splice((EdgePointer) sym(ans), b);
4067+  return(ans);
4068+}
4069+
4070+EdgePointer CDelaunay::connectRight(EdgePointer a, EdgePointer b)
4071+{
4072+  EdgePointer ans;
4073+  ans = makeEdge(dest(a), orig(b));
4074+  splice(ans, (EdgePointer) sym(a));
4075+  splice((EdgePointer) sym(ans), (EdgePointer) oprev(b));
4076+  return(ans);
4077+}
4078+
4079+// disconnects e from the rest of the structure and destroys it
4080+void CDelaunay::deleteEdge(EdgePointer e)
4081+{
4082+  splice(e, (EdgePointer) oprev(e));
4083+  splice((EdgePointer) sym(e), (EdgePointer) oprev(sym(e)));
4084+  freeEdge(e);
4085+}
4086+
4087+//
4088+// Overall storage allocation
4089+//
4090+
4091+// Quad-edge storage allocation
4092+CSite *CDelaunay::allocMemory(int n)
4093+{
4094+  unsigned int size;
4095+
4096+  size = ((sizeof(CSite) + sizeof(SitePointer)) * n +
4097+          (sizeof(SitePointer) + sizeof(EdgePointer)) * 12
4098+          ) * n;
4099+  if (!(sa = (CSite*) malloc(size))) {
4100+    return NULL;
4101+  }
4102+  sp = (SitePointer *) (sa + n);
4103+  ev = (SEdgeVector *) (org = sp + n);
4104+  next = (EdgePointer *) (org + 12 * n);
4105+  ei = (struct EDGE_INFO *) (next + 12 * n);
4106+  return sa;
4107+}
4108+
4109+void CDelaunay::freeMemory()
4110+{
4111+  if (sa) {
4112+    free(sa);
4113+    sa = (CSite*)NULL;
4114+  }
4115+}
4116+
4117+//
4118+// Edge storage management
4119+//
4120+
4121+void CDelaunay::deleteAllEdges()
4122+{
4123+    nextEdge = 0;
4124+    availEdge = NYL;
4125+}
4126+
4127+EdgePointer CDelaunay::allocEdge()
4128+{
4129+  EdgePointer ans;
4130+
4131+  if (availEdge == NYL) {
4132+    ans = nextEdge, nextEdge += 4;
4133+  } else {
4134+    ans = availEdge, availEdge = onext(availEdge);
4135+  }
4136+  return(ans);
4137+}
4138+
4139+void CDelaunay::freeEdge(EdgePointer e)
4140+{
4141+  e ^= e & 3;
4142+  onext(e) = availEdge;
4143+  availEdge = e;
4144+}
4145+
4146+EdgePointer CDelaunay::consolidateEdges()
4147+{
4148+  EdgePointer e;
4149+  int i,j;
4150+
4151+  while (availEdge != NYL) {
4152+    nextEdge -= 4; e = availEdge; availEdge = onext(availEdge);
4153+
4154+    if (e==nextEdge) {
4155+      continue; // the one deleted was the last one anyway
4156+    }
4157+    if ((oneBndryEdge&~3) == nextEdge) {
4158+      oneBndryEdge = (EdgePointer) (e | (oneBndryEdge&3));
4159+    }
4160+    for (i=0,j=3; i<4; i++,j=rot(j)) {
4161+      onext(e+i) = onext(nextEdge+i);
4162+      onext(rot(onext(e+i))) = (EdgePointer) (e+j);
4163+    }
4164+  }
4165+  return nextEdge;
4166+}
4167+
4168+//
4169+// Sorting Routines
4170+//
4171+
4172+int CDelaunay::xcmpsp(int i, int j)
4173+{
4174+  double d = sa[(i>=0)?sp[i]:sp1].X() - sa[(j>=0)?sp[j]:sp1].X();
4175+  if ( d > 0. ) {
4176+    return 1;
4177+  }
4178+  if ( d < 0. ) {
4179+    return -1;
4180+  }
4181+  d = sa[(i>=0)?sp[i]:sp1].Y() - sa[(j>=0)?sp[j]:sp1].Y();
4182+  if ( d > 0. ) {
4183+    return 1;
4184+  }
4185+  if ( d < 0. ) {
4186+    return -1;
4187+  }
4188+  return 0;
4189+}
4190+
4191+int CDelaunay::ycmpsp(int i, int j)
4192+{
4193+  double d = sa[(i>=0)?sp[i]:sp1].Y() - sa[(j>=0)?sp[j]:sp1].Y();
4194+  if ( d > 0. ) {
4195+    return 1;
4196+  }
4197+  if ( d < 0. ) {
4198+    return -1;
4199+  }
4200+  d = sa[(i>=0)?sp[i]:sp1].X() - sa[(j>=0)?sp[j]:sp1].X();
4201+  if ( d > 0. ) {
4202+    return 1;
4203+  }
4204+  if ( d < 0. ) {
4205+    return -1;
4206+  }
4207+  return 0;
4208+}
4209+
4210+int CDelaunay::cmpev(int i, int j)
4211+{
4212+  return (ev[i].first - ev[j].first);
4213+}
4214+
4215+void CDelaunay::swapsp(int i, int j)
4216+{
4217+  int t;
4218+  t = (i>=0) ? sp[i] : sp1;
4219+
4220+  if (i>=0) {
4221+    sp[i] = (j>=0)?sp[j]:sp1;
4222+  } else {
4223+    sp1 = (j>=0)?sp[j]:sp1;
4224+  }
4225+
4226+  if (j>=0) {
4227+    sp[j] = (SitePointer) t;
4228+  } else {
4229+    sp1 = (SitePointer) t;
4230+  }
4231+}
4232+
4233+void CDelaunay::swapev(int i, int j)
4234+{
4235+  SEdgeVector temp;
4236+
4237+  temp = ev[i];
4238+  ev[i] = ev[j];
4239+  ev[j] = temp;
4240+}
4241+
4242+void CDelaunay::copysp(int i, int j)
4243+{
4244+  if (j>=0) {
4245+    sp[j] = (i>=0)?sp[i]:sp1;
4246+  } else {
4247+    sp1 = (i>=0)?sp[i]:sp1;
4248+  }
4249+}
4250+
4251+void CDelaunay::copyev(int i, int j)
4252+{
4253+  ev[j] = ev[i];
4254+}
4255+
4256+void CDelaunay::spsortx(SitePointer *sp_in, int low, int high)
4257+{
4258+  sp = sp_in;
4259+  rcssort(low,high,-1,&CDelaunay::xcmpsp,&CDelaunay::swapsp,&CDelaunay::copysp);
4260+}
4261+
4262+void CDelaunay::spsorty(SitePointer *sp_in, int low, int high )
4263+{
4264+  sp = sp_in;
4265+  rcssort(low,high,-1,&CDelaunay::ycmpsp,&CDelaunay::swapsp,&CDelaunay::copysp);
4266+}
4267+
4268+void CDelaunay::rcssort(int lowelt, int highelt, int temp,
4269+                    int (CDelaunay::*comparison)(int,int),
4270+                    void (CDelaunay::*swap)(int,int),
4271+                    void (CDelaunay::*copy)(int,int))
4272+{
4273+  int m,sij,si,sj,sL,sk;
4274+  int stack[DM];
4275+
4276+  if (highelt-lowelt<=1) {
4277+    return;
4278+  }
4279+  if (highelt-lowelt>QQ) {
4280+    m = 0;
4281+    si = lowelt; sj = highelt;
4282+    for (;;) { // partition [si,sj] about median-of-3.
4283+      sij = (sj+si) >> 1;
4284+
4285+      // Now to sort elements si,sij,sj into order & set temp=their median
4286+      if ( (this->*comparison)( si,sij ) > 0 ) {
4287+        (this->*swap)( si,sij );
4288+      }
4289+      if ( (this->*comparison)( sij,sj ) > 0 ) {
4290+        (this->*swap)( sj,sij );
4291+        if ( (this->*comparison)( si,sij ) > 0 ) {
4292+          (this->*swap)( si,sij );
4293+        }
4294+      }
4295+      (this->*copy)( sij,temp );
4296+
4297+      // Now to partition into elements <=temp, >=temp, and ==temp.
4298+      sk = si; sL = sj;
4299+      do {
4300+        do {
4301+          sL--;
4302+        } while( (this->*comparison)( sL,temp ) > 0 );
4303+        do {
4304+          sk++;
4305+        } while( (this->*comparison)( temp,sk ) > 0 );
4306+        if ( sk < sL ) {
4307+          (this->*swap)( sL,sk );
4308+        }
4309+      } while(sk <= sL);
4310+
4311+      // Now to recurse on shorter partition, store longer partition on stack
4312+      if ( sL-si > sj-sk ) {
4313+        if ( sL-si < QQ ) {
4314+          if( m==0 ) {
4315+            break;  // empty stack && both partitions < QQ so break
4316+          } else {
4317+            sj = stack[--m];
4318+            si = stack[--m];
4319+          }
4320+        }
4321+        else {
4322+          if ( sj-sk < QQ ) {
4323+            sj = sL;
4324+          } else {
4325+            stack[m++] = si;
4326+            stack[m++] = sL;
4327+            si = sk;
4328+          }
4329+        }
4330+      }
4331+      else {
4332+        if ( sj-sk < QQ ) {
4333+          if ( m==0 ) {
4334+            break; // empty stack && both partitions < QQ so break
4335+          } else {
4336+            sj = stack[--m];
4337+            si = stack[--m];
4338+          }
4339+        }
4340+        else {
4341+          if ( sL-si < QQ ) {
4342+            si = sk;
4343+          } else {
4344+            stack[m++] = sk;
4345+            stack[m++] = sj;
4346+            sj = sL;
4347+          }
4348+        }
4349+      }
4350+    }
4351+  }
4352+
4353+  // Now for 0 or Data bounded  "straight insertion" sort of [0,nels-1]; if it is
4354+  // known that el[-1] = -INF, then can omit the "sk>=0" test and save time.
4355+  for (si=lowelt; si<highelt; si++) {
4356+    if ( (this->*comparison)( si,si+1 ) > 0 ) {
4357+      (this->*copy)( si+1,temp );
4358+      sj = sk = si;
4359+      sj++;
4360+      do {
4361+        (this->*copy)( sk,sj );
4362+        sj = sk;
4363+        sk--;
4364+      } while ( (this->*comparison)( sk,temp ) > 0 && sk>=lowelt );
4365+      (this->*copy)( temp,sj );
4366+    }
4367+  }
4368+}
4369+
4370+//
4371+// Geometric primitives
4372+//
4373+
4374+// incircle, as in the Guibas-Stolfi paper.
4375+int CDelaunay::incircle(SitePointer a, SitePointer b, SitePointer c, SitePointer d)
4376+{
4377+  double adx, ady, bdx, bdy, cdx, cdy, dx, dy, nad, nbd, ncd;
4378+  dx = sa[d].X();
4379+  dy = sa[d].Y();
4380+  adx = sa[a].X() - dx;
4381+  ady = sa[a].Y() - dy;
4382+  bdx = sa[b].X() - dx;
4383+  bdy = sa[b].Y() - dy;
4384+  cdx = sa[c].X() - dx;
4385+  cdy = sa[c].Y() - dy;
4386+  nad = adx*adx+ady*ady;
4387+  nbd = bdx*bdx+bdy*bdy;
4388+  ncd = cdx*cdx+cdy*cdy;
4389+  return( (0.0 < (nad * (bdx * cdy - bdy * cdx)
4390+                  + nbd * (cdx * ady - cdy * adx)
4391+                  + ncd * (adx * bdy - ady * bdx))) ? TRUE : FALSE );
4392+}
4393+
4394+// TRUE iff A, B, C form a counterclockwise oriented triangle
4395+int CDelaunay::ccw(SitePointer a, SitePointer b, SitePointer c)
4396+{
4397+  double ax = sa[a].X();
4398+  double bx = sa[b].X();
4399+  double cx = sa[c].X();
4400+  double ay = sa[a].Y();
4401+  double by = sa[b].Y();
4402+  double cy = sa[c].Y();
4403+
4404+  double val = (ax - cx)*(by - cy) - (bx - cx)*(ay - cy);
4405+  if ( val > 0.0) {
4406+    return true;
4407+  }
4408+
4409+  return false;
4410+}
4411+
4412+//
4413+// The Merge Procedure.
4414+//
4415+
4416+void CDelaunay::doMerge(EdgePointer *ldo, EdgePointer ldi, EdgePointer rdi, EdgePointer *rdo)
4417+{
4418+  int rvalid, lvalid;
4419+  EdgePointer basel,lcand,rcand,t;
4420+
4421+  for (;;) {
4422+    while (ccw(orig(ldi), dest(ldi), orig(rdi))) {
4423+        ldi = (EdgePointer) lnext(ldi);
4424+    }
4425+    if (ccw(dest(rdi), orig(rdi), orig(ldi))) {
4426+        rdi = (EdgePointer)rprev(rdi);
4427+    } else {
4428+      break;
4429+    }
4430+  }
4431+
4432+  basel = connectLeft((EdgePointer) sym(rdi), ldi);
4433+  lcand = rprev(basel);
4434+  rcand = (EdgePointer) oprev(basel);
4435+  if (orig(basel) == orig(*rdo)) {
4436+    *rdo = basel;
4437+  }
4438+  if (dest(basel) == orig(*ldo)) {
4439+    *ldo = (EdgePointer) sym(basel);
4440+  }
4441+
4442+  for (;;) {
4443+#if 1
4444+    if (valid(t=onext(lcand))) {
4445+#else
4446+    t = (EdgePointer)onext(lcand);
4447+    if (valid(basel, t)) {
4448+#endif
4449+      while (incircle(dest(lcand), dest(t), orig(lcand), orig(basel))) {
4450+        deleteEdge(lcand);
4451+        lcand = t;
4452+        t = onext(lcand);
4453+      }
4454+    }
4455+#if 1
4456+    if (valid(t=(EdgePointer)oprev(rcand))) {
4457+#else
4458+    t = (EdgePointer)oprev(rcand);
4459+    if (valid(basel, t)) {
4460+#endif
4461+      while (incircle(dest(t), dest(rcand), orig(rcand), dest(basel))) {
4462+        deleteEdge(rcand);
4463+        rcand = t;
4464+        t = (EdgePointer)oprev(rcand);
4465+      }
4466+    }
4467+
4468+#if 1
4469+    lvalid = valid(lcand);
4470+    rvalid = valid(rcand);
4471+#else
4472+    lvalid = valid(basel, lcand);
4473+    rvalid = valid(basel, rcand);
4474+#endif
4475+    if ((! lvalid) && (! rvalid)) {
4476+      return;
4477+    }
4478+
4479+    if (!lvalid ||
4480+        (rvalid && incircle(dest(lcand), orig(lcand), orig(rcand), dest(rcand)))) {
4481+      basel = connectLeft(rcand, (EdgePointer) sym(basel));
4482+      rcand = (EdgePointer) lnext(sym(basel));
4483+    } else {
4484+      basel = (EdgePointer) sym(connectRight(lcand, basel));
4485+      lcand = rprev(basel);
4486+    }
4487+  }
4488+}
4489+
4490+int CDelaunay::constructList(EdgePointer last, int width, int height)
4491+{
4492+  int c, i;
4493+  EdgePointer curr, src, nex;
4494+  SEdgeVector *currv, *prevv;
4495+
4496+  c = (int) ((curr = (EdgePointer) ((last & ~3))) >> 1);
4497+
4498+  for (last -= 4; last >= 0; last -= 4) {
4499+    src = orig(last);
4500+    nex = dest(last);
4501+    orig(--curr) = src;
4502+    orig(--curr) = nex;
4503+    orig(--curr) = nex;
4504+    orig(--curr) = src;
4505+  }
4506+  rcssort(0, c - 1, -1, &CDelaunay::cmpev, &CDelaunay::swapev, &CDelaunay::copyev);
4507+
4508+  // Throw out any edges that are too far apart
4509+  currv = prevv = ev;
4510+  for (i = c; i--; currv++) {
4511+      if ((int) fabs(sa[currv->first].getVCenter().x - sa[currv->second].getVCenter().x) <= width &&
4512+          (int) fabs(sa[currv->first].getVCenter().y - sa[currv->second].getVCenter().y) <= height) {
4513+          *(prevv++) = *currv;
4514+      } else {
4515+        c--;
4516+      }
4517+  }
4518+  return c;
4519+}
4520+
4521+// Fill in site neighbor information
4522+void CDelaunay::linkNeighbors(SEdgeVector *edge, int nedge, int nsite)
4523+{
4524+  int i;
4525+
4526+  for (i = 0; i < nsite; i++) {
4527+    sa[i].setNeighbor(edge);
4528+    sa[i].setNumNeighbors(0);
4529+    for (; edge->first == i && nedge; edge++, nedge--) {
4530+      sa[i].incrNumNeighbors();
4531+    }
4532+  }
4533+}
4534diff --git a/benchmark/feature_mos/src/mosaic/Delaunay.h b/benchmark/feature_mos/src/mosaic/Delaunay.h
4535new file mode 100644
4536index 00000000..7a450b5e
4537--- /dev/null
4538+++ b/benchmark/feature_mos/src/mosaic/Delaunay.h
4539@@ -0,0 +1,126 @@
4540+/*
4541+ * Copyright (C) 2011 The Android Open Source Project
4542+ *
4543+ * Licensed under the Apache License, Version 2.0 (the "License");
4544+ * you may not use this file except in compliance with the License.
4545+ * You may obtain a copy of the License at
4546+ *
4547+ *      http://www.apache.org/licenses/LICENSE-2.0
4548+ *
4549+ * Unless required by applicable law or agreed to in writing, software
4550+ * distributed under the License is distributed on an "AS IS" BASIS,
4551+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4552+ * See the License for the specific language governing permissions and
4553+ * limitations under the License.
4554+ */
4555+
4556+// Delaunay.h
4557+// $Id: Delaunay.h,v 1.9 2011/06/17 13:35:48 mbansal Exp $
4558+
4559+#ifndef DELAUNAY_H
4560+#define DELAUNAY_H
4561+#include <stdio.h>
4562+#include <math.h>
4563+#include "CSite.h"
4564+#include "EdgePointerUtil.h"
4565+
4566+#ifndef TRUE
4567+#define TRUE 1==1
4568+#define FALSE 0==1
4569+#endif
4570+
4571+//******************************************************************************
4572+// Reference for Quad-edge data structure:
4573+//
4574+// Leonidas Guibas and Jorge Stolfi, "Primitives for the manipulation of general
4575+//     subdivisions and the computations of Voronoi diagrams",
4576+//     ACM Transactions on Graphics 4, 74-123 (1985).
4577+//
4578+//******************************************************************************
4579+
4580+//
4581+// Common data structures
4582+//
4583+
4584+typedef short SitePointer;
4585+typedef short TrianglePointer;
4586+
4587+class CDelaunay
4588+{
4589+private:
4590+  CSite *sa;
4591+  EdgePointer oneBndryEdge;
4592+  EdgePointer *next;
4593+  SitePointer *org;
4594+  struct EDGE_INFO *ei;
4595+  SitePointer *sp;
4596+  SEdgeVector *ev;
4597+
4598+  SitePointer sp1;
4599+  EdgePointer nextEdge;
4600+  EdgePointer availEdge;
4601+
4602+private:
4603+  void build(int lo, int hi, EdgePointer *le, EdgePointer *re, int rows);
4604+  void buildTriangulation(int size);
4605+
4606+  EdgePointer allocEdge();
4607+  void freeEdge(EdgePointer e);
4608+
4609+  EdgePointer makeEdge(SitePointer origin, SitePointer destination);
4610+  void deleteEdge(EdgePointer e);
4611+
4612+  void splice(EdgePointer, EdgePointer);
4613+  EdgePointer consolidateEdges();
4614+  void deleteAllEdges();
4615+
4616+  void spsortx(SitePointer *, int, int);
4617+  void spsorty(SitePointer *, int, int);
4618+
4619+  int cmpev(int i, int j);
4620+  int xcmpsp(int i, int j);
4621+  int ycmpsp(int i, int j);
4622+
4623+  void swapsp(int i, int j);
4624+  void swapev(int i, int j);
4625+
4626+  void copysp(int i, int j);
4627+  void copyev(int i, int j);
4628+
4629+  void rcssort(int lowelt, int highelt, int temp,
4630+                 int (CDelaunay::*comparison)(int,int),
4631+                 void (CDelaunay::*swap)(int,int),
4632+                 void (CDelaunay::*copy)(int,int));
4633+
4634+  void doMerge(EdgePointer *ldo, EdgePointer ldi, EdgePointer rdi, EdgePointer *rdo);
4635+  EdgePointer connectLeft(EdgePointer a, EdgePointer b);
4636+  EdgePointer connectRight(EdgePointer a, EdgePointer b);
4637+  int ccw(SitePointer a, SitePointer b, SitePointer c);
4638+  int incircle(SitePointer a, SitePointer b, SitePointer c, SitePointer d);
4639+  int constructList(EdgePointer e, int width, int height);
4640+
4641+public:
4642+  CDelaunay();
4643+  ~CDelaunay();
4644+
4645+  CSite *allocMemory(int nsite);
4646+  void freeMemory();
4647+  int triangulate(SEdgeVector **edge, int nsite, int width, int height);
4648+  void linkNeighbors(SEdgeVector *edge, int nedge, int nsite);
4649+};
4650+
4651+#define onext(a) next[a]
4652+#define oprev(a) rot(onext(rot(a)))
4653+#define lnext(a) rot(onext(rotinv(a)))
4654+#define lprev(a) sym(onext(a))
4655+#define rnext(a) rotinv(onext(rot(a)))
4656+#define rprev(a) onext(sym(a))
4657+#define dnext(a) sym(onext(sym(a)))
4658+#define dprev(a) rotinv(onext(rotinv(a)))
4659+
4660+#define orig(a) org[a]
4661+#define dest(a) orig(sym(a))
4662+#define left(a) orig(rotinv(a))
4663+#define right(a) orig(rot(a))
4664+
4665+#endif
4666diff --git a/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h b/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h
4667new file mode 100644
4668index 00000000..fad05d7e
4669--- /dev/null
4670+++ b/benchmark/feature_mos/src/mosaic/EdgePointerUtil.h
4671@@ -0,0 +1,37 @@
4672+/*
4673+ * Copyright (C) 2011 The Android Open Source Project
4674+ *
4675+ * Licensed under the Apache License, Version 2.0 (the "License");
4676+ * you may not use this file except in compliance with the License.
4677+ * You may obtain a copy of the License at
4678+ *
4679+ *      http://www.apache.org/licenses/LICENSE-2.0
4680+ *
4681+ * Unless required by applicable law or agreed to in writing, software
4682+ * distributed under the License is distributed on an "AS IS" BASIS,
4683+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4684+ * See the License for the specific language governing permissions and
4685+ * limitations under the License.
4686+ */
4687+
4688+#ifndef _EDGEPOINTERUTIL_H_
4689+#define _EDGEPOINTERUTIL_H_
4690+
4691+typedef short EdgePointer;
4692+
4693+inline EdgePointer sym(EdgePointer a)
4694+{
4695+  return a ^ 2;
4696+}
4697+
4698+inline EdgePointer rot(EdgePointer a)
4699+{
4700+  return (((a) + 1) & 3) | ((a) & ~3);
4701+}
4702+
4703+inline EdgePointer rotinv(EdgePointer a)
4704+{
4705+  return (((a) + 3) & 3) | ((a) & ~3);
4706+}
4707+
4708+#endif //_EDGEPOINTERUTIL_H_
4709diff --git a/benchmark/feature_mos/src/mosaic/Geometry.h b/benchmark/feature_mos/src/mosaic/Geometry.h
4710new file mode 100644
4711index 00000000..0efa0f4a
4712--- /dev/null
4713+++ b/benchmark/feature_mos/src/mosaic/Geometry.h
4714@@ -0,0 +1,156 @@
4715+/*
4716+ * Copyright (C) 2011 The Android Open Source Project
4717+ *
4718+ * Licensed under the Apache License, Version 2.0 (the "License");
4719+ * you may not use this file except in compliance with the License.
4720+ * You may obtain a copy of the License at
4721+ *
4722+ *      http://www.apache.org/licenses/LICENSE-2.0
4723+ *
4724+ * Unless required by applicable law or agreed to in writing, software
4725+ * distributed under the License is distributed on an "AS IS" BASIS,
4726+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4727+ * See the License for the specific language governing permissions and
4728+ * limitations under the License.
4729+ */
4730+
4731+/////////////////////////////
4732+// Geometry.h
4733+// $Id: Geometry.h,v 1.2 2011/06/17 13:35:48 mbansal Exp $
4734+
4735+#pragma once
4736+#include "MosaicTypes.h"
4737+
4738+///////////////////////////////////////////////////////////////
4739+///////////////// BEG GLOBAL ROUTINES /////////////////////////
4740+///////////////////////////////////////////////////////////////
4741+
4742+
4743+inline double hypotSq(double a, double b)
4744+{
4745+    return ((a)*(a)+(b)*(b));
4746+}
4747+
4748+inline void ClipRect(double x, double y, BlendRect &brect)
4749+{
4750+    if (y < brect.bot) brect.bot = y;
4751+    if (y > brect.top) brect.top = y;
4752+    if (x < brect.lft) brect.lft = x;
4753+    if (x > brect.rgt) brect.rgt = x;
4754+}
4755+
4756+inline void ClipRect(BlendRect rrect, BlendRect &brect)
4757+{
4758+    if (rrect.bot < brect.bot) brect.bot = rrect.bot;
4759+    if (rrect.top > brect.top) brect.top = rrect.top;
4760+    if (rrect.lft < brect.lft) brect.lft = rrect.lft;
4761+    if (rrect.rgt > brect.rgt) brect.rgt = rrect.rgt;
4762+}
4763+
4764+// Clip x to be within [-border,width+border-1]
4765+inline void clipToSegment(int &x, int width, int border)
4766+{
4767+    if(x < -border)
4768+        x = -border;
4769+    else if(x >= width+border)
4770+        x = width + border - 1;
4771+}
4772+
4773+// Return true if x within [-border,width+border-1]
4774+inline bool inSegment(int x, int width, int border)
4775+{
4776+    return (x >= -border && x < width + border - 1);
4777+}
4778+
4779+inline void FindTriangleCentroid(double x0, double y0, double x1, double y1,
4780+                                    double x2, double y2,
4781+                                    double &mass, double &centX, double &centY)
4782+{
4783+    // Calculate the centroid of the triangle
4784+    centX = (x0 + x1 + x2) / 3.0;
4785+    centY = (y0 + y1 + y2) / 3.0;
4786+
4787+    // Calculate 2*Area for the triangle
4788+    if (y0 == y2)
4789+    {
4790+        if (x0 == x1)
4791+        {
4792+            mass = fabs((y1 - y0) * (x2 - x0)); // Special case 1a
4793+        }
4794+        else
4795+        {
4796+            mass = fabs((y1 - y0) * (x1 - x0)); // Special case 1b
4797+        }
4798+    }
4799+    else if (x0 == x2)
4800+    {
4801+        if (x0 == x1)
4802+        {
4803+            mass = fabs((x2 - x0) * (y2 - y0)); // Special case 2a
4804+        }
4805+        else
4806+        {
4807+            mass = fabs((x1 - x0) * (y2 - y0)); // Special case 2a
4808+        }
4809+    }
4810+    else if (x1 == x2)
4811+    {
4812+        mass = fabs((x1 - x0) * (y2 - y0)); // Special case 3
4813+    }
4814+    else
4815+    {
4816+        // Calculate line equation from x0,y0 to x2,y2
4817+        double dx = x2 - x0;
4818+        double dy = y2 - y0;
4819+        // Calculate the length of the side
4820+        double len1 = sqrt(dx * dx + dy * dy);
4821+        double m1 = dy / dx;
4822+        double b1 = y0 - m1 * x0;
4823+        // Calculate the line that goes through x1,y1 and is perpendicular to
4824+        // the other line
4825+        double m2 = 1.0 / m1;
4826+        double b2 = y1 - m2 * x1;
4827+        // Calculate the intersection of the two lines
4828+        if (fabs( m1 - m2 ) > 1.e-6)
4829+        {
4830+            double x = (b2 - b1) / (m1 - m2);
4831+            // the mass is the base * height
4832+            dx = x1 - x;
4833+            dy = y1 - m1 * x + b1;
4834+            mass = len1 * sqrt(dx * dx + dy * dy);
4835+        }
4836+        else
4837+        {
4838+            mass = fabs( (y1 - y0) * (x2 - x0) );
4839+        }
4840+    }
4841+}
4842+
4843+inline void FindQuadCentroid(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3,
4844+                                     double &centX, double &centY)
4845+
4846+{
4847+    // To find the centroid:
4848+    // 1) Divide the quadrilateral into two triangles by scribing a diagonal
4849+    // 2) Calculate the centroid of each triangle (the intersection of the angle bisections).
4850+    // 3) Find the centroid of the quad by weighting each triangle centroids by their area.
4851+
4852+    // Calculate the corner points
4853+    double z;
4854+
4855+    // The quad is split from x0,y0 to x2,y2
4856+    double mass1, mass2, cent1x, cent2x, cent1y, cent2y;
4857+    FindTriangleCentroid(x0, y0, x1, y1, x2, y2, mass1, cent1x, cent1y);
4858+    FindTriangleCentroid(x0, y0, x3, y3, x2, y2, mass2, cent2x, cent2y);
4859+
4860+    // determine position of quad centroid
4861+    z = mass2 / (mass1 + mass2);
4862+    centX = cent1x + (cent2x - cent1x) * z;
4863+    centY = cent1y + (cent2y - cent1y) * z;
4864+}
4865+
4866+///////////////////////////////////////////////////////////////
4867+////////////////// END GLOBAL ROUTINES ////////////////////////
4868+///////////////////////////////////////////////////////////////
4869+
4870+
4871diff --git a/benchmark/feature_mos/src/mosaic/ImageUtils.cpp b/benchmark/feature_mos/src/mosaic/ImageUtils.cpp
4872new file mode 100644
4873index 00000000..28629d34
4874--- /dev/null
4875+++ b/benchmark/feature_mos/src/mosaic/ImageUtils.cpp
4876@@ -0,0 +1,406 @@
4877+/*
4878+ * Copyright (C) 2011 The Android Open Source Project
4879+ *
4880+ * Licensed under the Apache License, Version 2.0 (the "License");
4881+ * you may not use this file except in compliance with the License.
4882+ * You may obtain a copy of the License at
4883+ *
4884+ *      http://www.apache.org/licenses/LICENSE-2.0
4885+ *
4886+ * Unless required by applicable law or agreed to in writing, software
4887+ * distributed under the License is distributed on an "AS IS" BASIS,
4888+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4889+ * See the License for the specific language governing permissions and
4890+ * limitations under the License.
4891+ */
4892+
4893+///////////////////////////////////////////////////
4894+// ImageUtils.cpp
4895+// $Id: ImageUtils.cpp,v 1.12 2011/06/17 13:35:48 mbansal Exp $
4896+
4897+
4898+#include <stdio.h>
4899+#include <stdlib.h>
4900+#include <sys/time.h>
4901+
4902+#include "ImageUtils.h"
4903+
4904+void ImageUtils::rgba2yvu(ImageType out, ImageType in, int width, int height)
4905+{
4906+  int r,g,b, a;
4907+  ImageType yimg = out;
4908+  ImageType vimg = yimg + width*height;
4909+  ImageType uimg = vimg + width*height;
4910+  ImageType image = in;
4911+
4912+  for (int ii = 0; ii < height; ii++) {
4913+    for (int ij = 0; ij < width; ij++) {
4914+      r = (*image++);
4915+      g = (*image++);
4916+      b = (*image++);
4917+      a = (*image++);
4918+
4919+      if (r < 0) r = 0;
4920+      if (r > 255) r = 255;
4921+      if (g < 0) g = 0;
4922+      if (g > 255) g = 255;
4923+      if (b < 0) b = 0;
4924+      if (b > 255) b = 255;
4925+
4926+      int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
4927+      if (val < 0) val = 0;
4928+      if (val > 255) val = 255;
4929+      *(yimg) = val;
4930+
4931+      val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
4932+      if (val < 0) val = 0;
4933+      if (val > 255) val = 255;
4934+      *(vimg) = val;
4935+
4936+      val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
4937+      if (val < 0) val = 0;
4938+      if (val > 255) val = 255;
4939+      *(uimg) = val;
4940+
4941+      yimg++;
4942+      uimg++;
4943+      vimg++;
4944+    }
4945+  }
4946+}
4947+
4948+
4949+void ImageUtils::rgb2yvu(ImageType out, ImageType in, int width, int height)
4950+{
4951+  int r,g,b;
4952+  ImageType yimg = out;
4953+  ImageType vimg = yimg + width*height;
4954+  ImageType uimg = vimg + width*height;
4955+  ImageType image = in;
4956+
4957+  for (int ii = 0; ii < height; ii++) {
4958+    for (int ij = 0; ij < width; ij++) {
4959+      r = (*image++);
4960+      g = (*image++);
4961+      b = (*image++);
4962+
4963+      if (r < 0) r = 0;
4964+      if (r > 255) r = 255;
4965+      if (g < 0) g = 0;
4966+      if (g > 255) g = 255;
4967+      if (b < 0) b = 0;
4968+      if (b > 255) b = 255;
4969+
4970+      int val = (int) (REDY * r + GREENY * g + BLUEY * b) / 1000 + 16;
4971+      if (val < 0) val = 0;
4972+      if (val > 255) val = 255;
4973+      *(yimg) = val;
4974+
4975+      val = (int) (REDV * r - GREENV * g - BLUEV * b) / 1000 + 128;
4976+      if (val < 0) val = 0;
4977+      if (val > 255) val = 255;
4978+      *(vimg) = val;
4979+
4980+      val = (int) (-REDU * r - GREENU * g + BLUEU * b) / 1000 + 128;
4981+      if (val < 0) val = 0;
4982+      if (val > 255) val = 255;
4983+      *(uimg) = val;
4984+
4985+      yimg++;
4986+      uimg++;
4987+      vimg++;
4988+    }
4989+  }
4990+}
4991+
4992+ImageType ImageUtils::rgb2gray(ImageType in, int width, int height)
4993+{
4994+  int r,g,b;
4995+  ImageType image = in;
4996+  ImageType out = ImageUtils::allocateImage(width, height, 1);
4997+  ImageType outCopy = out;
4998+
4999+  for (int ii = 0; ii < height; ii++) {
5000+    for (int ij = 0; ij < width; ij++) {
5001+      r = (*image++);
5002+      g = (*image++);
5003+      b = (*image++);
5004+
5005+      if (r < 0) r = 0;
5006+      if (r > 255) r = 255;
5007+      if (g < 0) g = 0;
5008+      if (g > 255) g = 255;
5009+      if (b < 0) b = 0;
5010+      if (b > 255) b = 255;
5011+
5012+      (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
5013+
5014+      outCopy++;
5015+    }
5016+  }
5017+
5018+  return out;
5019+}
5020+
5021+ImageType ImageUtils::rgb2gray(ImageType out, ImageType in, int width, int height)
5022+{
5023+  int r,g,b;
5024+  ImageType image = in;
5025+  ImageType outCopy = out;
5026+
5027+  for (int ii = 0; ii < height; ii++) {
5028+    for (int ij = 0; ij < width; ij++) {
5029+      r = (*image++);
5030+      g = (*image++);
5031+      b = (*image++);
5032+
5033+      if (r < 0) r = 0;
5034+      if (r > 255) r = 255;
5035+      if (g < 0) g = 0;
5036+      if (g > 255) g = 255;
5037+      if (b < 0) b = 0;
5038+      if (b > 255) b = 255;
5039+
5040+      (*outCopy) = ( 0.3*r + 0.59*g + 0.11*b);
5041+
5042+      outCopy++;
5043+    }
5044+  }
5045+
5046+  return out;
5047+
5048+}
5049+
5050+ImageType *ImageUtils::imageTypeToRowPointers(ImageType in, int width, int height)
5051+{
5052+  int i;
5053+  int m_h = height;
5054+  int m_w = width;
5055+
5056+  ImageType *m_rows = new ImageType[m_h];
5057+
5058+  for (i=0;i<m_h;i++) {
5059+    m_rows[i] = &in[(m_w)*i];
5060+  }
5061+  return m_rows;
5062+}
5063+
5064+void ImageUtils::yvu2rgb(ImageType out, ImageType in, int width, int height)
5065+{
5066+  int y,v,u, r, g, b;
5067+  unsigned char *yimg = in;
5068+  unsigned char *vimg = yimg + width*height;
5069+  unsigned char *uimg = vimg + width*height;
5070+  unsigned char *image = out;
5071+
5072+  for (int i = 0; i < height; i++) {
5073+    for (int j = 0; j < width; j++) {
5074+
5075+      y = (*yimg);
5076+      v = (*vimg);
5077+      u = (*uimg);
5078+
5079+      if (y < 0) y = 0;
5080+      if (y > 255) y = 255;
5081+      if (u < 0) u = 0;
5082+      if (u > 255) u = 255;
5083+      if (v < 0) v = 0;
5084+      if (v > 255) v = 255;
5085+
5086+      b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
5087+      g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
5088+      r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
5089+
5090+      if (r < 0) r = 0;
5091+      if (r > 255) r = 255;
5092+      if (g < 0) g = 0;
5093+      if (g > 255) g = 255;
5094+      if (b < 0) b = 0;
5095+      if (b > 255) b = 255;
5096+
5097+      *(image++) = r;
5098+      *(image++) = g;
5099+      *(image++) = b;
5100+
5101+      yimg++;
5102+      uimg++;
5103+      vimg++;
5104+
5105+    }
5106+  }
5107+}
5108+
5109+void ImageUtils::yvu2bgr(ImageType out, ImageType in, int width, int height)
5110+{
5111+  int y,v,u, r, g, b;
5112+  unsigned char *yimg = in;
5113+  unsigned char *vimg = yimg + width*height;
5114+  unsigned char *uimg = vimg + width*height;
5115+  unsigned char *image = out;
5116+
5117+  for (int i = 0; i < height; i++) {
5118+    for (int j = 0; j < width; j++) {
5119+
5120+      y = (*yimg);
5121+      v = (*vimg);
5122+      u = (*uimg);
5123+
5124+      if (y < 0) y = 0;
5125+      if (y > 255) y = 255;
5126+      if (u < 0) u = 0;
5127+      if (u > 255) u = 255;
5128+      if (v < 0) v = 0;
5129+      if (v > 255) v = 255;
5130+
5131+      b = (int) ( 1.164*(y - 16) + 2.018*(u-128));
5132+      g = (int) ( 1.164*(y - 16) - 0.813*(v-128) - 0.391*(u-128));
5133+      r = (int) ( 1.164*(y - 16) + 1.596*(v-128));
5134+
5135+      if (r < 0) r = 0;
5136+      if (r > 255) r = 255;
5137+      if (g < 0) g = 0;
5138+      if (g > 255) g = 255;
5139+      if (b < 0) b = 0;
5140+      if (b > 255) b = 255;
5141+
5142+      *(image++) = b;
5143+      *(image++) = g;
5144+      *(image++) = r;
5145+
5146+      yimg++;
5147+      uimg++;
5148+      vimg++;
5149+
5150+    }
5151+  }
5152+}
5153+
5154+
5155+ImageType ImageUtils::readBinaryPPM(const char *filename, int &width, int &height)
5156+{
5157+
5158+  FILE *imgin = NULL;
5159+  int mval=0, format=0, eret;
5160+  ImageType ret = NULL;//IMAGE_TYPE_NOIMAGE;
5161+
5162+  imgin = fopen(filename, "r");
5163+  if (imgin == NULL) {
5164+    fprintf(stderr, "Error: Filename %s not found\n", filename);
5165+    return ret;
5166+  }
5167+
5168+  eret = fscanf(imgin, "P%d\n", &format);
5169+  if (format != 6) {
5170+    fprintf(stderr, "Error: readBinaryPPM only supports PPM format (P6)\n");
5171+    return ret;
5172+  }
5173+
5174+  eret = fscanf(imgin, "%d %d\n", &width, &height);
5175+  eret = fscanf(imgin, "%d\n", &mval);
5176+  ret  = allocateImage(width, height, IMAGE_TYPE_NUM_CHANNELS);
5177+  eret = fread(ret, sizeof(ImageTypeBase), IMAGE_TYPE_NUM_CHANNELS*width*height, imgin);
5178+
5179+  fclose(imgin);
5180+
5181+  return ret;
5182+
5183+}
5184+
5185+void ImageUtils::writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels)
5186+{
5187+  FILE *imgout = fopen(filename, "w");
5188+
5189+  if (imgout == NULL) {
5190+    fprintf(stderr, "Error: Filename %s could not be opened for writing\n", filename);
5191+    return;
5192+  }
5193+
5194+  if (numChannels == 3) {
5195+    fprintf(imgout, "P6\n%d %d\n255\n", width, height);
5196+  } else if (numChannels == 1) {
5197+    fprintf(imgout, "P5\n%d %d\n255\n", width, height);
5198+  } else {
5199+    fprintf(stderr, "Error: writeBinaryPPM: Unsupported number of channels\n");
5200+  }
5201+  fwrite(image, sizeof(ImageTypeBase), numChannels*width*height, imgout);
5202+
5203+  fclose(imgout);
5204+
5205+}
5206+
5207+ImageType ImageUtils::allocateImage(int width, int height, int numChannels, short int border)
5208+{
5209+  int overallocation = 256;
5210+ return (ImageType) calloc(width*height*numChannels+overallocation, sizeof(ImageTypeBase));
5211+}
5212+
5213+
5214+void ImageUtils::freeImage(ImageType image)
5215+{
5216+  free(image);
5217+}
5218+
5219+
5220+// allocation of one color image used for tmp buffers, etc.
5221+// format of contiguous memory block:
5222+//    YUVInfo struct (type + BimageInfo for Y,U, and V),
5223+//    Y row pointers
5224+//    U row pointers
5225+//    V row pointers
5226+//    Y image pixels
5227+//    U image pixels
5228+//    V image pixels
5229+YUVinfo *YUVinfo::allocateImage(unsigned short width, unsigned short height)
5230+{
5231+    unsigned short heightUV, widthUV;
5232+
5233+    widthUV = width;
5234+    heightUV = height;
5235+
5236+    // figure out how much space to hold all pixels...
5237+    int size = ((width * height * 3) + 8);
5238+    unsigned char *position = 0;
5239+
5240+    // VC 8 does not like calling free on yuv->Y.ptr since it is in
5241+    // the middle of a block.  So rearrange the memory layout so after
5242+    // calling mapYUVInforToImage yuv->Y.ptr points to the begginning
5243+    // of the calloc'ed block.
5244+    YUVinfo *yuv = (YUVinfo *) calloc(sizeof(YUVinfo), 1);
5245+    if (yuv) {
5246+        yuv->Y.width  = yuv->Y.pitch = width;
5247+        yuv->Y.height = height;
5248+        yuv->Y.border = yuv->U.border = yuv->V.border = (unsigned short) 0;
5249+        yuv->U.width  = yuv->U.pitch = yuv->V.width = yuv->V.pitch = widthUV;
5250+        yuv->U.height = yuv->V.height = heightUV;
5251+
5252+        unsigned char* block = (unsigned char*) calloc(
5253+                sizeof(unsigned char *) * (height + heightUV + heightUV) +
5254+                sizeof(unsigned char) * size, 1);
5255+
5256+        position = block;
5257+        unsigned char **y = (unsigned char **) (block + size);
5258+
5259+        /* Initialize and assign row pointers */
5260+        yuv->Y.ptr = y;
5261+        yuv->V.ptr = &y[height];
5262+        yuv->U.ptr = &y[height + heightUV];
5263+    }
5264+    if (size)
5265+        mapYUVInfoToImage(yuv, position);
5266+    return yuv;
5267+}
5268+
5269+// wrap YUVInfo row pointers around 3 contiguous image (color component) planes.
5270+// position = starting pixel in image.
5271+void YUVinfo::mapYUVInfoToImage(YUVinfo *img, unsigned char *position)
5272+{
5273+    int i;
5274+    for (i = 0; i < img->Y.height; i++, position += img->Y.width)
5275+        img->Y.ptr[i] = position;
5276+    for (i = 0; i < img->V.height; i++, position += img->V.width)
5277+        img->V.ptr[i] = position;
5278+    for (i = 0; i < img->U.height; i++, position += img->U.width)
5279+        img->U.ptr[i] = position;
5280+}
5281+
5282+
5283diff --git a/benchmark/feature_mos/src/mosaic/ImageUtils.h b/benchmark/feature_mos/src/mosaic/ImageUtils.h
5284new file mode 100644
5285index 00000000..92965ca8
5286--- /dev/null
5287+++ b/benchmark/feature_mos/src/mosaic/ImageUtils.h
5288@@ -0,0 +1,173 @@
5289+/*
5290+ * Copyright (C) 2011 The Android Open Source Project
5291+ *
5292+ * Licensed under the Apache License, Version 2.0 (the "License");
5293+ * you may not use this file except in compliance with the License.
5294+ * You may obtain a copy of the License at
5295+ *
5296+ *      http://www.apache.org/licenses/LICENSE-2.0
5297+ *
5298+ * Unless required by applicable law or agreed to in writing, software
5299+ * distributed under the License is distributed on an "AS IS" BASIS,
5300+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5301+ * See the License for the specific language governing permissions and
5302+ * limitations under the License.
5303+ */
5304+
5305+///////////////////////////////////////////////////
5306+// ImageUtils.h
5307+// $Id: ImageUtils.h,v 1.9 2011/05/16 15:33:06 mbansal Exp $
5308+
5309+#ifndef IMAGE_UTILS_H
5310+#define IMAGE_UTILS_H
5311+
5312+#include <stdlib.h>
5313+
5314+/**
5315+ *  Definition of basic image types
5316+ */
5317+typedef unsigned char ImageTypeBase;
5318+typedef ImageTypeBase *ImageType;
5319+
5320+typedef short ImageTypeShortBase;
5321+typedef ImageTypeShortBase *ImageTypeShort;
5322+
5323+typedef float ImageTypeFloatBase;
5324+typedef ImageTypeFloatBase *ImageTypeFloat;
5325+
5326+
5327+class ImageUtils {
5328+public:
5329+
5330+  /**
5331+   *  Default number of channels in image.
5332+   */
5333+  static const int IMAGE_TYPE_NUM_CHANNELS = 3;
5334+
5335+  /**
5336+   *  Definition of an empty image.
5337+   */
5338+  static const int IMAGE_TYPE_NOIMAGE = 0;
5339+
5340+  /**
5341+   *  Convert image from BGR (interlaced) to YVU (non-interlaced)
5342+   *
5343+   *  Arguments:
5344+   *    out: Resulting image (note must be preallocated before
5345+   *    call)
5346+   *    in: Input image
5347+   *    width: Width of input image
5348+   *    height: Height of input image
5349+   */
5350+  static void rgb2yvu(ImageType out, ImageType in, int width, int height);
5351+
5352+  static void rgba2yvu(ImageType out, ImageType in, int width, int height);
5353+
5354+  /**
5355+   *  Convert image from YVU (non-interlaced) to BGR (interlaced)
5356+   *
5357+   *  Arguments:
5358+   *    out: Resulting image (note must be preallocated before
5359+   *    call)
5360+   *    in: Input image
5361+   *    width: Width of input image
5362+   *    height: Height of input image
5363+   */
5364+  static void yvu2rgb(ImageType out, ImageType in, int width, int height);
5365+  static void yvu2bgr(ImageType out, ImageType in, int width, int height);
5366+
5367+  /**
5368+   *  Convert image from BGR to grayscale
5369+   *
5370+   *  Arguments:
5371+   *    in: Input image
5372+   *    width: Width of input image
5373+   *    height: Height of input image
5374+   *
5375+   *  Return:
5376+   *    Pointer to resulting image (allocation is done here, free
5377+   *    must be done by caller)
5378+   */
5379+  static ImageType rgb2gray(ImageType in, int width, int height);
5380+  static ImageType rgb2gray(ImageType out, ImageType in, int width, int height);
5381+
5382+  /**
5383+   *  Read a binary PPM image
5384+   */
5385+  static ImageType readBinaryPPM(const char *filename, int &width, int &height);
5386+
5387+  /**
5388+   *  Write a binary PPM image
5389+   */
5390+  static void writeBinaryPPM(ImageType image, const char *filename, int width, int height, int numChannels = IMAGE_TYPE_NUM_CHANNELS);
5391+
5392+  /**
5393+   *  Allocate space for a standard image.
5394+   */
5395+  static ImageType allocateImage(int width, int height, int numChannels, short int border = 0);
5396+
5397+  /**
5398+   *  Free memory of image
5399+   */
5400+  static void freeImage(ImageType image);
5401+
5402+  static ImageType *imageTypeToRowPointers(ImageType out, int width, int height);
5403+  /**
5404+   *  Get time.
5405+   */
5406+  static double getTime();
5407+
5408+protected:
5409+
5410+  /**
5411+  *  Constants for YVU/RGB conversion
5412+  */
5413+  static const int REDY = 257;
5414+  static const int REDV = 439;
5415+  static const int REDU = 148;
5416+  static const int GREENY = 504;
5417+  static const int GREENV = 368;
5418+  static const int GREENU = 291;
5419+  static const int BLUEY = 98;
5420+  static const int BLUEV = 71;
5421+  static const int BLUEU = 439;
5422+
5423+};
5424+
5425+/**
5426+ * Structure containing an image and other bookkeeping items.
5427+ * Used in YUVinfo to store separate YVU image planes.
5428+ */
5429+typedef struct {
5430+  ImageType *ptr;
5431+  unsigned short width;
5432+  unsigned short height;
5433+  unsigned short border;
5434+  unsigned short pitch;
5435+} BimageInfo;
5436+
5437+/**
5438+ * A YUV image container,
5439+ */
5440+class YUVinfo {
5441+public:
5442+  static YUVinfo *allocateImage(unsigned short width, unsigned short height);
5443+  static void mapYUVInfoToImage(YUVinfo *img, unsigned char *position);
5444+
5445+  /**
5446+  * Y Plane
5447+  */
5448+  BimageInfo Y;
5449+
5450+  /**
5451+  *  V (1st color) plane
5452+  */
5453+  BimageInfo V;
5454+
5455+  /**
5456+  *  U (1st color) plane
5457+  */
5458+  BimageInfo U;
5459+};
5460+
5461+#endif
5462diff --git a/benchmark/feature_mos/src/mosaic/Interp.h b/benchmark/feature_mos/src/mosaic/Interp.h
5463new file mode 100644
5464index 00000000..19c4a40c
5465--- /dev/null
5466+++ b/benchmark/feature_mos/src/mosaic/Interp.h
5467@@ -0,0 +1,80 @@
5468+/*
5469+ * Copyright (C) 2011 The Android Open Source Project
5470+ *
5471+ * Licensed under the Apache License, Version 2.0 (the "License");
5472+ * you may not use this file except in compliance with the License.
5473+ * You may obtain a copy of the License at
5474+ *
5475+ *      http://www.apache.org/licenses/LICENSE-2.0
5476+ *
5477+ * Unless required by applicable law or agreed to in writing, software
5478+ * distributed under the License is distributed on an "AS IS" BASIS,
5479+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5480+ * See the License for the specific language governing permissions and
5481+ * limitations under the License.
5482+ */
5483+
5484+///////////////////////////////////////////////////////////
5485+// Interp.h
5486+// $Id: Interp.h,v 1.2 2011/06/17 13:35:48 mbansal Exp $
5487+
5488+#ifndef INTERP_H
5489+#define INTERP_H
5490+
5491+#include "Pyramid.h"
5492+
5493+#define CTAPS 40
5494+static double ciTable[81] = {
5495+        1, 0.998461, 0.993938, 0.98657, 0.9765,
5496+        0.963867, 0.948813, 0.931477, 0.912, 0.890523,
5497+        0.867188, 0.842133, 0.8155, 0.78743, 0.758062,
5498+        0.727539, 0.696, 0.663586, 0.630437, 0.596695,
5499+        0.5625, 0.527992, 0.493312, 0.458602, 0.424,
5500+        0.389648, 0.355687, 0.322258, 0.2895, 0.257555,
5501+        0.226562, 0.196664, 0.168, 0.140711, 0.114937,
5502+        0.0908203, 0.0685, 0.0481172, 0.0298125, 0.0137266,
5503+        0, -0.0118828, -0.0225625, -0.0320859, -0.0405,
5504+        -0.0478516, -0.0541875, -0.0595547, -0.064, -0.0675703,
5505+        -0.0703125, -0.0722734, -0.0735, -0.0740391, -0.0739375,
5506+        -0.0732422, -0.072, -0.0702578, -0.0680625, -0.0654609,
5507+        -0.0625, -0.0592266, -0.0556875, -0.0519297, -0.048,
5508+        -0.0439453, -0.0398125, -0.0356484, -0.0315, -0.0274141,
5509+        -0.0234375, -0.0196172, -0.016, -0.0126328, -0.0095625,
5510+        -0.00683594, -0.0045, -0.00260156, -0.0011875, -0.000304687, 0.0
5511+};
5512+
5513+inline double ciCalc(PyramidShort *img, int xi, int yi, double xfrac, double yfrac)
5514+{
5515+  double tmpf[4];
5516+
5517+  // Interpolate using 16 points
5518+  ImageTypeShortBase *in = img->ptr[yi-1] + xi - 1;
5519+  int off = (int)(xfrac * CTAPS);
5520+
5521+  tmpf[0] = in[0] * ciTable[off + 40];
5522+  tmpf[0] += in[1] * ciTable[off];
5523+  tmpf[0] += in[2] * ciTable[40 - off];
5524+  tmpf[0] += in[3] * ciTable[80 - off];
5525+  in += img->pitch;
5526+  tmpf[1] = in[0] * ciTable[off + 40];
5527+  tmpf[1] += in[1] * ciTable[off];
5528+  tmpf[1] += in[2] * ciTable[40 - off];
5529+  tmpf[1] += in[3] * ciTable[80 - off];
5530+  in += img->pitch;
5531+  tmpf[2] = in[0] * ciTable[off + 40];
5532+  tmpf[2] += in[1] * ciTable[off];
5533+  tmpf[2] += in[2] * ciTable[40 - off];
5534+  tmpf[2] += in[3] * ciTable[80 - off];
5535+  in += img->pitch;
5536+  tmpf[3] = in[0] * ciTable[off + 40];
5537+  tmpf[3] += in[1] * ciTable[off];
5538+  tmpf[3] += in[2] * ciTable[40 - off];
5539+  tmpf[3] += in[3] * ciTable[80 - off];
5540+
5541+  // this is the final interpolation
5542+  off = (int)(yfrac * CTAPS);
5543+  return (ciTable[off + 40] * tmpf[0] + ciTable[off] * tmpf[1] +
5544+          ciTable[40 - off] * tmpf[2] + ciTable[80 - off] * tmpf[3]);
5545+}
5546+
5547+#endif
5548diff --git a/benchmark/feature_mos/src/mosaic/Log.h b/benchmark/feature_mos/src/mosaic/Log.h
5549new file mode 100644
5550index 00000000..2adfeda9
5551--- /dev/null
5552+++ b/benchmark/feature_mos/src/mosaic/Log.h
5553@@ -0,0 +1,24 @@
5554+/*
5555+ * Copyright (C) 2011 The Android Open Source Project
5556+ *
5557+ * Licensed under the Apache License, Version 2.0 (the "License");
5558+ * you may not use this file except in compliance with the License.
5559+ * You may obtain a copy of the License at
5560+ *
5561+ *      http://www.apache.org/licenses/LICENSE-2.0
5562+ *
5563+ * Unless required by applicable law or agreed to in writing, software
5564+ * distributed under the License is distributed on an "AS IS" BASIS,
5565+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5566+ * See the License for the specific language governing permissions and
5567+ * limitations under the License.
5568+ */
5569+#ifndef LOG_H_
5570+#define LOG_H_
5571+
5572+#include <android/log.h>
5573+#define LOGV(...) __android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__)
5574+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
5575+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
5576+
5577+#endif
5578diff --git a/benchmark/feature_mos/src/mosaic/MatrixUtils.h b/benchmark/feature_mos/src/mosaic/MatrixUtils.h
5579new file mode 100644
5580index 00000000..a0b84d81
5581--- /dev/null
5582+++ b/benchmark/feature_mos/src/mosaic/MatrixUtils.h
5583@@ -0,0 +1,141 @@
5584+/*
5585+ * Copyright (C) 2011 The Android Open Source Project
5586+ *
5587+ * Licensed under the Apache License, Version 2.0 (the "License");
5588+ * you may not use this file except in compliance with the License.
5589+ * You may obtain a copy of the License at
5590+ *
5591+ *      http://www.apache.org/licenses/LICENSE-2.0
5592+ *
5593+ * Unless required by applicable law or agreed to in writing, software
5594+ * distributed under the License is distributed on an "AS IS" BASIS,
5595+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5596+ * See the License for the specific language governing permissions and
5597+ * limitations under the License.
5598+ */
5599+
5600+///////////////////////////////////////////////////
5601+// Matrixutils.h
5602+// $Id: MatrixUtils.h,v 1.5 2011/05/16 15:33:06 mbansal Exp $
5603+
5604+
5605+#ifndef MATRIX_UTILS_H
5606+#define MATRIX_UTILS_H
5607+
5608+/* Simple class for 3x3 matrix, mainly used to convert from 9x1
5609+ * to 3x3
5610+ */
5611+class Matrix33 {
5612+public:
5613+
5614+  /**
5615+   *  Empty constructor
5616+   */
5617+  Matrix33() {
5618+    initialize();
5619+  }
5620+
5621+  /**
5622+   *  Constructor with identity initialization
5623+   *  Arguments:
5624+   *     identity: Specifies wether to initialize matrix to
5625+   *     identity or zeros
5626+   */
5627+  Matrix33(bool identity) {
5628+    initialize(identity);
5629+  }
5630+
5631+  /**
5632+   *  Initialize to identity matrix
5633+   */
5634+  void initialize(bool identity = false) {
5635+    mat[0][1] = mat[0][2] = mat[1][0] = mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
5636+    if (identity) {
5637+      mat[0][0] = mat[1][1] = mat[2][2] = 1.0;
5638+    } else {
5639+      mat[0][0] = mat[1][1] = mat[2][2] = 0.0;
5640+    }
5641+  }
5642+
5643+  /**
5644+   *  Conver ta 9x1 matrix to a 3x3 matrix
5645+   */
5646+  static void convert9to33(double out[3][3], double in[9]) {
5647+    out[0][0] = in[0];
5648+    out[0][1] = in[1];
5649+    out[0][2] = in[2];
5650+
5651+    out[1][0] = in[3];
5652+    out[1][1] = in[4];
5653+    out[1][2] = in[5];
5654+
5655+    out[2][0] = in[6];
5656+    out[2][1] = in[7];
5657+    out[2][2] = in[8];
5658+
5659+  }
5660+
5661+  /* Matrix data */
5662+  double mat[3][3];
5663+
5664+};
5665+
5666+/* Simple class for 9x1 matrix, mainly used to convert from 3x3
5667+ * to 9x1
5668+ */
5669+class Matrix9 {
5670+public:
5671+
5672+  /**
5673+   *  Empty constructor
5674+   */
5675+  Matrix9() {
5676+    initialize();
5677+  }
5678+
5679+  /**
5680+   *  Constructor with identity initialization
5681+   *  Arguments:
5682+   *     identity: Specifies wether to initialize matrix to
5683+   *     identity or zeros
5684+   */
5685+  Matrix9(bool identity) {
5686+    initialize(identity);
5687+  }
5688+
5689+  /**
5690+   *  Initialize to identity matrix
5691+   */
5692+  void initialize(bool identity = false) {
5693+    mat[1] = mat[2] = mat[3] = mat[5] = mat[6] = mat[7] = 0.0;
5694+    if (identity) {
5695+      mat[0] = mat[4] = mat[8] = 1.0;
5696+    } else {
5697+      mat[0] = mat[4] = mat[8] = 0.0;
5698+    }
5699+  }
5700+
5701+  /**
5702+   *  Conver ta 3x3 matrix to a 9x1 matrix
5703+   */
5704+  static void convert33to9(double out[9], double in[3][3]) {
5705+    out[0] = in[0][0];
5706+    out[1] = in[0][1];
5707+    out[2] = in[0][2];
5708+
5709+    out[3] = in[1][0];
5710+    out[4] = in[1][1];
5711+    out[5] = in[1][2];
5712+
5713+    out[6] = in[2][0];
5714+    out[7] = in[2][1];
5715+    out[8] = in[2][2];
5716+
5717+  }
5718+
5719+  /* Matrix data */
5720+  double mat[9];
5721+
5722+};
5723+
5724+#endif
5725diff --git a/benchmark/feature_mos/src/mosaic/Mosaic.cpp b/benchmark/feature_mos/src/mosaic/Mosaic.cpp
5726new file mode 100644
5727index 00000000..4abc6f68
5728--- /dev/null
5729+++ b/benchmark/feature_mos/src/mosaic/Mosaic.cpp
5730@@ -0,0 +1,255 @@
5731+/*
5732+ * Copyright (C) 2011 The Android Open Source Project
5733+ *
5734+ * Licensed under the Apache License, Version 2.0 (the "License");
5735+ * you may not use this file except in compliance with the License.
5736+ * You may obtain a copy of the License at
5737+ *
5738+ *      http://www.apache.org/licenses/LICENSE-2.0
5739+ *
5740+ * Unless required by applicable law or agreed to in writing, software
5741+ * distributed under the License is distributed on an "AS IS" BASIS,
5742+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5743+ * See the License for the specific language governing permissions and
5744+ * limitations under the License.
5745+ */
5746+
5747+///////////////////////////////////////////////////
5748+// Mosaic.pp
5749+// S.O. # :
5750+// Author(s): zkira
5751+// $Id: Mosaic.cpp,v 1.20 2011/06/24 04:22:14 mbansal Exp $
5752+
5753+#include <stdio.h>
5754+#include <string.h>
5755+
5756+#include "Mosaic.h"
5757+#include "trsMatrix.h"
5758+
5759+Mosaic::Mosaic()
5760+{
5761+    initialized = false;
5762+    imageMosaicYVU = NULL;
5763+    frames_size = 0;
5764+    max_frames = 200;
5765+}
5766+
5767+Mosaic::~Mosaic()
5768+{
5769+    for (int i = 0; i < frames_size; i++)
5770+    {
5771+        if (frames[i])
5772+            delete frames[i];
5773+    }
5774+    delete frames;
5775+    delete rframes;
5776+
5777+    for (int j = 0; j < owned_size; j++)
5778+        delete owned_frames[j];
5779+    delete owned_frames;
5780+
5781+    if (aligner != NULL)
5782+        delete aligner;
5783+    if (blender != NULL)
5784+        delete blender;
5785+}
5786+
5787+int Mosaic::initialize(int blendingType, int stripType, int width, int height, int nframes, bool quarter_res, float thresh_still)
5788+{
5789+    this->blendingType = blendingType;
5790+
5791+    // TODO: Review this logic if enabling FULL or PAN mode
5792+    if (blendingType == Blend::BLEND_TYPE_FULL ||
5793+            blendingType == Blend::BLEND_TYPE_PAN)
5794+    {
5795+        stripType = Blend::STRIP_TYPE_THIN;
5796+    }
5797+
5798+    this->stripType = stripType;
5799+    this->width = width;
5800+    this->height = height;
5801+
5802+
5803+    mosaicWidth = mosaicHeight = 0;
5804+    imageMosaicYVU = NULL;
5805+
5806+    frames = new MosaicFrame *[max_frames];
5807+    rframes = new MosaicFrame *[max_frames];
5808+
5809+    if(nframes>-1)
5810+    {
5811+        for(int i=0; i<nframes; i++)
5812+        {
5813+            frames[i] = new MosaicFrame(this->width,this->height,false); // Do no allocate memory for YUV data
5814+        }
5815+    }
5816+    else
5817+    {
5818+        for(int i=0; i<max_frames; i++)
5819+        {
5820+            frames[i] = NULL;
5821+        }
5822+    }
5823+
5824+    owned_frames = new ImageType[max_frames];
5825+    owned_size = 0;
5826+
5827+    aligner = new Align();
5828+    aligner->initialize(width, height,quarter_res,thresh_still);
5829+
5830+    if (blendingType == Blend::BLEND_TYPE_FULL ||
5831+            blendingType == Blend::BLEND_TYPE_PAN ||
5832+            blendingType == Blend::BLEND_TYPE_CYLPAN ||
5833+            blendingType == Blend::BLEND_TYPE_HORZ) {
5834+        blender = new Blend();
5835+        blender->initialize(blendingType, stripType, width, height);
5836+    } else {
5837+        blender = NULL;
5838+        return MOSAIC_RET_ERROR;
5839+    }
5840+
5841+    initialized = true;
5842+
5843+    return MOSAIC_RET_OK;
5844+}
5845+
5846+int Mosaic::addFrameRGB(ImageType imageRGB)
5847+{
5848+    ImageType imageYVU;
5849+    // Convert to YVU24 which is used by blending
5850+    imageYVU = ImageUtils::allocateImage(this->width, this->height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
5851+    ImageUtils::rgb2yvu(imageYVU, imageRGB, width, height);
5852+
5853+    int existing_frames_size = frames_size;
5854+    int ret = addFrame(imageYVU);
5855+
5856+    if (frames_size > existing_frames_size)
5857+        owned_frames[owned_size++] = imageYVU;
5858+    else
5859+        ImageUtils::freeImage(imageYVU);
5860+
5861+    return ret;
5862+}
5863+
5864+int Mosaic::addFrame(ImageType imageYVU)
5865+{
5866+    if(frames[frames_size]==NULL)
5867+        frames[frames_size] = new MosaicFrame(this->width,this->height,false);
5868+
5869+    MosaicFrame *frame = frames[frames_size];
5870+
5871+    frame->image = imageYVU;
5872+
5873+    // Add frame to aligner
5874+    int ret = MOSAIC_RET_ERROR;
5875+    if (aligner != NULL)
5876+    {
5877+        // Note aligner takes in RGB images
5878+        int align_flag = Align::ALIGN_RET_OK;
5879+        align_flag = aligner->addFrame(frame->image);
5880+        aligner->getLastTRS(frame->trs);
5881+
5882+        if (frames_size >= max_frames)
5883+        {
5884+            return MOSAIC_RET_ERROR;
5885+        }
5886+
5887+        switch (align_flag)
5888+        {
5889+            case Align::ALIGN_RET_OK:
5890+                frames_size++;
5891+                ret = MOSAIC_RET_OK;
5892+                break;
5893+            case Align::ALIGN_RET_FEW_INLIERS:
5894+                frames_size++;
5895+                ret = MOSAIC_RET_FEW_INLIERS;
5896+                break;
5897+            case Align::ALIGN_RET_LOW_TEXTURE:
5898+                ret = MOSAIC_RET_LOW_TEXTURE;
5899+                break;
5900+            case Align::ALIGN_RET_ERROR:
5901+                ret = MOSAIC_RET_ERROR;
5902+                break;
5903+            default:
5904+                break;
5905+        }
5906+    }
5907+
5908+    return ret;
5909+}
5910+
5911+
5912+int Mosaic::createMosaic(float &progress, bool &cancelComputation)
5913+{
5914+    if (frames_size <= 0)
5915+    {
5916+        // Haven't accepted any frame in aligner. No need to do blending.
5917+        progress = TIME_PERCENT_ALIGN + TIME_PERCENT_BLEND
5918+                + TIME_PERCENT_FINAL;
5919+        return MOSAIC_RET_OK;
5920+    }
5921+
5922+    if (blendingType == Blend::BLEND_TYPE_PAN)
5923+    {
5924+
5925+        balanceRotations();
5926+
5927+    }
5928+
5929+    int ret = Blend::BLEND_RET_ERROR;
5930+
5931+    // Blend the mosaic (alignment has already been done)
5932+    if (blender != NULL)
5933+    {
5934+        ret = blender->runBlend((MosaicFrame **) frames, (MosaicFrame **) rframes,
5935+                frames_size, imageMosaicYVU,
5936+                mosaicWidth, mosaicHeight, progress, cancelComputation);
5937+    }
5938+
5939+    switch(ret)
5940+    {
5941+        case Blend::BLEND_RET_ERROR:
5942+        case Blend::BLEND_RET_ERROR_MEMORY:
5943+            ret = MOSAIC_RET_ERROR;
5944+            break;
5945+        case Blend::BLEND_RET_CANCELLED:
5946+            ret = MOSAIC_RET_CANCELLED;
5947+            break;
5948+        case Blend::BLEND_RET_OK:
5949+            ret = MOSAIC_RET_OK;
5950+    }
5951+    return ret;
5952+}
5953+
5954+ImageType Mosaic::getMosaic(int &width, int &height)
5955+{
5956+    width = mosaicWidth;
5957+    height = mosaicHeight;
5958+
5959+    return imageMosaicYVU;
5960+}
5961+
5962+
5963+
5964+int Mosaic::balanceRotations()
5965+{
5966+    // Normalize to the mean angle of rotation (Smiley face)
5967+    double sineAngle = 0.0;
5968+
5969+    for (int i = 0; i < frames_size; i++) sineAngle += frames[i]->trs[0][1];
5970+    sineAngle /= frames_size;
5971+    // Calculate the cosineAngle (1 - sineAngle*sineAngle) = cosineAngle*cosineAngle
5972+    double cosineAngle = sqrt(1.0 - sineAngle*sineAngle);
5973+    double m[3][3] = {
5974+        { cosineAngle, -sineAngle, 0 },
5975+        { sineAngle, cosineAngle, 0},
5976+        { 0, 0, 1}};
5977+    double tmp[3][3];
5978+
5979+    for (int i = 0; i < frames_size; i++) {
5980+        memcpy(tmp, frames[i]->trs, sizeof(tmp));
5981+        mult33d(frames[i]->trs, m, tmp);
5982+    }
5983+
5984+    return MOSAIC_RET_OK;
5985+}
5986diff --git a/benchmark/feature_mos/src/mosaic/Mosaic.h b/benchmark/feature_mos/src/mosaic/Mosaic.h
5987new file mode 100644
5988index 00000000..9dea6642
5989--- /dev/null
5990+++ b/benchmark/feature_mos/src/mosaic/Mosaic.h
5991@@ -0,0 +1,226 @@
5992+/*
5993+ * Copyright (C) 2011 The Android Open Source Project
5994+ *
5995+ * Licensed under the Apache License, Version 2.0 (the "License");
5996+ * you may not use this file except in compliance with the License.
5997+ * You may obtain a copy of the License at
5998+ *
5999+ *      http://www.apache.org/licenses/LICENSE-2.0
6000+ *
6001+ * Unless required by applicable law or agreed to in writing, software
6002+ * distributed under the License is distributed on an "AS IS" BASIS,
6003+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6004+ * See the License for the specific language governing permissions and
6005+ * limitations under the License.
6006+ */
6007+
6008+///////////////////////////////////////////////////
6009+// Mosaic.h
6010+// S.O. # :
6011+// Author(s): zkira
6012+// $Id: Mosaic.h,v 1.16 2011/06/24 04:22:14 mbansal Exp $
6013+
6014+#ifndef MOSAIC_H
6015+#define MOSAIC_H
6016+
6017+#include "ImageUtils.h"
6018+#include "AlignFeatures.h"
6019+#include "Blend.h"
6020+#include "MosaicTypes.h"
6021+
6022+/*! \mainpage Mosaic
6023+
6024+    \section intro Introduction
6025+    The class Mosaic provides a simple interface to the panoramic mosaicing algorithm. The class allows passing in individual image frames to be stitched together, computes the alignment transformation between them, and then stitches and blends them together into a single panoramic output which can then be accessed as a single image. \
6026+
6027+    \section usage Usage
6028+    The class methods need to be called as outlined in the sample application which is created from the mosaic_main.cpp file in the directory src/mosaic/. A brief snapshot of the flow is given below:
6029+
6030+    \code
6031+    Mosaic mosaic;
6032+    // Define blending types to use, and the frame dimensions
6033+    int blendingType = Blend::BLEND_TYPE_CYLPAN;
6034+    int stripType = Blend::STRIP_TYPE_THIN;
6035+    int width = 640;
6036+    int height = 480;
6037+
6038+    while (<image frames are available>)
6039+    {
6040+        // Check for initialization and if not, initialize
6041+        if (!mosaic.isInitialized())
6042+        {
6043+          // Initialize mosaic processing
6044+          mosaic.initialize(blendingType, stripType, width, height, -1, false, 5.0f);
6045+        }
6046+
6047+        // Add to list of frames
6048+        mosaic.addFrameRGB(imageRGB);
6049+
6050+        // Free image
6051+        ImageUtils::freeImage(imageRGB);
6052+    }
6053+
6054+    // Create the mosaic
6055+    ret = mosaic.createMosaic();
6056+
6057+    // Get back the result
6058+    resultYVU = mosaic.getMosaic(mosaicWidth, mosaicHeight);
6059+
6060+    printf("Got mosaic of size %d,%d\n", mosaicWidth, mosaicHeight);
6061+
6062+    \endcode
6063+*/
6064+
6065+/*!
6066+ *  Main class that creates a mosaic by creating an aligner and blender.
6067+ */
6068+class Mosaic
6069+{
6070+
6071+public:
6072+
6073+  Mosaic();
6074+  ~Mosaic();
6075+
6076+   /*!
6077+    *   Creates the aligner and blender and initializes state.
6078+    *   \param blendingType Type of blending to perform
6079+    *   \param stripType    Type of strip to use. 0: thin, 1: wide. stripType
6080+    *                       is effective only when blendingType is CylPan or
6081+    *                       Horz. Otherwise, it is set to thin irrespective of the input.
6082+    *   \param width        Width of input images (note: all images must be same size)
6083+    *   \param height       Height of input images (note: all images must be same size)
6084+    *   \param nframes      Number of frames to pre-allocate; default value -1 will allocate each frame as it comes
6085+    *   \param quarter_res  Whether to compute alignment at quarter the input resolution (default = false)
6086+    *   \param thresh_still Minimum number of pixels of translation detected between the new frame and the last frame before this frame is added to be mosaiced. For the low-res processing at 320x180 resolution input, we set this to 5 pixels. To reject no frames, set this to 0.0 (default value).
6087+    *   \return             Return code signifying success or failure.
6088+    */
6089+  int initialize(int blendingType, int stripType, int width, int height, int nframes = -1, bool quarter_res = false, float thresh_still = 0.0);
6090+
6091+   /*!
6092+    *   Adds a YVU frame to the mosaic.
6093+    *   \param imageYVU     Pointer to a YVU image.
6094+    *   \return             Return code signifying success or failure.
6095+    */
6096+  int addFrame(ImageType imageYVU);
6097+
6098+   /*!
6099+    *   Adds a RGB frame to the mosaic.
6100+    *   \param imageRGB     Pointer to a RGB image.
6101+    *   \return             Return code signifying success or failure.
6102+    */
6103+  int addFrameRGB(ImageType imageRGB);
6104+
6105+   /*!
6106+    *   After adding all frames, call this function to perform the final blending.
6107+    *   \param progress     Variable to set the current progress in.
6108+    *   \return             Return code signifying success or failure.
6109+    */
6110+  int createMosaic(float &progress, bool &cancelComputation);
6111+
6112+    /*!
6113+    *   Obtains the resulting mosaic and its dimensions.
6114+    *   \param width        Width of the resulting mosaic (returned)
6115+    *   \param height       Height of the resulting mosaic (returned)
6116+    *   \return             Pointer to image.
6117+    */
6118+  ImageType getMosaic(int &width, int &height);
6119+
6120+    /*!
6121+    *   Provides access to the internal alignment object pointer.
6122+    *   \return             Pointer to the aligner object.
6123+    */
6124+  Align* getAligner() { return aligner; }
6125+
6126+    /*!
6127+    *   Obtain initialization state.
6128+    *
6129+    *   return              Returns true if initialized, false otherwise.
6130+    */
6131+  bool isInitialized() { return initialized; }
6132+
6133+
6134+  /*!
6135+   *  Return codes for mosaic.
6136+   */
6137+  static const int MOSAIC_RET_OK    = 1;
6138+  static const int MOSAIC_RET_ERROR = -1;
6139+  static const int MOSAIC_RET_CANCELLED = -2;
6140+  static const int MOSAIC_RET_LOW_TEXTURE = -3;
6141+  static const int MOSAIC_RET_FEW_INLIERS = 2;
6142+
6143+protected:
6144+
6145+  /**
6146+   * Size of image frames making up mosaic
6147+   */
6148+  int width, height;
6149+
6150+  /**
6151+   * Size of actual mosaic
6152+   */
6153+  int mosaicWidth, mosaicHeight;
6154+
6155+  /**
6156+   * Bounding box to crop the mosaic when the gray border is not desired.
6157+   */
6158+  MosaicRect mosaicCroppingRect;
6159+
6160+  ImageType imageMosaicYVU;
6161+
6162+  /**
6163+   * Collection of frames that will make up mosaic.
6164+   */
6165+  MosaicFrame **frames;
6166+
6167+  /**
6168+    * Subset of frames that are considered as relevant.
6169+    */
6170+  MosaicFrame **rframes;
6171+
6172+  int frames_size;
6173+  int max_frames;
6174+
6175+  /**
6176+    * Implicitly created frames, should be freed by Mosaic.
6177+    */
6178+  ImageType *owned_frames;
6179+  int owned_size;
6180+
6181+  /**
6182+   * Initialization state.
6183+   */
6184+  bool initialized;
6185+
6186+  /**
6187+   *  Type of blending to perform.
6188+   */
6189+  int blendingType;
6190+
6191+  /**
6192+    * Type of strip to use. 0: thin (default), 1: wide
6193+    */
6194+  int stripType;
6195+
6196+  /**
6197+   *  Pointer to aligner.
6198+   */
6199+  Align *aligner;
6200+
6201+  /**
6202+   *  Pointer to blender.
6203+   */
6204+  Blend *blender;
6205+
6206+  /**
6207+   *  Modifies TRS matrices so that rotations are balanced
6208+   *  about center of mosaic
6209+   *
6210+   * Side effect: TRS matrices of all mosaic frames
6211+   *              are modified
6212+   */
6213+  int balanceRotations();
6214+
6215+};
6216+
6217+#endif
6218diff --git a/benchmark/feature_mos/src/mosaic/MosaicTypes.h b/benchmark/feature_mos/src/mosaic/MosaicTypes.h
6219new file mode 100644
6220index 00000000..395ec458
6221--- /dev/null
6222+++ b/benchmark/feature_mos/src/mosaic/MosaicTypes.h
6223@@ -0,0 +1,154 @@
6224+/*
6225+ * Copyright (C) 2011 The Android Open Source Project
6226+ *
6227+ * Licensed under the Apache License, Version 2.0 (the "License");
6228+ * you may not use this file except in compliance with the License.
6229+ * You may obtain a copy of the License at
6230+ *
6231+ *      http://www.apache.org/licenses/LICENSE-2.0
6232+ *
6233+ * Unless required by applicable law or agreed to in writing, software
6234+ * distributed under the License is distributed on an "AS IS" BASIS,
6235+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6236+ * See the License for the specific language governing permissions and
6237+ * limitations under the License.
6238+ */
6239+
6240+///////////////////////////////////////////////////
6241+// MosaicTypes.h
6242+// S.O. # :
6243+// Author(s): zkira
6244+// $Id: MosaicTypes.h,v 1.15 2011/06/17 13:35:48 mbansal Exp $
6245+
6246+
6247+#ifndef MOSAIC_TYPES_H
6248+#define MOSAIC_TYPES_H
6249+
6250+#include "ImageUtils.h"
6251+
6252+/**
6253+ *  Definition of rectangle in a mosaic.
6254+ */
6255+class MosaicRect
6256+{
6257+    public:
6258+        MosaicRect()
6259+        {
6260+            left = right = top = bottom = 0.0;
6261+        }
6262+
6263+        inline int Width()
6264+        {
6265+            return right - left;
6266+        }
6267+
6268+        inline int Height()
6269+        {
6270+            return bottom - top;
6271+        }
6272+
6273+        /**
6274+         *  Bounds of the rectangle
6275+         */
6276+        int left, right, top, bottom;
6277+};
6278+
6279+class BlendRect
6280+{
6281+    public:
6282+    double lft, rgt, top, bot;
6283+};
6284+
6285+/**
6286+ *  A frame making up the mosaic.
6287+ *  Note: Currently assumes a YVU image
6288+ *  containing separate Y,V, and U planes
6289+ *  in contiguous memory (in that order).
6290+ */
6291+class MosaicFrame {
6292+public:
6293+  ImageType image;
6294+  double trs[3][3];
6295+  int width, height;
6296+  BlendRect brect;  // This frame warped to the Mosaic coordinate system
6297+  BlendRect vcrect; // brect clipped using the voronoi neighbors
6298+  bool internal_allocation;
6299+
6300+  MosaicFrame() { };
6301+  MosaicFrame(int _width, int _height, bool allocate=true)
6302+  {
6303+    width = _width;
6304+    height = _height;
6305+    internal_allocation = allocate;
6306+    if(internal_allocation)
6307+        image = ImageUtils::allocateImage(width, height, ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
6308+  }
6309+
6310+
6311+  ~MosaicFrame()
6312+  {
6313+    if(internal_allocation)
6314+        if (image)
6315+        free(image);
6316+  }
6317+
6318+  /**
6319+  *  Get the V plane of the image.
6320+  */
6321+  inline ImageType getV()
6322+  {
6323+    return (image + (width*height));
6324+  }
6325+
6326+  /**
6327+  *  Get the U plane of the image.
6328+  */
6329+  inline ImageType getU()
6330+  {
6331+    return (image + (width*height*2));
6332+  }
6333+
6334+  /**
6335+  *  Get a pixel from the V plane of the image.
6336+  */
6337+  inline int getV(int y, int x)
6338+  {
6339+    ImageType U = image + (width*height);
6340+    return U[y*width+x];
6341+  }
6342+
6343+  /**
6344+  *  Get a pixel from the U plane of the image.
6345+  */
6346+  inline int getU(int y, int x)
6347+  {
6348+    ImageType U = image + (width*height*2);
6349+    return U[y*width+x];
6350+  }
6351+
6352+};
6353+
6354+/**
6355+ *  Structure for describing a warp.
6356+ */
6357+typedef struct {
6358+  int horizontal;
6359+  double theta;
6360+  double x;
6361+  double y;
6362+  double width;
6363+  double radius;
6364+  double direction;
6365+  double correction;
6366+  int blendRange;
6367+  int blendRangeUV;
6368+  int nlevs;
6369+  int nlevsC;
6370+  int blendingType;
6371+  int stripType;
6372+  // Add an overlap to prevent a gap between pictures due to roundoffs
6373+  double roundoffOverlap;// 1.5
6374+
6375+} BlendParams;
6376+
6377+#endif
6378diff --git a/benchmark/feature_mos/src/mosaic/Pyramid.cpp b/benchmark/feature_mos/src/mosaic/Pyramid.cpp
6379new file mode 100644
6380index 00000000..b022d73d
6381--- /dev/null
6382+++ b/benchmark/feature_mos/src/mosaic/Pyramid.cpp
6383@@ -0,0 +1,270 @@
6384+/*
6385+ * Copyright (C) 2011 The Android Open Source Project
6386+ *
6387+ * Licensed under the Apache License, Version 2.0 (the "License");
6388+ * you may not use this file except in compliance with the License.
6389+ * You may obtain a copy of the License at
6390+ *
6391+ *      http://www.apache.org/licenses/LICENSE-2.0
6392+ *
6393+ * Unless required by applicable law or agreed to in writing, software
6394+ * distributed under the License is distributed on an "AS IS" BASIS,
6395+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6396+ * See the License for the specific language governing permissions and
6397+ * limitations under the License.
6398+ */
6399+
6400+// pyramid.cpp
6401+
6402+#include <stdio.h>
6403+#include <string.h>
6404+
6405+#include "Pyramid.h"
6406+
6407+// We allocate the entire pyramid into one contiguous storage. This makes
6408+// cleanup easier than fragmented stuff. In addition, we added a "pitch"
6409+// field, so pointer manipulation is much simpler when it would be faster.
6410+PyramidShort *PyramidShort::allocatePyramidPacked(real levels,
6411+        real width, real height, real border)
6412+{
6413+    real border2 = (real) (border << 1);
6414+    int lines, size = calcStorage(width, height, border2, levels, &lines);
6415+
6416+    PyramidShort *img = (PyramidShort *) calloc(sizeof(PyramidShort) * levels
6417+            + sizeof(short *) * lines +
6418+            + sizeof(short) * size, 1);
6419+
6420+    if (img) {
6421+        PyramidShort *curr, *last;
6422+        ImageTypeShort *y = (ImageTypeShort *) &img[levels];
6423+        ImageTypeShort position = (ImageTypeShort) &y[lines];
6424+        for (last = (curr = img) + levels; curr < last; curr++) {
6425+            curr->width = width;
6426+            curr->height = height;
6427+            curr->border = border;
6428+            curr->pitch = (real) (width + border2);
6429+            curr->ptr = y + border;
6430+
6431+            // Assign row pointers
6432+            for (int j = height + border2; j--; y++, position += curr->pitch) {
6433+                *y = position + border;
6434+            }
6435+
6436+            width >>= 1;
6437+            height >>= 1;
6438+        }
6439+    }
6440+
6441+    return img;
6442+}
6443+
6444+// Allocate an image of type short
6445+PyramidShort *PyramidShort::allocateImage(real width, real height, real border)
6446+{
6447+    real border2 = (real) (border << 1);
6448+    PyramidShort *img = (PyramidShort *)
6449+        calloc(sizeof(PyramidShort) + sizeof(short *) * (height + border2) +
6450+                sizeof(short) * (width + border2) * (height + border2), 1);
6451+
6452+    if (img) {
6453+        short **y = (short **) &img[1];
6454+        short *position = (short *) &y[height + border2];
6455+        img->width = width;
6456+        img->height = height;
6457+        img->border = border;
6458+        img->pitch = (real) (width + border2);
6459+        img->ptr = y + border;
6460+        position += border; // Move position down to origin of real image
6461+
6462+        // Assign row pointers
6463+        for (int j = height + border2; j--; y++, position += img->pitch) {
6464+            *y = position;
6465+        }
6466+    }
6467+
6468+    return img;
6469+}
6470+
6471+// Free the images
6472+void PyramidShort::freeImage(PyramidShort *image)
6473+{
6474+    if (image != NULL)
6475+        free(image);
6476+}
6477+
6478+// Calculate amount of storage needed taking into account the borders, etc.
6479+unsigned int PyramidShort::calcStorage(real width, real height, real border2,   int levels, int *lines)
6480+{
6481+    int size;
6482+
6483+    *lines = size = 0;
6484+
6485+    while(levels--) {
6486+        size += (width + border2) * (height + border2);
6487+        *lines += height + border2;
6488+        width >>= 1;
6489+        height >>= 1;
6490+    }
6491+
6492+    return size;
6493+}
6494+
6495+void PyramidShort::BorderSpread(PyramidShort *pyr, int left, int right,
6496+        int top, int bot)
6497+{
6498+    int off, off2, height, h, w;
6499+    ImageTypeShort base;
6500+
6501+    if (left || right) {
6502+        off = pyr->border - left;
6503+        off2 = pyr->width + off + pyr->border - right - 1;
6504+        h = pyr->border - top;
6505+        height = pyr->height + (h << 1);
6506+        base = pyr->ptr[-h] - off;
6507+
6508+        // spread in X
6509+        for (h = height; h--; base += pyr->pitch) {
6510+            for (w = left; w--;)
6511+                base[-1 - w] = base[0];
6512+            for (w = right; w--;)
6513+                base[off2 + w + 1] = base[off2];
6514+        }
6515+    }
6516+
6517+    if (top || bot) {
6518+        // spread in Y
6519+        base = pyr->ptr[top - pyr->border] - pyr->border;
6520+        for (h = top; h--; base -= pyr->pitch) {
6521+            memcpy(base - pyr->pitch, base, pyr->pitch * sizeof(short));
6522+        }
6523+
6524+        base = pyr->ptr[pyr->height + pyr->border - bot] - pyr->border;
6525+        for (h = bot; h--; base += pyr->pitch) {
6526+            memcpy(base, base - pyr->pitch, pyr->pitch * sizeof(short));
6527+        }
6528+    }
6529+}
6530+
6531+void PyramidShort::BorderExpandOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr,
6532+        int mode)
6533+{
6534+    int i,j;
6535+    int off = in->border / 2;
6536+
6537+    // Vertical Filter
6538+    for (j = -off; j < in->height + off; j++) {
6539+        int j2 = j * 2;
6540+        int limit = scr->width + scr->border;
6541+        for (i = -scr->border; i < limit; i++) {
6542+            int t1 = in->ptr[j][i];
6543+            int t2 = in->ptr[j+1][i];
6544+            scr->ptr[j2][i] = (short)
6545+                ((6 * t1 + (in->ptr[j-1][i] + t2) + 4) >> 3);
6546+            scr->ptr[j2+1][i] = (short)((t1 + t2 + 1) >> 1);
6547+        }
6548+    }
6549+
6550+    BorderSpread(scr, 0, 0, 3, 3);
6551+
6552+    // Horizontal Filter
6553+    int limit = out->height + out->border;
6554+    for (j = -out->border; j < limit; j++) {
6555+        for (i = -off; i < scr->width + off; i++) {
6556+            int i2 = i * 2;
6557+            int t1 = scr->ptr[j][i];
6558+            int t2 = scr->ptr[j][i+1];
6559+            out->ptr[j][i2] = (short) (out->ptr[j][i2] +
6560+                    (mode * ((6 * t1 +
6561+                              scr->ptr[j][i-1] + t2 + 4) >> 3)));
6562+            out->ptr[j][i2+1] = (short) (out->ptr[j][i2+1] +
6563+                    (mode * ((t1 + t2 + 1) >> 1)));
6564+        }
6565+    }
6566+
6567+}
6568+
6569+int PyramidShort::BorderExpand(PyramidShort *pyr, int nlev, int mode)
6570+{
6571+    PyramidShort *tpyr = pyr + nlev - 1;
6572+    PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border);
6573+    if (scr == NULL) return 0;
6574+
6575+    if (mode > 0) {
6576+        // Expand and add (reconstruct from Laplacian)
6577+        for (; tpyr > pyr; tpyr--) {
6578+            scr->width = tpyr[0].width;
6579+            scr->height = tpyr[-1].height;
6580+            BorderExpandOdd(tpyr, tpyr - 1, scr, 1);
6581+        }
6582+    }
6583+    else if (mode < 0) {
6584+        // Expand and subtract (build Laplacian)
6585+        while ((pyr++) < tpyr) {
6586+            scr->width = pyr[0].width;
6587+            scr->height = pyr[-1].height;
6588+            BorderExpandOdd(pyr, pyr - 1, scr, -1);
6589+        }
6590+    }
6591+
6592+    freeImage(scr);
6593+    return 1;
6594+}
6595+
6596+void PyramidShort::BorderReduceOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr)
6597+{
6598+    ImageTypeShortBase *s, *ns, *ls, *p, *np;
6599+
6600+    int off = scr->border - 2;
6601+    s = scr->ptr[-scr->border] - (off >> 1);
6602+    ns = s + scr->pitch;
6603+    ls = scr->ptr[scr->height + scr->border - 1] + scr->pitch - (off >> 1);
6604+    int width = scr->width + scr->border;
6605+    p = in->ptr[-scr->border] - off;
6606+    np = p + in->pitch;
6607+
6608+    // treat it as if the whole thing were the image
6609+    for (; s < ls; s = ns, ns += scr->pitch, p = np, np += in->pitch) {
6610+        for (int w = width; w--; s++, p += 2) {
6611+            *s = (short)((((int) p[-2]) + ((int) p[2]) + 8 +    // 1
6612+                        ((((int) p[-1]) + ((int) p[1])) << 2) + // 4
6613+                        ((int) *p) * 6) >> 4);          // 6
6614+        }
6615+    }
6616+
6617+    BorderSpread(scr, 5, 4 + ((in->width ^ 1) & 1), 0, 0); //
6618+
6619+    s = out->ptr[-(off >> 1)] - out->border;
6620+    ns = s + out->pitch;
6621+    ls = s + out->pitch * (out->height + off);
6622+    p = scr->ptr[-off] - out->border;
6623+    int pitch = scr->pitch;
6624+    int pitch2 = pitch << 1;
6625+    np = p + pitch2;
6626+    for (; s < ls; s = ns, ns += out->pitch, p = np, np += pitch2) {
6627+        for (int w = out->pitch; w--; s++, p++) {
6628+            *s = (short)((((int) p[-pitch2]) + ((int) p[pitch2]) + 8 + // 1
6629+                        ((((int) p[-pitch]) + ((int) p[pitch])) << 2) + // 4
6630+                        ((int) *p) * 6) >> 4);              // 6
6631+        }
6632+    }
6633+    BorderSpread(out, 0, 0, 5, 5);
6634+
6635+}
6636+
6637+int PyramidShort::BorderReduce(PyramidShort *pyr, int nlev)
6638+{
6639+    PyramidShort *scr = allocateImage(pyr[1].width, pyr[0].height, pyr->border);
6640+    if (scr == NULL)
6641+        return 0;
6642+
6643+    BorderSpread(pyr, pyr->border, pyr->border, pyr->border, pyr->border);
6644+    while (--nlev) {
6645+        BorderReduceOdd(pyr, pyr + 1, scr);
6646+        pyr++;
6647+        scr->width = pyr[1].width;
6648+        scr->height = pyr[0].height;
6649+    }
6650+
6651+    freeImage(scr);
6652+    return 1;
6653+}
6654diff --git a/benchmark/feature_mos/src/mosaic/Pyramid.h b/benchmark/feature_mos/src/mosaic/Pyramid.h
6655new file mode 100644
6656index 00000000..c5fe9071
6657--- /dev/null
6658+++ b/benchmark/feature_mos/src/mosaic/Pyramid.h
6659@@ -0,0 +1,54 @@
6660+/*
6661+ * Copyright (C) 2011 The Android Open Source Project
6662+ *
6663+ * Licensed under the Apache License, Version 2.0 (the "License");
6664+ * you may not use this file except in compliance with the License.
6665+ * You may obtain a copy of the License at
6666+ *
6667+ *      http://www.apache.org/licenses/LICENSE-2.0
6668+ *
6669+ * Unless required by applicable law or agreed to in writing, software
6670+ * distributed under the License is distributed on an "AS IS" BASIS,
6671+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6672+ * See the License for the specific language governing permissions and
6673+ * limitations under the License.
6674+ */
6675+
6676+// Pyramid.h
6677+
6678+#ifndef PYRAMID_H
6679+#define PYRAMID_H
6680+
6681+#include "ImageUtils.h"
6682+
6683+typedef unsigned short int real;
6684+
6685+//  Structure containing a packed pyramid of type ImageTypeShort.  Used for pyramid
6686+//  blending, among other things.
6687+
6688+class PyramidShort
6689+{
6690+
6691+public:
6692+
6693+  ImageTypeShort *ptr;              // Pointer containing the image
6694+  real width, height;               // Width and height of input images
6695+  real numChannels;                 // Number of channels in input images
6696+  real border;                      // border size
6697+  real pitch;                       // Pitch.  Used for moving through image efficiently.
6698+
6699+  static PyramidShort *allocatePyramidPacked(real width, real height, real levels, real border = 0);
6700+  static PyramidShort *allocateImage(real width, real height, real border);
6701+  static void createPyramid(ImageType image, PyramidShort *pyramid, int last = 3 );
6702+  static void freeImage(PyramidShort *image);
6703+
6704+  static unsigned int calcStorage(real width, real height, real border2, int levels, int *lines);
6705+
6706+  static void BorderSpread(PyramidShort *pyr, int left, int right, int top, int bot);
6707+  static void BorderExpandOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr, int mode);
6708+  static int BorderExpand(PyramidShort *pyr, int nlev, int mode);
6709+  static int BorderReduce(PyramidShort *pyr, int nlev);
6710+  static void BorderReduceOdd(PyramidShort *in, PyramidShort *out, PyramidShort *scr);
6711+};
6712+
6713+#endif
6714diff --git a/benchmark/feature_mos/src/mosaic/trsMatrix.cpp b/benchmark/feature_mos/src/mosaic/trsMatrix.cpp
6715new file mode 100644
6716index 00000000..4c04e6c3
6717--- /dev/null
6718+++ b/benchmark/feature_mos/src/mosaic/trsMatrix.cpp
6719@@ -0,0 +1,93 @@
6720+/*
6721+ * Copyright (C) 2011 The Android Open Source Project
6722+ *
6723+ * Licensed under the Apache License, Version 2.0 (the "License");
6724+ * you may not use this file except in compliance with the License.
6725+ * You may obtain a copy of the License at
6726+ *
6727+ *      http://www.apache.org/licenses/LICENSE-2.0
6728+ *
6729+ * Unless required by applicable law or agreed to in writing, software
6730+ * distributed under the License is distributed on an "AS IS" BASIS,
6731+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6732+ * See the License for the specific language governing permissions and
6733+ * limitations under the License.
6734+ */
6735+
6736+// trsMatrix.cpp
6737+// $Id: trsMatrix.cpp,v 1.9 2011/06/17 13:35:48 mbansal Exp $
6738+
6739+#include "stdio.h"
6740+#include <math.h>
6741+#include "trsMatrix.h"
6742+
6743+void mult33d(double a[3][3], double b[3][3], double c[3][3])
6744+{
6745+    a[0][0] = b[0][0]*c[0][0] + b[0][1]*c[1][0] + b[0][2]*c[2][0];
6746+    a[0][1] = b[0][0]*c[0][1] + b[0][1]*c[1][1] + b[0][2]*c[2][1];
6747+    a[0][2] = b[0][0]*c[0][2] + b[0][1]*c[1][2] + b[0][2]*c[2][2];
6748+    a[1][0] = b[1][0]*c[0][0] + b[1][1]*c[1][0] + b[1][2]*c[2][0];
6749+    a[1][1] = b[1][0]*c[0][1] + b[1][1]*c[1][1] + b[1][2]*c[2][1];
6750+    a[1][2] = b[1][0]*c[0][2] + b[1][1]*c[1][2] + b[1][2]*c[2][2];
6751+    a[2][0] = b[2][0]*c[0][0] + b[2][1]*c[1][0] + b[2][2]*c[2][0];
6752+    a[2][1] = b[2][0]*c[0][1] + b[2][1]*c[1][1] + b[2][2]*c[2][1];
6753+    a[2][2] = b[2][0]*c[0][2] + b[2][1]*c[1][2] + b[2][2]*c[2][2];
6754+}
6755+
6756+
6757+// normProjMat33d
6758+// m = input matrix
6759+// return: result if successful
6760+int normProjMat33d(double m[3][3])
6761+{
6762+
6763+    if(m[2][2] == 0.0)
6764+        {
6765+        return 0;
6766+}
6767+
6768+    m[0][0] /= m[2][2];
6769+    m[0][1] /= m[2][2];
6770+    m[0][2] /= m[2][2];
6771+    m[1][0] /= m[2][2];
6772+    m[1][1] /= m[2][2];
6773+    m[1][2] /= m[2][2];
6774+    m[2][0] /= m[2][2];
6775+    m[2][1] /= m[2][2];
6776+    m[2][2] = 1.0;
6777+
6778+    return 1;
6779+}
6780+
6781+// det33d
6782+// m = input matrix
6783+// returns: determinant
6784+double det33d(const double m[3][3])
6785+{
6786+    double result;
6787+
6788+    result  = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
6789+    result += m[0][1] * (m[1][2] * m[2][0] - m[1][0] * m[2][2]);
6790+    result += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
6791+
6792+    return result;
6793+}
6794+
6795+// inv33d
6796+//
6797+void inv33d(const double m[3][3], double out[3][3])
6798+{
6799+    double det = det33d(m);
6800+
6801+    out[0][0] = (m[1][1]*m[2][2] - m[1][2]*m[2][1]) / det;
6802+    out[1][0] = (m[1][2]*m[2][0] - m[1][0]*m[2][2]) / det;
6803+    out[2][0] = (m[1][0]*m[2][1] - m[1][1]*m[2][0]) / det;
6804+
6805+    out[0][1] = (m[0][2]*m[2][1] - m[0][1]*m[2][2]) / det;
6806+    out[1][1] = (m[0][0]*m[2][2] - m[0][2]*m[2][0]) / det;
6807+    out[2][1] = (m[0][1]*m[2][0] - m[0][0]*m[2][1]) / det;
6808+
6809+    out[0][2] = (m[0][1]*m[1][2] - m[0][2]*m[1][1]) / det;
6810+    out[1][2] = (m[0][2]*m[1][0] - m[0][0]*m[1][2]) / det;
6811+    out[2][2] = (m[0][0]*m[1][1] - m[0][1]*m[1][0]) / det;
6812+}
6813diff --git a/benchmark/feature_mos/src/mosaic/trsMatrix.h b/benchmark/feature_mos/src/mosaic/trsMatrix.h
6814new file mode 100644
6815index 00000000..054cc333
6816--- /dev/null
6817+++ b/benchmark/feature_mos/src/mosaic/trsMatrix.h
6818@@ -0,0 +1,53 @@
6819+/*
6820+ * Copyright (C) 2011 The Android Open Source Project
6821+ *
6822+ * Licensed under the Apache License, Version 2.0 (the "License");
6823+ * you may not use this file except in compliance with the License.
6824+ * You may obtain a copy of the License at
6825+ *
6826+ *      http://www.apache.org/licenses/LICENSE-2.0
6827+ *
6828+ * Unless required by applicable law or agreed to in writing, software
6829+ * distributed under the License is distributed on an "AS IS" BASIS,
6830+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6831+ * See the License for the specific language governing permissions and
6832+ * limitations under the License.
6833+ */
6834+
6835+///////////////////////////////////////////////////
6836+// trsMatrix.h
6837+// $Id: trsMatrix.h,v 1.8 2011/06/17 13:35:48 mbansal Exp $
6838+
6839+#ifndef TRSMATRIX_H_
6840+#define TRSMATRIX_H_
6841+
6842+
6843+// Calculate the determinant of a matrix
6844+double det33d(const double m[3][3]);
6845+
6846+// Invert a matrix
6847+void inv33d(const double m[3][3], double out[3][3]);
6848+
6849+// Multiply a = b * c
6850+void mult33d(double a[3][3], double b[3][3], double c[3][3]);
6851+
6852+// Normalize matrix so matrix[2][2] is '1'
6853+int normProjMat33d(double m[3][3]);
6854+
6855+inline double ProjZ(double trs[3][3], double x, double y, double f)
6856+{
6857+    return ((trs)[2][0]*(x) + (trs)[2][1]*(y) + (trs)[2][2]*(f));
6858+}
6859+
6860+inline double ProjX(double trs[3][3], double x, double y, double z, double f)
6861+{
6862+    return (((trs)[0][0]*(x) + (trs)[0][1]*(y) + (trs)[0][2]*(f)) / (z));
6863+}
6864+
6865+inline double ProjY(double trs[3][3], double x, double y, double z, double f)
6866+{
6867+    return (((trs)[1][0]*(x) + (trs)[1][1]*(y) + (trs)[1][2]*(f)) / (z));
6868+}
6869+
6870+
6871+#endif
6872diff --git a/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp
6873new file mode 100755
6874index 00000000..a956f23b
6875--- /dev/null
6876+++ b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.cpp
6877@@ -0,0 +1,98 @@
6878+#include "FrameBuffer.h"
6879+
6880+FrameBuffer::FrameBuffer()
6881+{
6882+    Reset();
6883+}
6884+
6885+FrameBuffer::~FrameBuffer() {
6886+}
6887+
6888+void FrameBuffer::Reset() {
6889+    mFrameBufferName = -1;
6890+    mTextureName = -1;
6891+    mWidth = 0;
6892+    mHeight = 0;
6893+    mFormat = -1;
6894+}
6895+
6896+bool FrameBuffer::InitializeGLContext() {
6897+    Reset();
6898+    return CreateBuffers();
6899+}
6900+
6901+bool FrameBuffer::Init(int width, int height, GLenum format) {
6902+    if (mFrameBufferName == (GLuint)-1) {
6903+        if (!CreateBuffers()) {
6904+            return false;
6905+        }
6906+    }
6907+    glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferName);
6908+    glBindTexture(GL_TEXTURE_2D, mTextureName);
6909+
6910+    glTexImage2D(GL_TEXTURE_2D,
6911+                 0,
6912+                 format,
6913+                 width,
6914+                 height,
6915+                 0,
6916+                 format,
6917+                 GL_UNSIGNED_BYTE,
6918+                 NULL);
6919+    if (!checkGlError("bind/teximage")) {
6920+        return false;
6921+    }
6922+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6923+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6924+    // This is necessary to work with user-generated frame buffers with
6925+    // dimensions that are NOT powers of 2.
6926+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6927+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
6928+
6929+    // Attach texture to frame buffer.
6930+    glFramebufferTexture2D(GL_FRAMEBUFFER,
6931+                           GL_COLOR_ATTACHMENT0,
6932+                           GL_TEXTURE_2D,
6933+                           mTextureName,
6934+                           0);
6935+    checkFramebufferStatus("FrameBuffer.cpp");
6936+    checkGlError("framebuffertexture2d");
6937+
6938+    if (!checkGlError("texture setup")) {
6939+        return false;
6940+    }
6941+    mWidth = width;
6942+    mHeight = height;
6943+    mFormat = format;
6944+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
6945+    return true;
6946+}
6947+
6948+bool FrameBuffer::CreateBuffers() {
6949+    glGenFramebuffers(1, &mFrameBufferName);
6950+    glGenTextures(1, &mTextureName);
6951+    if (!checkGlError("texture generation")) {
6952+        return false;
6953+    }
6954+    return true;
6955+}
6956+
6957+GLuint FrameBuffer::GetTextureName() const {
6958+    return mTextureName;
6959+}
6960+
6961+GLuint FrameBuffer::GetFrameBufferName() const {
6962+    return mFrameBufferName;
6963+}
6964+
6965+GLenum FrameBuffer::GetFormat() const {
6966+    return mFormat;
6967+}
6968+
6969+int FrameBuffer::GetWidth() const {
6970+    return mWidth;
6971+}
6972+
6973+int FrameBuffer::GetHeight() const {
6974+    return mHeight;
6975+}
6976diff --git a/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h
6977new file mode 100755
6978index 00000000..314b1262
6979--- /dev/null
6980+++ b/benchmark/feature_mos/src/mosaic_renderer/FrameBuffer.h
6981@@ -0,0 +1,34 @@
6982+#pragma once
6983+
6984+#include <EGL/egl.h>
6985+#include <GLES2/gl2.h>
6986+#include <GLES2/gl2ext.h>
6987+
6988+#define checkGlError(op)  checkGLErrorDetail(__FILE__, __LINE__, (op))
6989+
6990+extern bool checkGLErrorDetail(const char* file, int line, const char* op);
6991+extern void checkFramebufferStatus(const char* name);
6992+
6993+class FrameBuffer {
6994+  public:
6995+    FrameBuffer();
6996+    virtual ~FrameBuffer();
6997+
6998+    bool InitializeGLContext();
6999+    bool Init(int width, int height, GLenum format);
7000+    GLuint GetTextureName() const;
7001+    GLuint GetFrameBufferName() const;
7002+    GLenum GetFormat() const;
7003+
7004+    int GetWidth() const;
7005+    int GetHeight() const;
7006+
7007+ private:
7008+    void Reset();
7009+    bool CreateBuffers();
7010+    GLuint mFrameBufferName;
7011+    GLuint mTextureName;
7012+    int mWidth;
7013+    int mHeight;
7014+    GLenum mFormat;
7015+};
7016diff --git a/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp
7017new file mode 100755
7018index 00000000..b9938eb6
7019--- /dev/null
7020+++ b/benchmark/feature_mos/src/mosaic_renderer/Renderer.cpp
7021@@ -0,0 +1,226 @@
7022+/*
7023+ * Copyright (C) 2011 The Android Open Source Project
7024+ *
7025+ * Licensed under the Apache License, Version 2.0 (the "License");
7026+ * you may not use this file except in compliance with the License.
7027+ * You may obtain a copy of the License at
7028+ *
7029+ *      http://www.apache.org/licenses/LICENSE-2.0
7030+ *
7031+ * Unless required by applicable law or agreed to in writing, software
7032+ * distributed under the License is distributed on an "AS IS" BASIS,
7033+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7034+ * See the License for the specific language governing permissions and
7035+ * limitations under the License.
7036+ */
7037+
7038+#include "Renderer.h"
7039+
7040+#include "mosaic/Log.h"
7041+#define LOG_TAG "Renderer"
7042+
7043+#include <GLES2/gl2ext.h>
7044+
7045+Renderer::Renderer()
7046+      : mGlProgram(0),
7047+        mInputTextureName(-1),
7048+        mInputTextureWidth(0),
7049+        mInputTextureHeight(0),
7050+        mSurfaceWidth(0),
7051+        mSurfaceHeight(0)
7052+{
7053+    InitializeGLContext();
7054+}
7055+
7056+Renderer::~Renderer() {
7057+}
7058+
7059+GLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
7060+    GLuint shader = glCreateShader(shaderType);
7061+    if (shader) {
7062+        glShaderSource(shader, 1, &pSource, NULL);
7063+        glCompileShader(shader);
7064+        GLint compiled = 0;
7065+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
7066+        if (!compiled) {
7067+            GLint infoLen = 0;
7068+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
7069+            if (infoLen) {
7070+                char* buf = (char*) malloc(infoLen);
7071+                if (buf) {
7072+                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
7073+                    LOGE("Could not compile shader %d:\n%s\n",
7074+                            shaderType, buf);
7075+                    free(buf);
7076+                }
7077+                glDeleteShader(shader);
7078+                shader = 0;
7079+            }
7080+        }
7081+    }
7082+    return shader;
7083+}
7084+
7085+GLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
7086+{
7087+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
7088+    if (!vertexShader)
7089+    {
7090+        return 0;
7091+    }
7092+
7093+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
7094+    if (!pixelShader)
7095+    {
7096+        return 0;
7097+    }
7098+
7099+    GLuint program = glCreateProgram();
7100+    if (program)
7101+    {
7102+        glAttachShader(program, vertexShader);
7103+        checkGlError("glAttachShader");
7104+        glAttachShader(program, pixelShader);
7105+        checkGlError("glAttachShader");
7106+
7107+        glLinkProgram(program);
7108+        GLint linkStatus = GL_FALSE;
7109+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
7110+
7111+        LOGI("Program Linked (%d)!", program);
7112+
7113+        if (linkStatus != GL_TRUE)
7114+        {
7115+            GLint bufLength = 0;
7116+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
7117+            if (bufLength)
7118+            {
7119+                char* buf = (char*) malloc(bufLength);
7120+                if (buf)
7121+                {
7122+                    glGetProgramInfoLog(program, bufLength, NULL, buf);
7123+                    LOGE("Could not link program:\n%s\n", buf);
7124+                    free(buf);
7125+                }
7126+            }
7127+            glDeleteProgram(program);
7128+            program = 0;
7129+        }
7130+    }
7131+    return program;
7132+}
7133+
7134+// Set this renderer to use the default frame-buffer (screen) and
7135+// set the viewport size to be the given width and height (pixels).
7136+bool Renderer::SetupGraphics(int width, int height)
7137+{
7138+    bool succeeded = false;
7139+    do {
7140+        if (mGlProgram == 0)
7141+        {
7142+            if (!InitializeGLProgram())
7143+            {
7144+              break;
7145+            }
7146+        }
7147+        glUseProgram(mGlProgram);
7148+        if (!checkGlError("glUseProgram")) break;
7149+
7150+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
7151+
7152+        mFrameBuffer = NULL;
7153+        mSurfaceWidth = width;
7154+        mSurfaceHeight = height;
7155+
7156+        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
7157+        if (!checkGlError("glViewport")) break;
7158+        succeeded = true;
7159+    } while (false);
7160+
7161+    return succeeded;
7162+}
7163+
7164+
7165+// Set this renderer to use the specified FBO and
7166+// set the viewport size to be the width and height of this FBO.
7167+bool Renderer::SetupGraphics(FrameBuffer* buffer)
7168+{
7169+    bool succeeded = false;
7170+    do {
7171+        if (mGlProgram == 0)
7172+        {
7173+            if (!InitializeGLProgram())
7174+            {
7175+              break;
7176+            }
7177+        }
7178+        glUseProgram(mGlProgram);
7179+        if (!checkGlError("glUseProgram")) break;
7180+
7181+        glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
7182+
7183+        mFrameBuffer = buffer;
7184+        mSurfaceWidth = mFrameBuffer->GetWidth();
7185+        mSurfaceHeight = mFrameBuffer->GetHeight();
7186+
7187+        glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
7188+        if (!checkGlError("glViewport")) break;
7189+        succeeded = true;
7190+    } while (false);
7191+
7192+    return succeeded;
7193+}
7194+
7195+bool Renderer::Clear(float r, float g, float b, float a)
7196+{
7197+    bool succeeded = false;
7198+    do {
7199+        bool rt = (mFrameBuffer == NULL)?
7200+                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
7201+                SetupGraphics(mFrameBuffer);
7202+
7203+        if(!rt)
7204+            break;
7205+
7206+        glClearColor(r, g, b, a);
7207+        glClear(GL_COLOR_BUFFER_BIT);
7208+
7209+        succeeded = true;
7210+    } while (false);
7211+    return succeeded;
7212+
7213+}
7214+
7215+void Renderer::InitializeGLContext()
7216+{
7217+    if(mFrameBuffer != NULL)
7218+    {
7219+        delete mFrameBuffer;
7220+        mFrameBuffer = NULL;
7221+    }
7222+
7223+    mInputTextureName = -1;
7224+    mInputTextureType = GL_TEXTURE_2D;
7225+    mGlProgram = 0;
7226+}
7227+
7228+int Renderer::GetTextureName()
7229+{
7230+    return mInputTextureName;
7231+}
7232+
7233+void Renderer::SetInputTextureName(GLuint textureName)
7234+{
7235+    mInputTextureName = textureName;
7236+}
7237+
7238+void Renderer::SetInputTextureType(GLenum textureType)
7239+{
7240+    mInputTextureType = textureType;
7241+}
7242+
7243+void Renderer::SetInputTextureDimensions(int width, int height)
7244+{
7245+    mInputTextureWidth = width;
7246+    mInputTextureHeight = height;
7247+}
7248diff --git a/benchmark/feature_mos/src/mosaic_renderer/Renderer.h b/benchmark/feature_mos/src/mosaic_renderer/Renderer.h
7249new file mode 100755
7250index 00000000..a43e8028
7251--- /dev/null
7252+++ b/benchmark/feature_mos/src/mosaic_renderer/Renderer.h
7253@@ -0,0 +1,65 @@
7254+#pragma once
7255+
7256+#include "FrameBuffer.h"
7257+
7258+#include <GLES2/gl2.h>
7259+
7260+#include <stdint.h>
7261+#include <stdio.h>
7262+#include <stdlib.h>
7263+
7264+class Renderer {
7265+  public:
7266+    Renderer();
7267+    virtual ~Renderer();
7268+
7269+    // Initialize OpenGL resources
7270+    // @return true if successful
7271+    virtual bool InitializeGLProgram() = 0;
7272+
7273+    bool SetupGraphics(FrameBuffer* buffer);
7274+    bool SetupGraphics(int width, int height);
7275+
7276+    bool Clear(float r, float g, float b, float a);
7277+
7278+    int GetTextureName();
7279+    void SetInputTextureName(GLuint textureName);
7280+    void SetInputTextureDimensions(int width, int height);
7281+    void SetInputTextureType(GLenum textureType);
7282+
7283+    void InitializeGLContext();
7284+
7285+  protected:
7286+
7287+    GLuint loadShader(GLenum shaderType, const char* pSource);
7288+    GLuint createProgram(const char*, const char* );
7289+
7290+    int SurfaceWidth() const { return mSurfaceWidth; }
7291+    int SurfaceHeight() const { return mSurfaceHeight; }
7292+
7293+    // Source code for shaders.
7294+    virtual const char* VertexShaderSource() const = 0;
7295+    virtual const char* FragmentShaderSource() const = 0;
7296+
7297+    // Redefine this to use special texture types such as
7298+    // GL_TEXTURE_EXTERNAL_OES.
7299+    GLenum InputTextureType() const { return mInputTextureType; }
7300+
7301+    GLuint mGlProgram;
7302+    GLuint mInputTextureName;
7303+    GLenum mInputTextureType;
7304+    int mInputTextureWidth;
7305+    int mInputTextureHeight;
7306+
7307+    // Attribute locations
7308+    GLint  mScalingtransLoc;
7309+    GLint maPositionHandle;
7310+    GLint maTextureHandle;
7311+
7312+
7313+    int mSurfaceWidth;      // Width of target surface.
7314+    int mSurfaceHeight;     // Height of target surface.
7315+
7316+    FrameBuffer *mFrameBuffer;
7317+};
7318+
7319diff --git a/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp
7320new file mode 100755
7321index 00000000..36f133f8
7322--- /dev/null
7323+++ b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp
7324@@ -0,0 +1,186 @@
7325+/*
7326+ * Copyright (C) 2011 The Android Open Source Project
7327+ *
7328+ * Licensed under the Apache License, Version 2.0 (the "License");
7329+ * you may not use this file except in compliance with the License.
7330+ * You may obtain a copy of the License at
7331+ *
7332+ *      http://www.apache.org/licenses/LICENSE-2.0
7333+ *
7334+ * Unless required by applicable law or agreed to in writing, software
7335+ * distributed under the License is distributed on an "AS IS" BASIS,
7336+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7337+ * See the License for the specific language governing permissions and
7338+ * limitations under the License.
7339+ */
7340+
7341+#include "SurfaceTextureRenderer.h"
7342+
7343+#include <string.h>
7344+
7345+#include <GLES2/gl2ext.h>
7346+const GLfloat g_vVertices[] = {
7347+    -1.f, -1.f, 0.0f, 1.0f,  // Position 0
7348+    0.0f,  0.0f,         // TexCoord 0
7349+     1.f, -1.f, 0.0f, 1.0f, // Position 1
7350+    1.0f,  0.0f,         // TexCoord 1
7351+    -1.f,  1.f, 0.0f, 1.0f, // Position 2
7352+    0.0f,  1.0f,         // TexCoord 2
7353+    1.f,   1.f, 0.0f, 1.0f, // Position 3
7354+    1.0f,  1.0f          // TexCoord 3
7355+};
7356+GLushort g_iIndices2[] = { 0, 1, 2, 3 };
7357+
7358+const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
7359+
7360+SurfaceTextureRenderer::SurfaceTextureRenderer() : Renderer() {
7361+    memset(mSTMatrix, 0.0, 16*sizeof(float));
7362+    mSTMatrix[0] = 1.0f;
7363+    mSTMatrix[5] = 1.0f;
7364+    mSTMatrix[10] = 1.0f;
7365+    mSTMatrix[15] = 1.0f;
7366+}
7367+
7368+SurfaceTextureRenderer::~SurfaceTextureRenderer() {
7369+}
7370+
7371+void SurfaceTextureRenderer::SetViewportMatrix(int w, int h, int W, int H)
7372+{
7373+    for(int i=0; i<16; i++)
7374+    {
7375+        mViewportMatrix[i] = 0.0f;
7376+    }
7377+
7378+    mViewportMatrix[0] = float(w)/float(W);
7379+    mViewportMatrix[5] = float(h)/float(H);
7380+    mViewportMatrix[10] = 1.0f;
7381+    mViewportMatrix[12] = -1.0f + float(w)/float(W);
7382+    mViewportMatrix[13] = -1.0f + float(h)/float(H);
7383+    mViewportMatrix[15] = 1.0f;
7384+}
7385+
7386+void SurfaceTextureRenderer::SetScalingMatrix(float xscale, float yscale)
7387+{
7388+    for(int i=0; i<16; i++)
7389+    {
7390+        mScalingMatrix[i] = 0.0f;
7391+    }
7392+
7393+    mScalingMatrix[0] = xscale;
7394+    mScalingMatrix[5] = yscale;
7395+    mScalingMatrix[10] = 1.0f;
7396+    mScalingMatrix[15] = 1.0f;
7397+}
7398+
7399+void SurfaceTextureRenderer::SetSTMatrix(float *stmat)
7400+{
7401+    memcpy(mSTMatrix, stmat, 16*sizeof(float));
7402+}
7403+
7404+
7405+bool SurfaceTextureRenderer::InitializeGLProgram()
7406+{
7407+    bool succeeded = false;
7408+    do {
7409+        GLuint glProgram;
7410+        glProgram = createProgram(VertexShaderSource(),
7411+                FragmentShaderSource());
7412+        if (!glProgram) {
7413+            break;
7414+        }
7415+
7416+        glUseProgram(glProgram);
7417+        if (!checkGlError("glUseProgram")) break;
7418+
7419+        maPositionHandle = glGetAttribLocation(glProgram, "aPosition");
7420+        checkGlError("glGetAttribLocation aPosition");
7421+        maTextureHandle = glGetAttribLocation(glProgram, "aTextureCoord");
7422+        checkGlError("glGetAttribLocation aTextureCoord");
7423+        muSTMatrixHandle = glGetUniformLocation(glProgram, "uSTMatrix");
7424+        checkGlError("glGetUniformLocation uSTMatrix");
7425+        mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans");
7426+
7427+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
7428+        mGlProgram = glProgram;
7429+        succeeded = true;
7430+    } while (false);
7431+
7432+    if (!succeeded && (mGlProgram != 0))
7433+    {
7434+        glDeleteProgram(mGlProgram);
7435+        checkGlError("glDeleteProgram");
7436+        mGlProgram = 0;
7437+    }
7438+    return succeeded;
7439+}
7440+
7441+bool SurfaceTextureRenderer::DrawTexture(GLfloat *affine)
7442+{
7443+    bool succeeded = false;
7444+    do {
7445+        bool rt = (mFrameBuffer == NULL)?
7446+            SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
7447+            SetupGraphics(mFrameBuffer);
7448+
7449+        if(!rt)
7450+            break;
7451+
7452+        glDisable(GL_BLEND);
7453+
7454+        glActiveTexture(GL_TEXTURE0);
7455+        if (!checkGlError("glActiveTexture")) break;
7456+
7457+        const GLenum texture_type = InputTextureType();
7458+        glBindTexture(texture_type, mInputTextureName);
7459+        if (!checkGlError("glBindTexture")) break;
7460+
7461+        glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix);
7462+        glUniformMatrix4fv(muSTMatrixHandle, 1, GL_FALSE, mSTMatrix);
7463+
7464+        // Load the vertex position
7465+        glVertexAttribPointer(maPositionHandle, 4, GL_FLOAT,
7466+                GL_FALSE, VERTEX_STRIDE, g_vVertices);
7467+        glEnableVertexAttribArray(maPositionHandle);
7468+        // Load the texture coordinate
7469+        glVertexAttribPointer(maTextureHandle, 2, GL_FLOAT,
7470+                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
7471+        glEnableVertexAttribArray(maTextureHandle);
7472+
7473+        // And, finally, execute the GL draw command.
7474+        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices2);
7475+
7476+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
7477+        succeeded = true;
7478+    } while (false);
7479+    return succeeded;
7480+}
7481+
7482+const char* SurfaceTextureRenderer::VertexShaderSource() const
7483+{
7484+    static const char gVertexShader[] =
7485+        "uniform mat4 uSTMatrix;\n"
7486+        "uniform mat4 u_scalingtrans;  \n"
7487+        "attribute vec4 aPosition;\n"
7488+        "attribute vec4 aTextureCoord;\n"
7489+        "varying vec2 vTextureNormCoord;\n"
7490+        "void main() {\n"
7491+        "  gl_Position = u_scalingtrans * aPosition;\n"
7492+        "  vTextureNormCoord = (uSTMatrix * aTextureCoord).xy;\n"
7493+        "}\n";
7494+
7495+    return gVertexShader;
7496+}
7497+
7498+const char* SurfaceTextureRenderer::FragmentShaderSource() const
7499+{
7500+    static const char gFragmentShader[] =
7501+        "#extension GL_OES_EGL_image_external : require\n"
7502+        "precision mediump float;\n"
7503+        "varying vec2 vTextureNormCoord;\n"
7504+        "uniform samplerExternalOES sTexture;\n"
7505+        "void main() {\n"
7506+        "  gl_FragColor = texture2D(sTexture, vTextureNormCoord);\n"
7507+        "}\n";
7508+
7509+    return gFragmentShader;
7510+}
7511diff --git a/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h
7512new file mode 100755
7513index 00000000..ea2b81ad
7514--- /dev/null
7515+++ b/benchmark/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h
7516@@ -0,0 +1,44 @@
7517+#pragma once
7518+
7519+#include "FrameBuffer.h"
7520+#include "Renderer.h"
7521+
7522+#include <GLES2/gl2.h>
7523+
7524+#include <stdint.h>
7525+#include <stdio.h>
7526+#include <stdlib.h>
7527+
7528+class SurfaceTextureRenderer: public Renderer {
7529+  public:
7530+    SurfaceTextureRenderer();
7531+    virtual ~SurfaceTextureRenderer();
7532+
7533+    // Initialize OpenGL resources
7534+    // @return true if successful
7535+    bool InitializeGLProgram();
7536+
7537+    bool DrawTexture(GLfloat *affine);
7538+
7539+    void SetViewportMatrix(int w, int h, int W, int H);
7540+    void SetScalingMatrix(float xscale, float yscale);
7541+    void SetSTMatrix(float *stmat);
7542+
7543+ private:
7544+    // Source code for shaders.
7545+    const char* VertexShaderSource() const;
7546+    const char* FragmentShaderSource() const;
7547+
7548+    // Attribute locations
7549+    GLint  mScalingtransLoc;
7550+    GLint muSTMatrixHandle;
7551+    GLint maPositionHandle;
7552+    GLint maTextureHandle;
7553+
7554+    GLfloat mViewportMatrix[16];
7555+    GLfloat mScalingMatrix[16];
7556+
7557+    GLfloat mSTMatrix[16];
7558+
7559+};
7560+
7561diff --git a/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp
7562new file mode 100755
7563index 00000000..af6779a3
7564--- /dev/null
7565+++ b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.cpp
7566@@ -0,0 +1,190 @@
7567+/*
7568+ * Copyright (C) 2011 The Android Open Source Project
7569+ *
7570+ * Licensed under the Apache License, Version 2.0 (the "License");
7571+ * you may not use this file except in compliance with the License.
7572+ * You may obtain a copy of the License at
7573+ *
7574+ *      http://www.apache.org/licenses/LICENSE-2.0
7575+ *
7576+ * Unless required by applicable law or agreed to in writing, software
7577+ * distributed under the License is distributed on an "AS IS" BASIS,
7578+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7579+ * See the License for the specific language governing permissions and
7580+ * limitations under the License.
7581+ */
7582+
7583+#include "WarpRenderer.h"
7584+
7585+#include <GLES2/gl2ext.h>
7586+
7587+const GLfloat g_vVertices[] = {
7588+    -1.f, 1.f, 0.0f, 1.0f,  // Position 0
7589+    0.0f,  1.0f,         // TexCoord 0
7590+     1.f, 1.f, 0.0f, 1.0f, // Position 1
7591+    1.0f,  1.0f,         // TexCoord 1
7592+    -1.f, -1.f, 0.0f, 1.0f, // Position 2
7593+    0.0f,  0.0f,         // TexCoord 2
7594+    1.f,  -1.f, 0.0f, 1.0f, // Position 3
7595+    1.0f,  0.0f          // TexCoord 3
7596+};
7597+
7598+const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
7599+
7600+GLushort g_iIndices[] = { 0, 1, 2, 3 };
7601+
7602+WarpRenderer::WarpRenderer() : Renderer()
7603+{
7604+}
7605+
7606+WarpRenderer::~WarpRenderer() {
7607+}
7608+
7609+void WarpRenderer::SetViewportMatrix(int w, int h, int W, int H)
7610+{
7611+    for(int i=0; i<16; i++)
7612+    {
7613+        mViewportMatrix[i] = 0.0f;
7614+    }
7615+
7616+    mViewportMatrix[0] = float(w)/float(W);
7617+    mViewportMatrix[5] = float(h)/float(H);
7618+    mViewportMatrix[10] = 1.0f;
7619+    mViewportMatrix[12] = -1.0f + float(w)/float(W);
7620+    mViewportMatrix[13] = -1.0f + float(h)/float(H);
7621+    mViewportMatrix[15] = 1.0f;
7622+}
7623+
7624+void WarpRenderer::SetScalingMatrix(float xscale, float yscale)
7625+{
7626+    for(int i=0; i<16; i++)
7627+    {
7628+        mScalingMatrix[i] = 0.0f;
7629+    }
7630+
7631+    mScalingMatrix[0] = xscale;
7632+    mScalingMatrix[5] = yscale;
7633+    mScalingMatrix[10] = 1.0f;
7634+    mScalingMatrix[15] = 1.0f;
7635+}
7636+
7637+bool WarpRenderer::InitializeGLProgram()
7638+{
7639+    bool succeeded = false;
7640+    do {
7641+        GLuint glProgram;
7642+        glProgram = createProgram(VertexShaderSource(),
7643+                FragmentShaderSource());
7644+        if (!glProgram) {
7645+            break;
7646+        }
7647+
7648+        glUseProgram(glProgram);
7649+        if (!checkGlError("glUseProgram")) break;
7650+
7651+        // Get attribute locations
7652+        mPositionLoc     = glGetAttribLocation(glProgram, "a_position");
7653+        mAffinetransLoc  = glGetUniformLocation(glProgram, "u_affinetrans");
7654+        mViewporttransLoc = glGetUniformLocation(glProgram, "u_viewporttrans");
7655+        mScalingtransLoc = glGetUniformLocation(glProgram, "u_scalingtrans");
7656+        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
7657+
7658+        // Get sampler location
7659+        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
7660+
7661+        mGlProgram = glProgram;
7662+        succeeded = true;
7663+    } while (false);
7664+
7665+    if (!succeeded && (mGlProgram != 0))
7666+    {
7667+        glDeleteProgram(mGlProgram);
7668+        checkGlError("glDeleteProgram");
7669+        mGlProgram = 0;
7670+    }
7671+    return succeeded;
7672+}
7673+
7674+bool WarpRenderer::DrawTexture(GLfloat *affine)
7675+{
7676+    bool succeeded = false;
7677+    do {
7678+        bool rt = (mFrameBuffer == NULL)?
7679+                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
7680+                SetupGraphics(mFrameBuffer);
7681+
7682+        if(!rt)
7683+            break;
7684+
7685+        glDisable(GL_BLEND);
7686+
7687+        glActiveTexture(GL_TEXTURE0);
7688+        if (!checkGlError("glActiveTexture")) break;
7689+
7690+        const GLenum texture_type = InputTextureType();
7691+        glBindTexture(texture_type, mInputTextureName);
7692+        if (!checkGlError("glBindTexture")) break;
7693+
7694+        // Set the sampler texture unit to 0
7695+        glUniform1i(mSamplerLoc, 0);
7696+
7697+        // Load the vertex position
7698+        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
7699+                GL_FALSE, VERTEX_STRIDE, g_vVertices);
7700+
7701+        // Load the texture coordinate
7702+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
7703+                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
7704+
7705+        glEnableVertexAttribArray(mPositionLoc);
7706+        glEnableVertexAttribArray(mTexCoordLoc);
7707+
7708+        // pass matrix information to the vertex shader
7709+        glUniformMatrix4fv(mAffinetransLoc, 1, GL_FALSE, affine);
7710+        glUniformMatrix4fv(mViewporttransLoc, 1, GL_FALSE, mViewportMatrix);
7711+        glUniformMatrix4fv(mScalingtransLoc, 1, GL_FALSE, mScalingMatrix);
7712+
7713+        // And, finally, execute the GL draw command.
7714+        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices);
7715+
7716+        checkGlError("glDrawElements");
7717+
7718+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
7719+        succeeded = true;
7720+    } while (false);
7721+    return succeeded;
7722+}
7723+
7724+const char* WarpRenderer::VertexShaderSource() const
7725+{
7726+    static const char gVertexShader[] =
7727+        "uniform mat4 u_affinetrans;  \n"
7728+        "uniform mat4 u_viewporttrans;  \n"
7729+        "uniform mat4 u_scalingtrans;  \n"
7730+        "attribute vec4 a_position;   \n"
7731+        "attribute vec2 a_texCoord;   \n"
7732+        "varying vec2 v_texCoord;     \n"
7733+        "void main()                  \n"
7734+        "{                            \n"
7735+        "   gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n"
7736+        "   v_texCoord = a_texCoord;  \n"
7737+        "}                            \n";
7738+
7739+    return gVertexShader;
7740+}
7741+
7742+const char* WarpRenderer::FragmentShaderSource() const
7743+{
7744+    static const char gFragmentShader[] =
7745+        "precision mediump float;                            \n"
7746+        "varying vec2 v_texCoord;                            \n"
7747+        "uniform sampler2D s_texture;                        \n"
7748+        "void main()                                         \n"
7749+        "{                                                   \n"
7750+        "  vec4 color;                                       \n"
7751+        "  color = texture2D(s_texture, v_texCoord);       \n"
7752+        "  gl_FragColor = color;                             \n"
7753+        "}                                                   \n";
7754+
7755+    return gFragmentShader;
7756+}
7757diff --git a/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h
7758new file mode 100755
7759index 00000000..aa3f50c0
7760--- /dev/null
7761+++ b/benchmark/feature_mos/src/mosaic_renderer/WarpRenderer.h
7762@@ -0,0 +1,44 @@
7763+#pragma once
7764+
7765+#include "FrameBuffer.h"
7766+#include "Renderer.h"
7767+
7768+#include <GLES2/gl2.h>
7769+
7770+#include <stdint.h>
7771+#include <stdio.h>
7772+#include <stdlib.h>
7773+
7774+class WarpRenderer: public Renderer {
7775+  public:
7776+    WarpRenderer();
7777+    virtual ~WarpRenderer();
7778+
7779+    // Initialize OpenGL resources
7780+    // @return true if successful
7781+    bool InitializeGLProgram();
7782+
7783+    void SetViewportMatrix(int w, int h, int W, int H);
7784+    void SetScalingMatrix(float xscale, float yscale);
7785+
7786+    bool DrawTexture(GLfloat *affine);
7787+
7788+ private:
7789+    // Source code for shaders.
7790+    const char* VertexShaderSource() const;
7791+    const char* FragmentShaderSource() const;
7792+
7793+    // Attribute locations
7794+    GLint  mPositionLoc;
7795+    GLint  mAffinetransLoc;
7796+    GLint  mViewporttransLoc;
7797+    GLint  mScalingtransLoc;
7798+    GLint  mTexCoordLoc;
7799+
7800+    GLfloat mViewportMatrix[16];
7801+    GLfloat mScalingMatrix[16];
7802+
7803+    // Sampler location
7804+    GLint mSamplerLoc;
7805+};
7806+
7807diff --git a/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp
7808new file mode 100755
7809index 00000000..f7dcf6f6
7810--- /dev/null
7811+++ b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.cpp
7812@@ -0,0 +1,160 @@
7813+/*
7814+ * Copyright (C) 2011 The Android Open Source Project
7815+ *
7816+ * Licensed under the Apache License, Version 2.0 (the "License");
7817+ * you may not use this file except in compliance with the License.
7818+ * You may obtain a copy of the License at
7819+ *
7820+ *      http://www.apache.org/licenses/LICENSE-2.0
7821+ *
7822+ * Unless required by applicable law or agreed to in writing, software
7823+ * distributed under the License is distributed on an "AS IS" BASIS,
7824+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7825+ * See the License for the specific language governing permissions and
7826+ * limitations under the License.
7827+ */
7828+
7829+#include "YVURenderer.h"
7830+
7831+#include <GLES2/gl2ext.h>
7832+
7833+const GLfloat g_vVertices[] = {
7834+    -1.f, 1.f, 0.0f, 1.0f,  // Position 0
7835+    0.0f,  1.0f,         // TexCoord 0
7836+     1.f, 1.f, 0.0f, 1.0f, // Position 1
7837+    1.0f,  1.0f,         // TexCoord 1
7838+    -1.f, -1.f, 0.0f, 1.0f, // Position 2
7839+    0.0f,  0.0f,         // TexCoord 2
7840+    1.f,  -1.f, 0.0f, 1.0f, // Position 3
7841+    1.0f,  0.0f          // TexCoord 3
7842+};
7843+
7844+const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
7845+
7846+GLushort g_iIndices3[] = { 0, 1, 2, 3 };
7847+
7848+YVURenderer::YVURenderer() : Renderer()
7849+                   {
7850+}
7851+
7852+YVURenderer::~YVURenderer() {
7853+}
7854+
7855+bool YVURenderer::InitializeGLProgram()
7856+{
7857+    bool succeeded = false;
7858+    do {
7859+        GLuint glProgram;
7860+        glProgram = createProgram(VertexShaderSource(),
7861+                FragmentShaderSource());
7862+        if (!glProgram) {
7863+            break;
7864+        }
7865+
7866+        glUseProgram(glProgram);
7867+        if (!checkGlError("glUseProgram")) break;
7868+
7869+        // Get attribute locations
7870+        mPositionLoc     = glGetAttribLocation(glProgram, "a_Position");
7871+        mTexCoordLoc     = glGetAttribLocation(glProgram, "a_texCoord");
7872+
7873+        // Get sampler location
7874+        mSamplerLoc      = glGetUniformLocation(glProgram, "s_texture");
7875+
7876+        mGlProgram = glProgram;
7877+        succeeded = true;
7878+    } while (false);
7879+
7880+    if (!succeeded && (mGlProgram != 0))
7881+    {
7882+        glDeleteProgram(mGlProgram);
7883+        checkGlError("glDeleteProgram");
7884+        mGlProgram = 0;
7885+    }
7886+    return succeeded;
7887+}
7888+
7889+bool YVURenderer::DrawTexture()
7890+{
7891+    bool succeeded = false;
7892+    do {
7893+        bool rt = (mFrameBuffer == NULL)?
7894+                SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
7895+                SetupGraphics(mFrameBuffer);
7896+
7897+        if(!rt)
7898+            break;
7899+
7900+        glDisable(GL_BLEND);
7901+
7902+        glActiveTexture(GL_TEXTURE0);
7903+        if (!checkGlError("glActiveTexture")) break;
7904+
7905+        const GLenum texture_type = InputTextureType();
7906+        glBindTexture(texture_type, mInputTextureName);
7907+        if (!checkGlError("glBindTexture")) break;
7908+
7909+        // Set the sampler texture unit to 0
7910+        glUniform1i(mSamplerLoc, 0);
7911+
7912+        // Load the vertex position
7913+        glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
7914+                GL_FALSE, VERTEX_STRIDE, g_vVertices);
7915+
7916+        // Load the texture coordinate
7917+        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
7918+                GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
7919+
7920+        glEnableVertexAttribArray(mPositionLoc);
7921+        glEnableVertexAttribArray(mTexCoordLoc);
7922+
7923+        // And, finally, execute the GL draw command.
7924+        glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3);
7925+
7926+        checkGlError("glDrawElements");
7927+
7928+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
7929+        succeeded = true;
7930+    } while (false);
7931+    return succeeded;
7932+}
7933+
7934+const char* YVURenderer::VertexShaderSource() const
7935+{
7936+    // All this really does is copy the coordinates into
7937+    // variables for the fragment shader to pick up.
7938+    static const char gVertexShader[] =
7939+        "attribute vec4 a_Position;\n"
7940+        "attribute vec2 a_texCoord;\n"
7941+        "varying vec2 v_texCoord;\n"
7942+        "void main() {\n"
7943+        "  gl_Position = a_Position;\n"
7944+        "  v_texCoord = a_texCoord;\n"
7945+        "}\n";
7946+
7947+    return gVertexShader;
7948+}
7949+
7950+const char* YVURenderer::FragmentShaderSource() const
7951+{
7952+    static const char gFragmentShader[] =
7953+        "precision mediump float;\n"
7954+        "uniform sampler2D s_texture;\n"
7955+        "const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n"
7956+        "const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n"
7957+        "const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n"
7958+        "varying vec2 v_texCoord;\n"
7959+        "void main() {\n"
7960+        "  vec4 p;\n"
7961+        "  p = texture2D(s_texture, v_texCoord);\n"
7962+        "  gl_FragColor[0] = dot(p, coeff_y);\n"
7963+        "  p = texture2D(s_texture, v_texCoord);\n"
7964+        "  gl_FragColor[1] = dot(p, coeff_v);\n"
7965+        "  p = texture2D(s_texture, v_texCoord);\n"
7966+        "  gl_FragColor[2] = dot(p, coeff_u);\n"
7967+        "  p = texture2D(s_texture, v_texCoord);\n"
7968+        "  gl_FragColor[3] = dot(p, coeff_y);\n"
7969+        "}\n";
7970+
7971+    return gFragmentShader;
7972+}
7973diff --git a/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h
7974new file mode 100755
7975index 00000000..d14a4b99
7976--- /dev/null
7977+++ b/benchmark/feature_mos/src/mosaic_renderer/YVURenderer.h
7978@@ -0,0 +1,35 @@
7979+#pragma once
7980+
7981+#include "FrameBuffer.h"
7982+#include "Renderer.h"
7983+
7984+#include <GLES2/gl2.h>
7985+
7986+#include <stdint.h>
7987+#include <stdio.h>
7988+#include <stdlib.h>
7989+
7990+class YVURenderer: public Renderer {
7991+  public:
7992+    YVURenderer();
7993+    virtual ~YVURenderer();
7994+
7995+    // Initialize OpenGL resources
7996+    // @return true if successful
7997+    bool InitializeGLProgram();
7998+
7999+    bool DrawTexture();
8000+
8001+ private:
8002+    // Source code for shaders.
8003+    const char* VertexShaderSource() const;
8004+    const char* FragmentShaderSource() const;
8005+
8006+    // Attribute locations
8007+    GLint  mPositionLoc;
8008+    GLint  mTexCoordLoc;
8009+
8010+    // Sampler location
8011+    GLint mSamplerLoc;
8012+};
8013+
8014diff --git a/benchmark/feature_mos_jni.cpp b/benchmark/feature_mos_jni.cpp
8015new file mode 100644
8016index 00000000..e40b75a0
8017--- /dev/null
8018+++ b/benchmark/feature_mos_jni.cpp
8019@@ -0,0 +1,669 @@
8020+/*
8021+ * Copyright (C) 2011 The Android Open Source Project
8022+ *
8023+ * Licensed under the Apache License, Version 2.0 (the "License");
8024+ * you may not use this file except in compliance with the License.
8025+ * You may obtain a copy of the License at
8026+ *
8027+ *      http://www.apache.org/licenses/LICENSE-2.0
8028+ *
8029+ * Unless required by applicable law or agreed to in writing, software
8030+ * distributed under the License is distributed on an "AS IS" BASIS,
8031+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8032+ * See the License for the specific language governing permissions and
8033+ * limitations under the License.
8034+ */
8035+
8036+/*
8037+*
8038+ */
8039+#include <string.h>
8040+#include <jni.h>
8041+#include <stdio.h>
8042+#include <stdlib.h>
8043+#include <time.h>
8044+#include <db_utilities_camera.h>
8045+
8046+#include "mosaic/AlignFeatures.h"
8047+#include "mosaic/Blend.h"
8048+#include "mosaic/Mosaic.h"
8049+#include "mosaic/Log.h"
8050+#define LOG_TAG "FEATURE_MOS_JNI"
8051+
8052+#ifdef __cplusplus
8053+extern "C" {
8054+#endif
8055+
8056+#include "mosaic_renderer_jni.h"
8057+
8058+char buffer[1024];
8059+
8060+const int MAX_FRAMES = 100;
8061+
8062+static double mTx;
8063+
8064+int tWidth[NR];
8065+int tHeight[NR];
8066+
8067+ImageType tImage[NR][MAX_FRAMES];// = {{ImageUtils::IMAGE_TYPE_NOIMAGE}}; // YVU24 format image
8068+Mosaic *mosaic[NR] = {NULL,NULL};
8069+ImageType resultYVU = ImageUtils::IMAGE_TYPE_NOIMAGE;
8070+ImageType resultBGR = ImageUtils::IMAGE_TYPE_NOIMAGE;
8071+float gTRS[11]; // 9 elements of the transformation, 1 for frame-number, 1 for alignment error code.
8072+// Variables to keep track of the mosaic computation progress for both LR & HR.
8073+float gProgress[NR];
8074+// Variables to be able to cancel the mosaic computation when the GUI says so.
8075+bool gCancelComputation[NR];
8076+
8077+int c;
8078+int width=0, height=0;
8079+int mosaicWidth=0, mosaicHeight=0;
8080+
8081+//int blendingType = Blend::BLEND_TYPE_FULL;
8082+//int blendingType = Blend::BLEND_TYPE_CYLPAN;
8083+int blendingType = Blend::BLEND_TYPE_HORZ;
8084+int stripType = Blend::STRIP_TYPE_THIN;
8085+bool high_res = false;
8086+bool quarter_res[NR] = {false,false};
8087+float thresh_still[NR] = {5.0f,0.0f};
8088+
8089+/* return current time in milliseconds*/
8090+
8091+#ifndef now_ms
8092+static double
8093+now_ms(void)
8094+{
8095+    //struct timespec res;
8096+    struct timeval res;
8097+    //clock_gettime(CLOCK_REALTIME, &res);
8098+    gettimeofday(&res, NULL);
8099+    return 1000.0*res.tv_sec + (double)res.tv_usec/1e3;
8100+}
8101+#endif
8102+
8103+
8104+static int frame_number_HR = 0;
8105+static int frame_number_LR = 0;
8106+
8107+int Init(int mID, int nmax)
8108+{
8109+        double  t0, t1, time_c;
8110+
8111+        if(mosaic[mID]!=NULL)
8112+        {
8113+                delete mosaic[mID];
8114+                mosaic[mID] = NULL;
8115+        }
8116+
8117+        mosaic[mID] = new Mosaic();
8118+
8119+        t0 = now_ms();
8120+
8121+        // When processing higher than 720x480 video, process low-res at
8122+        // quarter resolution
8123+        if(tWidth[LR]>180)
8124+            quarter_res[LR] = true;
8125+
8126+
8127+        // Check for initialization and if not, initialize
8128+        if (!mosaic[mID]->isInitialized())
8129+        {
8130+                mosaic[mID]->initialize(blendingType, stripType, tWidth[mID], tHeight[mID],
8131+                        nmax, quarter_res[mID], thresh_still[mID]);
8132+        }
8133+
8134+        t1 = now_ms();
8135+        time_c = t1 - t0;
8136+        LOGV("Init[%d]: %g ms [%d frames]",mID,time_c,nmax);
8137+        return 1;
8138+}
8139+
8140+void GenerateQuarterResImagePlanar(ImageType im, int input_w, int input_h,
8141+        ImageType &out)
8142+{
8143+    ImageType imp;
8144+    ImageType outp;
8145+
8146+    int count = 0;
8147+
8148+    for (int j = 0; j < input_h; j += H2L_FACTOR)
8149+    {
8150+        imp = im + j * input_w;
8151+        outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR);
8152+
8153+        for (int i = 0; i < input_w; i += H2L_FACTOR)
8154+        {
8155+            *outp++ = *(imp + i);
8156+            count++;
8157+        }
8158+    }
8159+
8160+    for (int j = input_h; j < 2 * input_h; j += H2L_FACTOR)
8161+    {
8162+        imp = im + j * input_w;
8163+        outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR);
8164+
8165+        for (int i = 0; i < input_w; i += H2L_FACTOR)
8166+        {
8167+            *outp++ = *(imp + i);
8168+            count++;
8169+        }
8170+    }
8171+
8172+    for (int j = 2 * input_h; j < 3 * input_h; j += H2L_FACTOR)
8173+    {
8174+        imp = im + j * input_w;
8175+        outp = out + (j / H2L_FACTOR) * (input_w / H2L_FACTOR);
8176+
8177+        for (int i = 0; i < input_w; i += H2L_FACTOR)
8178+        {
8179+            *outp++ = *(imp + i);
8180+            count++;
8181+        }
8182+    }
8183+}
8184+
8185+int AddFrame(int mID, int k, float* trs1d)
8186+{
8187+    double  t0, t1, time_c;
8188+    double trs[3][3];
8189+
8190+    int ret_code = mosaic[mID]->addFrame(tImage[mID][k]);
8191+
8192+    mosaic[mID]->getAligner()->getLastTRS(trs);
8193+
8194+    if(trs1d!=NULL)
8195+    {
8196+
8197+        trs1d[0] = trs[0][0];
8198+        trs1d[1] = trs[0][1];
8199+        trs1d[2] = trs[0][2];
8200+        trs1d[3] = trs[1][0];
8201+        trs1d[4] = trs[1][1];
8202+        trs1d[5] = trs[1][2];
8203+        trs1d[6] = trs[2][0];
8204+        trs1d[7] = trs[2][1];
8205+        trs1d[8] = trs[2][2];
8206+    }
8207+
8208+    return ret_code;
8209+}
8210+
8211+int Finalize(int mID)
8212+{
8213+    double  t0, t1, time_c;
8214+
8215+    t0 = now_ms();
8216+    // Create the mosaic
8217+    int ret = mosaic[mID]->createMosaic(gProgress[mID], gCancelComputation[mID]);
8218+    t1 = now_ms();
8219+    time_c = t1 - t0;
8220+    LOGV("CreateMosaic: %g ms",time_c);
8221+
8222+    // Get back the result
8223+    resultYVU = mosaic[mID]->getMosaic(mosaicWidth, mosaicHeight);
8224+
8225+    return ret;
8226+}
8227+
8228+void YUV420toYVU24(ImageType yvu24, ImageType yuv420sp, int width, int height)
8229+{
8230+    int frameSize = width * height;
8231+
8232+    ImageType oyp = yvu24;
8233+    ImageType ovp = yvu24+frameSize;
8234+    ImageType oup = yvu24+frameSize+frameSize;
8235+
8236+    for (int j = 0, yp = 0; j < height; j++)
8237+    {
8238+        unsigned char u = 0, v = 0;
8239+        int uvp = frameSize + (j >> 1) * width;
8240+        for (int i = 0; i < width; i++, yp++)
8241+        {
8242+            *oyp++ = yuv420sp[yp];
8243+            //int y = (0xff & (int)yuv420sp[yp]) -16;
8244+            //yvu24p[yp] = (y<0)?0:y;
8245+
8246+            if ((i & 1) == 0)
8247+            {
8248+                v = yuv420sp[uvp++];
8249+                u = yuv420sp[uvp++];
8250+            }
8251+
8252+            *ovp++ = v;
8253+            *oup++ = u;
8254+        }
8255+    }
8256+}
8257+
8258+void YUV420toYVU24_NEW(ImageType yvu24, ImageType yuv420sp, int width,
8259+        int height)
8260+{
8261+    int frameSize = width * height;
8262+
8263+    ImageType oyp = yvu24;
8264+    ImageType ovp = yvu24 + frameSize;
8265+    ImageType oup = yvu24 + frameSize + frameSize;
8266+
8267+    memcpy(yvu24, yuv420sp, frameSize * sizeof(unsigned char));
8268+
8269+    for (int j = 0; j < height; j += 2)
8270+    {
8271+        unsigned char u = 0, v = 0;
8272+        int uvp = frameSize + (j >> 1) * width;
8273+        ovp = yvu24 + frameSize + j * width;
8274+        oup = ovp + frameSize;
8275+
8276+        ImageType iuvp = yuv420sp + uvp;
8277+
8278+        for (int i = 0; i < width; i += 2)
8279+        {
8280+            v = *iuvp++;
8281+            u = *iuvp++;
8282+
8283+            *ovp++ = v;
8284+            *oup++ = u;
8285+
8286+            *ovp++ = v;
8287+            *oup++ = u;
8288+
8289+        }
8290+        memcpy(ovp, ovp - width, width * sizeof(unsigned char));
8291+        memcpy(oup, oup - width, width * sizeof(unsigned char));
8292+    }
8293+}
8294+
8295+
8296+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_allocateMosaicMemory(
8297+        JNIEnv* env, jobject thiz, jint width, jint height)
8298+{
8299+    tWidth[HR] = width;
8300+    tHeight[HR] = height;
8301+    tWidth[LR] = int(width / H2L_FACTOR);
8302+    tHeight[LR] = int(height / H2L_FACTOR);
8303+
8304+    for(int i=0; i<MAX_FRAMES; i++)
8305+    {
8306+            tImage[LR][i] = ImageUtils::allocateImage(tWidth[LR], tHeight[LR],
8307+                    ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
8308+            tImage[HR][i] = ImageUtils::allocateImage(tWidth[HR], tHeight[HR],
8309+                    ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
8310+    }
8311+
8312+    AllocateTextureMemory(tWidth[HR], tHeight[HR], tWidth[LR], tHeight[LR]);
8313+}
8314+
8315+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_freeMosaicMemory(
8316+        JNIEnv* env, jobject thiz)
8317+{
8318+    for(int i = 0; i < MAX_FRAMES; i++)
8319+    {
8320+        ImageUtils::freeImage(tImage[LR][i]);
8321+        ImageUtils::freeImage(tImage[HR][i]);
8322+    }
8323+
8324+    FreeTextureMemory();
8325+}
8326+
8327+
8328+void decodeYUV444SP(unsigned char* rgb, unsigned char* yuv420sp, int width,
8329+        int height)
8330+{
8331+    int frameSize = width * height;
8332+
8333+    for (int j = 0, yp = 0; j < height; j++)
8334+    {
8335+        int vp = frameSize + j * width, u = 0, v = 0;
8336+        int up = vp + frameSize;
8337+
8338+        for (int i = 0; i < width; i++, yp++, vp++, up++)
8339+        {
8340+            int y = (0xff & ((int) yuv420sp[yp])) - 16;
8341+            if (y < 0) y = 0;
8342+
8343+            v = (0xff & yuv420sp[vp]) - 128;
8344+            u = (0xff & yuv420sp[up]) - 128;
8345+
8346+            int y1192 = 1192 * y;
8347+            int r = (y1192 + 1634 * v);
8348+            int g = (y1192 - 833 * v - 400 * u);
8349+            int b = (y1192 + 2066 * u);
8350+
8351+            if (r < 0) r = 0; else if (r > 262143) r = 262143;
8352+            if (g < 0) g = 0; else if (g > 262143) g = 262143;
8353+            if (b < 0) b = 0; else if (b > 262143) b = 262143;
8354+
8355+            //rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
8356+            int p = j*width*3+i*3;
8357+            rgb[p+0] = (r<<6 & 0xFF0000)>>16;
8358+            rgb[p+1] = (g>>2 & 0xFF00)>>8;
8359+            rgb[p+2] =  b>>10 & 0xFF;
8360+        }
8361+    }
8362+}
8363+
8364+static int count = 0;
8365+
8366+void ConvertYVUAiToPlanarYVU(unsigned char *planar, unsigned char *in, int width,
8367+        int height)
8368+{
8369+    int planeSize = width * height;
8370+    unsigned char* Yptr = planar;
8371+    unsigned char* Vptr = planar + planeSize;
8372+    unsigned char* Uptr = Vptr + planeSize;
8373+
8374+    for (int i = 0; i < planeSize; i++)
8375+    {
8376+        *Yptr++ = *in++;
8377+        *Vptr++ = *in++;
8378+        *Uptr++ = *in++;
8379+        in++;   // Alpha
8380+    }
8381+}
8382+
8383+JNIEXPORT jfloatArray JNICALL Java_com_android_camera_panorama_Mosaic_setSourceImageFromGPU(
8384+        JNIEnv* env, jobject thiz)
8385+{
8386+    double  t0, t1, time_c;
8387+    t0 = now_ms();
8388+    int ret_code;
8389+
8390+    if(frame_number_HR<MAX_FRAMES && frame_number_LR<MAX_FRAMES)
8391+    {
8392+        double last_tx = mTx;
8393+
8394+        sem_wait(&gPreviewImage_semaphore);
8395+        ConvertYVUAiToPlanarYVU(tImage[LR][frame_number_LR], gPreviewImage[LR],
8396+                tWidth[LR], tHeight[LR]);
8397+
8398+        sem_post(&gPreviewImage_semaphore);
8399+
8400+        ret_code = AddFrame(LR, frame_number_LR, gTRS);
8401+
8402+        if(ret_code == Mosaic::MOSAIC_RET_OK || ret_code == Mosaic::MOSAIC_RET_FEW_INLIERS)
8403+        {
8404+            // Copy into HR buffer only if this is a valid frame
8405+            sem_wait(&gPreviewImage_semaphore);
8406+            ConvertYVUAiToPlanarYVU(tImage[HR][frame_number_HR], gPreviewImage[HR],
8407+                    tWidth[HR], tHeight[HR]);
8408+            sem_post(&gPreviewImage_semaphore);
8409+
8410+            frame_number_LR++;
8411+            frame_number_HR++;
8412+        }
8413+    }
8414+    else
8415+    {
8416+        gTRS[1] = gTRS[2] = gTRS[3] = gTRS[5] = gTRS[6] = gTRS[7] = 0.0f;
8417+        gTRS[0] = gTRS[4] = gTRS[8] = 1.0f;
8418+    }
8419+
8420+    UpdateWarpTransformation(gTRS);
8421+
8422+    gTRS[9] = frame_number_HR;
8423+    gTRS[10] = ret_code;
8424+
8425+    jfloatArray bytes = env->NewFloatArray(11);
8426+    if(bytes != 0)
8427+    {
8428+        env->SetFloatArrayRegion(bytes, 0, 11, (jfloat*) gTRS);
8429+    }
8430+    return bytes;
8431+}
8432+
8433+
8434+
8435+JNIEXPORT jfloatArray JNICALL Java_com_android_camera_panorama_Mosaic_setSourceImage(
8436+        JNIEnv* env, jobject thiz, jbyteArray photo_data)
8437+{
8438+    double  t0, t1, time_c;
8439+    t0 = now_ms();
8440+
8441+    int ret_code;
8442+
8443+    if(frame_number_HR<MAX_FRAMES && frame_number_LR<MAX_FRAMES)
8444+    {
8445+        jbyte *pixels = env->GetByteArrayElements(photo_data, 0);
8446+
8447+        YUV420toYVU24_NEW(tImage[HR][frame_number_HR], (ImageType)pixels,
8448+                tWidth[HR], tHeight[HR]);
8449+
8450+        env->ReleaseByteArrayElements(photo_data, pixels, 0);
8451+
8452+        double last_tx = mTx;
8453+
8454+        t0 = now_ms();
8455+        GenerateQuarterResImagePlanar(tImage[HR][frame_number_HR], tWidth[HR],
8456+                tHeight[HR], tImage[LR][frame_number_LR]);
8457+
8458+
8459+        sem_wait(&gPreviewImage_semaphore);
8460+        decodeYUV444SP(gPreviewImage[LR], tImage[LR][frame_number_LR],
8461+                gPreviewImageWidth[LR], gPreviewImageHeight[LR]);
8462+        sem_post(&gPreviewImage_semaphore);
8463+
8464+        ret_code = AddFrame(LR, frame_number_LR, gTRS);
8465+
8466+        if(ret_code == Mosaic::MOSAIC_RET_OK || ret_code == Mosaic::MOSAIC_RET_FEW_INLIERS)
8467+        {
8468+            frame_number_LR++;
8469+            frame_number_HR++;
8470+        }
8471+
8472+    }
8473+    else
8474+    {
8475+        gTRS[1] = gTRS[2] = gTRS[3] = gTRS[5] = gTRS[6] = gTRS[7] = 0.0f;
8476+        gTRS[0] = gTRS[4] = gTRS[8] = 1.0f;
8477+    }
8478+
8479+    UpdateWarpTransformation(gTRS);
8480+
8481+    gTRS[9] = frame_number_HR;
8482+    gTRS[10] = ret_code;
8483+
8484+    jfloatArray bytes = env->NewFloatArray(11);
8485+    if(bytes != 0)
8486+    {
8487+        env->SetFloatArrayRegion(bytes, 0, 11, (jfloat*) gTRS);
8488+    }
8489+    return bytes;
8490+}
8491+
8492+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_setBlendingType(
8493+        JNIEnv* env, jobject thiz, jint type)
8494+{
8495+    blendingType = int(type);
8496+}
8497+
8498+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_setStripType(
8499+        JNIEnv* env, jobject thiz, jint type)
8500+{
8501+    stripType = int(type);
8502+}
8503+
8504+JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_reset(
8505+        JNIEnv* env, jobject thiz)
8506+{
8507+    frame_number_HR = 0;
8508+    frame_number_LR = 0;
8509+
8510+    gProgress[LR] = 0.0;
8511+    gProgress[HR] = 0.0;
8512+
8513+    gCancelComputation[LR] = false;
8514+    gCancelComputation[HR] = false;
8515+
8516+    Init(LR,MAX_FRAMES);
8517+}
8518+
8519+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_reportProgress(
8520+        JNIEnv* env, jobject thiz, jboolean hires, jboolean cancel_computation)
8521+{
8522+    if(bool(hires))
8523+        gCancelComputation[HR] = cancel_computation;
8524+    else
8525+        gCancelComputation[LR] = cancel_computation;
8526+
8527+    if(bool(hires))
8528+        return (jint) gProgress[HR];
8529+    else
8530+        return (jint) gProgress[LR];
8531+}
8532+
8533+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_createMosaic(
8534+        JNIEnv* env, jobject thiz, jboolean value)
8535+{
8536+    high_res = bool(value);
8537+
8538+    int ret;
8539+
8540+    if(high_res)
8541+    {
8542+        LOGV("createMosaic() - High-Res Mode");
8543+        double  t0, t1, time_c;
8544+
8545+        gProgress[HR] = 0.0;
8546+        t0 = now_ms();
8547+
8548+        Init(HR, frame_number_HR);
8549+
8550+        for(int k = 0; k < frame_number_HR; k++)
8551+        {
8552+            if (gCancelComputation[HR])
8553+                break;
8554+            AddFrame(HR, k, NULL);
8555+            gProgress[HR] += TIME_PERCENT_ALIGN/frame_number_HR;
8556+        }
8557+
8558+        if (gCancelComputation[HR])
8559+        {
8560+            ret = Mosaic::MOSAIC_RET_CANCELLED;
8561+        }
8562+        else
8563+        {
8564+            gProgress[HR] = TIME_PERCENT_ALIGN;
8565+
8566+            t1 = now_ms();
8567+            time_c = t1 - t0;
8568+            LOGV("AlignAll - %d frames [HR]: %g ms", frame_number_HR, time_c);
8569+
8570+            ret = Finalize(HR);
8571+
8572+            gProgress[HR] = 100.0;
8573+        }
8574+
8575+        high_res = false;
8576+    }
8577+    else
8578+    {
8579+        LOGV("createMosaic() - Low-Res Mode");
8580+        gProgress[LR] = TIME_PERCENT_ALIGN;
8581+
8582+        ret = Finalize(LR);
8583+
8584+        gProgress[LR] = 100.0;
8585+    }
8586+
8587+    return (jint) ret;
8588+}
8589+
8590+JNIEXPORT jintArray JNICALL Java_com_android_camera_panorama_Mosaic_getFinalMosaic(
8591+        JNIEnv* env, jobject thiz)
8592+{
8593+    int y,x;
8594+    int width = mosaicWidth;
8595+    int height = mosaicHeight;
8596+    int imageSize = width * height;
8597+
8598+    // Convert back to RGB24
8599+    resultBGR = ImageUtils::allocateImage(mosaicWidth, mosaicHeight,
8600+            ImageUtils::IMAGE_TYPE_NUM_CHANNELS);
8601+    ImageUtils::yvu2bgr(resultBGR, resultYVU, mosaicWidth, mosaicHeight);
8602+
8603+    LOGV("MosBytes: %d, W = %d, H = %d", imageSize, width, height);
8604+
8605+    int* image = new int[imageSize];
8606+    int* dims = new int[2];
8607+
8608+    for(y=0; y<height; y++)
8609+    {
8610+        for(x=0; x<width; x++)
8611+        {
8612+            image[y*width+x] = (0xFF<<24) | (resultBGR[y*width*3+x*3+2]<<16)|
8613+                    (resultBGR[y*width*3+x*3+1]<<8)| (resultBGR[y*width*3+x*3]);
8614+        }
8615+    }
8616+
8617+    dims[0] = width;
8618+    dims[1] = height;
8619+
8620+    ImageUtils::freeImage(resultBGR);
8621+
8622+    jintArray bytes = env->NewIntArray(imageSize+2);
8623+    if (bytes == 0) {
8624+        LOGE("Error in creating the image.");
8625+        delete[] image;
8626+        return 0;
8627+    }
8628+    env->SetIntArrayRegion(bytes, 0, imageSize, (jint*) image);
8629+    env->SetIntArrayRegion(bytes, imageSize, 2, (jint*) dims);
8630+    delete[] image;
8631+    delete[] dims;
8632+    return bytes;
8633+}
8634+
8635+JNIEXPORT jbyteArray JNICALL Java_com_android_camera_panorama_Mosaic_getFinalMosaicNV21(
8636+        JNIEnv* env, jobject thiz)
8637+{
8638+    int y,x;
8639+    int width;
8640+    int height;
8641+
8642+    width = mosaicWidth;
8643+    height = mosaicHeight;
8644+
8645+    int imageSize = 1.5*width * height;
8646+
8647+    // Convert YVU to NV21 format in-place
8648+    ImageType V = resultYVU+mosaicWidth*mosaicHeight;
8649+    ImageType U = V+mosaicWidth*mosaicHeight;
8650+    for(int j=0; j<mosaicHeight/2; j++)
8651+    {
8652+        for(int i=0; i<mosaicWidth; i+=2)
8653+        {
8654+            V[j*mosaicWidth+i] = V[(2*j)*mosaicWidth+i];        // V
8655+            V[j*mosaicWidth+i+1] = U[(2*j)*mosaicWidth+i];        // U
8656+        }
8657+    }
8658+
8659+    LOGV("MosBytes: %d, W = %d, H = %d", imageSize, width, height);
8660+
8661+    unsigned char* dims = new unsigned char[8];
8662+
8663+    dims[0] = (unsigned char)(width >> 24);
8664+    dims[1] = (unsigned char)(width >> 16);
8665+    dims[2] = (unsigned char)(width >> 8);
8666+    dims[3] = (unsigned char)width;
8667+
8668+    dims[4] = (unsigned char)(height >> 24);
8669+    dims[5] = (unsigned char)(height >> 16);
8670+    dims[6] = (unsigned char)(height >> 8);
8671+    dims[7] = (unsigned char)height;
8672+
8673+    jbyteArray bytes = env->NewByteArray(imageSize+8);
8674+    if (bytes == 0) {
8675+        LOGE("Error in creating the image.");
8676+        ImageUtils::freeImage(resultYVU);
8677+        return 0;
8678+    }
8679+    env->SetByteArrayRegion(bytes, 0, imageSize, (jbyte*) resultYVU);
8680+    env->SetByteArrayRegion(bytes, imageSize, 8, (jbyte*) dims);
8681+    delete[] dims;
8682+    ImageUtils::freeImage(resultYVU);
8683+    return bytes;
8684+}
8685+
8686+#ifdef __cplusplus
8687+}
8688+#endif
8689diff --git a/benchmark/feature_stab/db_vlvm/db_bundle.h b/benchmark/feature_stab/db_vlvm/db_bundle.h
8690new file mode 100644
8691index 00000000..e4fb8db2
8692--- /dev/null
8693+++ b/benchmark/feature_stab/db_vlvm/db_bundle.h
8694@@ -0,0 +1,68 @@
8695+/*
8696+ * Copyright (C) 2011 The Android Open Source Project
8697+ *
8698+ * Licensed under the Apache License, Version 2.0 (the "License");
8699+ * you may not use this file except in compliance with the License.
8700+ * You may obtain a copy of the License at
8701+ *
8702+ *      http://www.apache.org/licenses/LICENSE-2.0
8703+ *
8704+ * Unless required by applicable law or agreed to in writing, software
8705+ * distributed under the License is distributed on an "AS IS" BASIS,
8706+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8707+ * See the License for the specific language governing permissions and
8708+ * limitations under the License.
8709+ */
8710+
8711+/* $Id: db_bundle.h,v 1.2 2011/06/17 14:03:30 mbansal Exp $ */
8712+
8713+#ifndef DB_BUNDLE_H
8714+#define DB_BUNDLE_H
8715+
8716+
8717+/*****************************************************************
8718+*    Lean and mean begins here                                   *
8719+*****************************************************************/
8720+/*!
8721+ * \defgroup LMBundle (LM) Bundle adjustment utilities (a.k.a. Levenberg-Marquardt algorithm)
8722+ */
8723+/*\{*/
8724+
8725+#include "db_utilities.h"
8726+
8727+/*!
8728+Solve for update dx such that diagmult(1+lambda,transpose(J)%J)%dx= -Jtf
8729+using only upper half of JtJ, destroying lower half below diagonal in the process
8730+dimension is n and d should point to n allocated doubles of scratch memory
8731+*/
8732+inline void db_Compute_dx(double *dx,double **JtJ,double *min_Jtf,double lambda,double *d,int n)
8733+{
8734+    int i;
8735+    double opl;
8736+
8737+    opl=1.0+lambda;
8738+    for(i=0;i<n;i++) d[i]=JtJ[i][i]*opl;
8739+
8740+    db_CholeskyDecompSeparateDiagonal(JtJ,d,n);
8741+    db_CholeskyBacksub(dx,JtJ,d,n,min_Jtf);
8742+}
8743+
8744+/*!
8745+Solve for update dx such that diagmult(1+lambda,transpose(J)%J)%dx= -Jtf
8746+using only upper half of JtJ, destroying lower half below diagonal in the process
8747+*/
8748+inline void db_Compute_dx_3x3(double dx[3],double JtJ[9],const double min_Jtf[3],double lambda)
8749+{
8750+    double d[3],opl;
8751+
8752+    opl=1.0+lambda;
8753+    d[0]=JtJ[0]*opl;
8754+    d[1]=JtJ[4]*opl;
8755+    d[2]=JtJ[8]*opl;
8756+    db_CholeskyDecomp3x3SeparateDiagonal(JtJ,d);
8757+    db_CholeskyBacksub3x3(dx,JtJ,d,min_Jtf);
8758+}
8759+
8760+/*\}*/
8761+
8762+#endif /* DB_BUNDLE_H */
8763diff --git a/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp b/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp
8764new file mode 100644
8765index 00000000..28cb4a78
8766--- /dev/null
8767+++ b/benchmark/feature_stab/db_vlvm/db_feature_detection.cpp
8768@@ -0,0 +1,1770 @@
8769+/*
8770+ * Copyright (C) 2011 The Android Open Source Project
8771+ *
8772+ * Licensed under the Apache License, Version 2.0 (the "License");
8773+ * you may not use this file except in compliance with the License.
8774+ * You may obtain a copy of the License at
8775+ *
8776+ *      http://www.apache.org/licenses/LICENSE-2.0
8777+ *
8778+ * Unless required by applicable law or agreed to in writing, software
8779+ * distributed under the License is distributed on an "AS IS" BASIS,
8780+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8781+ * See the License for the specific language governing permissions and
8782+ * limitations under the License.
8783+ */
8784+
8785+/*$Id: db_feature_detection.cpp,v 1.4 2011/06/17 14:03:30 mbansal Exp $*/
8786+
8787+/*****************************************************************
8788+*    Lean and mean begins here                                   *
8789+*****************************************************************/
8790+
8791+#include "db_utilities.h"
8792+#include "db_feature_detection.h"
8793+#ifdef _VERBOSE_
8794+#include <iostream>
8795+#endif
8796+#include <float.h>
8797+
8798+#define DB_SUB_PIXEL
8799+
8800+#define BORDER 10 // 5
8801+
8802+float** db_AllocStrengthImage_f(float **im,int w,int h)
8803+{
8804+    int i,n,aw;
8805+    long c,size;
8806+    float **img,*aim,*p;
8807+
8808+    /*Determine number of 124 element chunks needed*/
8809+    n=(db_maxi(1,w-6)+123)/124;
8810+    /*Determine the total allocation width aw*/
8811+    aw=n*124+8;
8812+    /*Allocate*/
8813+    size=aw*h+16;
8814+    *im=new float [size];
8815+    /*Clean up*/
8816+    p=(*im);
8817+    for(c=0;c<size;c++) p[c]=0.0;
8818+    /*Get a 16 byte aligned pointer*/
8819+    aim=db_AlignPointer_f(*im,16);
8820+    /*Allocate pointer table*/
8821+    img=new float* [h];
8822+    /*Initialize the pointer table*/
8823+    for(i=0;i<h;i++)
8824+    {
8825+        img[i]=aim+aw*i+1;
8826+    }
8827+
8828+    return(img);
8829+}
8830+
8831+void db_FreeStrengthImage_f(float *im,float **img,int h)
8832+{
8833+    delete [] im;
8834+    delete [] img;
8835+}
8836+
8837+/*Compute derivatives Ix,Iy for a subrow of img with upper left (i,j) and width chunk_width
8838+Memory references occur one pixel outside the subrow*/
8839+inline void db_IxIyRow_f(float *Ix,float *Iy,const float * const *img,int i,int j,int chunk_width)
8840+{
8841+    int c;
8842+
8843+    for(c=0;c<chunk_width;c++)
8844+    {
8845+        Ix[c]=img[i][j+c-1]-img[i][j+c+1];
8846+        Iy[c]=img[i-1][j+c]-img[i+1][j+c];
8847+    }
8848+}
8849+
8850+/*Compute derivatives Ix,Iy for a subrow of img with upper left (i,j) and width 128
8851+Memory references occur one pixel outside the subrow*/
8852+inline void db_IxIyRow_u(int *dxx,const unsigned char * const *img,int i,int j,int nc)
8853+{
8854+#ifdef DB_USE_MMX
8855+    const unsigned char *r1,*r2,*r3;
8856+
8857+    r1=img[i-1]+j; r2=img[i]+j; r3=img[i+1]+j;
8858+
8859+    _asm
8860+    {
8861+        mov esi,16
8862+        mov eax,r1
8863+        mov ebx,r2
8864+        mov ecx,r3
8865+        mov edx,dxx
8866+
8867+        /*Get bitmask into mm7*/
8868+        mov       edi,7F7F7F7Fh
8869+        movd      mm7,edi
8870+        punpckldq mm7,mm7
8871+
8872+loopstart:
8873+        /***************dx part 1-12*********************************/
8874+        movq       mm0,[eax]       /*1 Get upper*/
8875+         pxor      mm6,mm6         /*2 Set to zero*/
8876+        movq       mm1,[ecx]       /*3 Get lower*/
8877+         psrlq     mm0,1           /*4 Shift*/
8878+        psrlq      mm1,1           /*5 Shift*/
8879+         pand      mm0,mm7         /*6 And*/
8880+        movq       mm2,[ebx-1]     /*13 Get left*/
8881+         pand      mm1,mm7         /*7 And*/
8882+        psubb      mm0,mm1         /*8 Subtract*/
8883+         pxor      mm5,mm5         /*14 Set to zero*/
8884+        movq       mm1,mm0         /*9 Copy*/
8885+         pcmpgtb   mm6,mm0         /*10 Create unpack mask*/
8886+        movq       mm3,[ebx+1]     /*15 Get right*/
8887+         punpcklbw mm0,mm6         /*11 Unpack low*/
8888+        punpckhbw  mm1,mm6         /*12 Unpack high*/
8889+        /***************dy part 13-24*********************************/
8890+         movq      mm4,mm0         /*25 Copy dx*/
8891+        psrlq      mm2,1           /*16 Shift*/
8892+         pmullw    mm0,mm0         /*26 Multiply dx*dx*/
8893+        psrlq      mm3,1           /*17 Shift*/
8894+         pand      mm2,mm7         /*18 And*/
8895+        pand       mm3,mm7         /*19 And*/
8896+         /*Stall*/
8897+        psubb      mm2,mm3         /*20 Subtract*/
8898+         /*Stall*/
8899+        movq       mm3,mm2         /*21 Copy*/
8900+         pcmpgtb   mm5,mm2         /*22 Create unpack mask*/
8901+        punpcklbw  mm2,mm5         /*23 Unpack low*/
8902+         /*Stall*/
8903+        punpckhbw  mm3,mm5         /*24 Unpack high*/
8904+        /***************dxx dxy dyy low part 25-49*********************************/
8905+         pmullw    mm4,mm2         /*27 Multiply dx*dy*/
8906+        pmullw     mm2,mm2         /*28 Multiply dy*dy*/
8907+         pxor      mm6,mm6         /*29 Set to zero*/
8908+        movq       mm5,mm0         /*30 Copy dx*dx*/
8909+         pcmpgtw   mm6,mm0         /*31 Create unpack mask for dx*dx*/
8910+        punpcklwd  mm0,mm6         /*32 Unpack dx*dx lows*/
8911+         /*Stall*/
8912+        punpckhwd  mm5,mm6         /*33 Unpack dx*dx highs*/
8913+         pxor      mm6,mm6         /*36 Set to zero*/
8914+        movq       [edx],mm0       /*34 Store dx*dx lows*/
8915+         movq      mm0,mm4         /*37 Copy dx*dy*/
8916+        movq       [edx+8],mm5     /*35 Store dx*dx highs*/
8917+         pcmpgtw   mm6,mm4         /*38 Create unpack mask for dx*dy*/
8918+        punpcklwd  mm4,mm6         /*39 Unpack dx*dy lows*/
8919+         /*Stall*/
8920+        punpckhwd  mm0,mm6         /*40 Unpack dx*dy highs*/
8921+         pxor      mm6,mm6         /*43 Set to zero*/
8922+        movq       [edx+512],mm4   /*41 Store dx*dy lows*/
8923+         movq      mm5,mm2         /*44 Copy dy*dy*/
8924+        movq       [edx+520],mm0   /*42 Store dx*dy highs*/
8925+         pcmpgtw   mm6,mm2         /*45 Create unpack mask for dy*dy*/
8926+        punpcklwd  mm2,mm6         /*46 Unpack dy*dy lows*/
8927+         movq      mm4,mm1         /*50 Copy dx*/
8928+        punpckhwd  mm5,mm6         /*47 Unpack dy*dy highs*/
8929+         pmullw    mm1,mm1         /*51 Multiply dx*dx*/
8930+        movq       [edx+1024],mm2  /*48 Store dy*dy lows*/
8931+         pmullw    mm4,mm3         /*52 Multiply dx*dy*/
8932+        movq       [edx+1032],mm5  /*49 Store dy*dy highs*/
8933+        /***************dxx dxy dyy high part 50-79*********************************/
8934+         pmullw    mm3,mm3         /*53 Multiply dy*dy*/
8935+        pxor       mm6,mm6         /*54 Set to zero*/
8936+         movq      mm5,mm1         /*55 Copy dx*dx*/
8937+        pcmpgtw    mm6,mm1         /*56 Create unpack mask for dx*dx*/
8938+         pxor      mm2,mm2         /*61 Set to zero*/
8939+        punpcklwd  mm1,mm6         /*57 Unpack dx*dx lows*/
8940+         movq      mm0,mm4         /*62 Copy dx*dy*/
8941+        punpckhwd  mm5,mm6         /*58 Unpack dx*dx highs*/
8942+         pcmpgtw   mm2,mm4         /*63 Create unpack mask for dx*dy*/
8943+        movq       [edx+16],mm1    /*59 Store dx*dx lows*/
8944+         punpcklwd mm4,mm2         /*64 Unpack dx*dy lows*/
8945+        movq       [edx+24],mm5    /*60 Store dx*dx highs*/
8946+         punpckhwd mm0,mm2         /*65 Unpack dx*dy highs*/
8947+        movq       [edx+528],mm4   /*66 Store dx*dy lows*/
8948+         pxor      mm6,mm6         /*68 Set to zero*/
8949+        movq       [edx+536],mm0   /*67 Store dx*dy highs*/
8950+         movq      mm5,mm3         /*69 Copy dy*dy*/
8951+        pcmpgtw    mm6,mm3         /*70 Create unpack mask for dy*dy*/
8952+         add       eax,8           /*75*/
8953+        punpcklwd  mm3,mm6         /*71 Unpack dy*dy lows*/
8954+         add       ebx,8           /*76*/
8955+        punpckhwd  mm5,mm6         /*72 Unpack dy*dy highs*/
8956+         add       ecx,8           /*77*/
8957+        movq       [edx+1040],mm3  /*73 Store dy*dy lows*/
8958+         /*Stall*/
8959+        movq       [edx+1048],mm5  /*74 Store dy*dy highs*/
8960+         /*Stall*/
8961+        add        edx,32          /*78*/
8962+         dec esi                   /*79*/
8963+        jnz loopstart
8964+
8965+        emms
8966+    }
8967+
8968+#else
8969+    int c;
8970+    int Ix,Iy;
8971+
8972+    for(c=0;c<nc;c++)
8973+    {
8974+        Ix=(img[i][j+c-1]-img[i][j+c+1])>>1;
8975+        Iy=(img[i-1][j+c]-img[i+1][j+c])>>1;
8976+        dxx[c]=Ix*Ix;
8977+        dxx[c+128]=Ix*Iy;
8978+        dxx[c+256]=Iy*Iy;
8979+    }
8980+#endif /*DB_USE_MMX*/
8981+}
8982+
8983+/*Filter vertically five rows of derivatives of length chunk_width into gxx,gxy,gyy*/
8984+inline void db_gxx_gxy_gyy_row_f(float *gxx,float *gxy,float *gyy,int chunk_width,
8985+                                 float *Ix0,float *Ix1,float *Ix2,float *Ix3,float *Ix4,
8986+                                 float *Iy0,float *Iy1,float *Iy2,float *Iy3,float *Iy4)
8987+{
8988+    int c;
8989+    float dx,dy;
8990+    float Ixx0,Ixy0,Iyy0,Ixx1,Ixy1,Iyy1,Ixx2,Ixy2,Iyy2,Ixx3,Ixy3,Iyy3,Ixx4,Ixy4,Iyy4;
8991+
8992+    for(c=0;c<chunk_width;c++)
8993+    {
8994+        dx=Ix0[c];
8995+        dy=Iy0[c];
8996+        Ixx0=dx*dx;
8997+        Ixy0=dx*dy;
8998+        Iyy0=dy*dy;
8999+
9000+        dx=Ix1[c];
9001+        dy=Iy1[c];
9002+        Ixx1=dx*dx;
9003+        Ixy1=dx*dy;
9004+        Iyy1=dy*dy;
9005+
9006+        dx=Ix2[c];
9007+        dy=Iy2[c];
9008+        Ixx2=dx*dx;
9009+        Ixy2=dx*dy;
9010+        Iyy2=dy*dy;
9011+
9012+        dx=Ix3[c];
9013+        dy=Iy3[c];
9014+        Ixx3=dx*dx;
9015+        Ixy3=dx*dy;
9016+        Iyy3=dy*dy;
9017+
9018+        dx=Ix4[c];
9019+        dy=Iy4[c];
9020+        Ixx4=dx*dx;
9021+        Ixy4=dx*dy;
9022+        Iyy4=dy*dy;
9023+
9024+        /*Filter vertically*/
9025+        gxx[c]=Ixx0+Ixx1*4.0f+Ixx2*6.0f+Ixx3*4.0f+Ixx4;
9026+        gxy[c]=Ixy0+Ixy1*4.0f+Ixy2*6.0f+Ixy3*4.0f+Ixy4;
9027+        gyy[c]=Iyy0+Iyy1*4.0f+Iyy2*6.0f+Iyy3*4.0f+Iyy4;
9028+    }
9029+}
9030+
9031+/*Filter vertically five rows of derivatives of length 128 into gxx,gxy,gyy*/
9032+inline void db_gxx_gxy_gyy_row_s(int *g,int *d0,int *d1,int *d2,int *d3,int *d4,int nc)
9033+{
9034+#ifdef DB_USE_MMX
9035+    int c;
9036+
9037+    _asm
9038+    {
9039+        mov c,64
9040+        mov eax,d0
9041+        mov ebx,d1
9042+        mov ecx,d2
9043+        mov edx,d3
9044+        mov edi,d4
9045+        mov esi,g
9046+
9047+loopstart:
9048+        /***************dxx part 1-14*********************************/
9049+        movq        mm0,[eax]      /*1 Get dxx0*/
9050+         /*Stall*/
9051+        movq        mm1,[ebx]      /*2 Get dxx1*/
9052+         /*Stall*/
9053+        movq        mm2,[ecx]      /*5 Get dxx2*/
9054+         pslld      mm1,2          /*3 Shift dxx1*/
9055+        movq        mm3,[edx]      /*10 Get dxx3*/
9056+         paddd      mm0,mm1        /*4 Accumulate dxx1*/
9057+        movq        mm4,[eax+512]  /*15 Get dxy0*/
9058+         pslld      mm2,1          /*6 Shift dxx2 1*/
9059+        paddd       mm0,mm2        /*7 Accumulate dxx2 1*/
9060+         pslld      mm2,1          /*8 Shift dxx2 2*/
9061+        movq        mm5,[ebx+512]  /*16 Get dxy1*/
9062+         paddd      mm0,mm2        /*9 Accumulate dxx2 2*/
9063+        pslld       mm3,2          /*11 Shift dxx3*/
9064+         /*Stall*/
9065+        paddd       mm0,mm3        /*12 Accumulate dxx3*/
9066+         pslld      mm5,2          /*17 Shift dxy1*/
9067+        paddd       mm0,[edi]      /*13 Accumulate dxx4*/
9068+         paddd      mm4,mm5        /*18 Accumulate dxy1*/
9069+        movq        mm6,[ecx+512]  /*19 Get dxy2*/
9070+         /*Stall*/
9071+        movq        [esi],mm0      /*14 Store dxx sums*/
9072+        /***************dxy part 15-28*********************************/
9073+         pslld      mm6,1          /*20 Shift dxy2 1*/
9074+        paddd       mm4,mm6        /*21 Accumulate dxy2 1*/
9075+         pslld      mm6,1          /*22 Shift dxy2 2*/
9076+        movq        mm0,[eax+1024] /*29 Get dyy0*/
9077+         paddd      mm4,mm6        /*23 Accumulate dxy2 2*/
9078+        movq        mm7,[edx+512]  /*24 Get dxy3*/
9079+         pslld      mm7,2          /*25 Shift dxy3*/
9080+        movq        mm1,[ebx+1024] /*30 Get dyy1*/
9081+         paddd      mm4,mm7        /*26 Accumulate dxy3*/
9082+        paddd       mm4,[edi+512]  /*27 Accumulate dxy4*/
9083+         pslld      mm1,2          /*31 Shift dyy1*/
9084+        movq        mm2,[ecx+1024] /*33 Get dyy2*/
9085+         paddd      mm0,mm1        /*32 Accumulate dyy1*/
9086+        movq        [esi+512],mm4  /*28 Store dxy sums*/
9087+         pslld      mm2,1          /*34 Shift dyy2 1*/
9088+        /***************dyy part 29-49*********************************/
9089+
9090+
9091+        movq        mm3,[edx+1024] /*38 Get dyy3*/
9092+         paddd      mm0,mm2        /*35 Accumulate dyy2 1*/
9093+        paddd       mm0,[edi+1024] /*41 Accumulate dyy4*/
9094+         pslld      mm2,1          /*36 Shift dyy2 2*/
9095+        paddd       mm0,mm2        /*37 Accumulate dyy2 2*/
9096+         pslld      mm3,2          /*39 Shift dyy3*/
9097+        paddd       mm0,mm3        /*40 Accumulate dyy3*/
9098+         add        eax,8           /*43*/
9099+        add         ebx,8           /*44*/
9100+         add        ecx,8           /*45*/
9101+        movq        [esi+1024],mm0 /*42 Store dyy sums*/
9102+         /*Stall*/
9103+        add         edx,8           /*46*/
9104+         add        edi,8           /*47*/
9105+        add         esi,8           /*48*/
9106+         dec        c               /*49*/
9107+        jnz         loopstart
9108+
9109+        emms
9110+    }
9111+
9112+#else
9113+    int c,dd;
9114+
9115+    for(c=0;c<nc;c++)
9116+    {
9117+        /*Filter vertically*/
9118+        dd=d2[c];
9119+        g[c]=d0[c]+(d1[c]<<2)+(dd<<2)+(dd<<1)+(d3[c]<<2)+d4[c];
9120+
9121+        dd=d2[c+128];
9122+        g[c+128]=d0[c+128]+(d1[c+128]<<2)+(dd<<2)+(dd<<1)+(d3[c+128]<<2)+d4[c+128];
9123+
9124+        dd=d2[c+256];
9125+        g[c+256]=d0[c+256]+(d1[c+256]<<2)+(dd<<2)+(dd<<1)+(d3[c+256]<<2)+d4[c+256];
9126+    }
9127+#endif /*DB_USE_MMX*/
9128+}
9129+
9130+/*Filter horizontally the three rows gxx,gxy,gyy into the strength subrow starting at i,j
9131+and with width chunk_width. gxx,gxy and gyy are assumed to be four pixels wider than chunk_width
9132+and starting at (i,j-2)*/
9133+inline void db_HarrisStrength_row_f(float **s,float *gxx,float *gxy,float *gyy,int i,int j,int chunk_width)
9134+{
9135+    float Gxx,Gxy,Gyy,det,trc;
9136+    int c;
9137+
9138+    for(c=0;c<chunk_width;c++)
9139+    {
9140+        Gxx=gxx[c]+gxx[c+1]*4.0f+gxx[c+2]*6.0f+gxx[c+3]*4.0f+gxx[c+4];
9141+        Gxy=gxy[c]+gxy[c+1]*4.0f+gxy[c+2]*6.0f+gxy[c+3]*4.0f+gxy[c+4];
9142+        Gyy=gyy[c]+gyy[c+1]*4.0f+gyy[c+2]*6.0f+gyy[c+3]*4.0f+gyy[c+4];
9143+
9144+        det=Gxx*Gyy-Gxy*Gxy;
9145+        trc=Gxx+Gyy;
9146+        s[i][j+c]=det-0.06f*trc*trc;
9147+    }
9148+}
9149+
9150+/*Filter g of length 128 in place with 14641. Output is shifted two steps
9151+and of length 124*/
9152+inline void db_Filter14641_128_i(int *g,int nc)
9153+{
9154+#ifdef DB_USE_MMX
9155+    int mask;
9156+
9157+    mask=0xFFFFFFFF;
9158+    _asm
9159+    {
9160+        mov esi,31
9161+        mov eax,g
9162+
9163+        /*Get bitmask 00000000FFFFFFFF into mm7*/
9164+        movd mm7,mask
9165+
9166+        /*Warming iteration one 1-16********************/
9167+        movq       mm6,[eax]      /*1 Load new data*/
9168+        paddd      mm0,mm6        /*2 Add 1* behind two steps*/
9169+        movq       mm2,mm6        /*3 Start with 1* in front two steps*/
9170+        pslld      mm6,1          /*4*/
9171+        paddd      mm1,mm6        /*5 Add 2* same place*/
9172+        pslld      mm6,1          /*6*/
9173+        paddd      mm1,mm6        /*7 Add 4* same place*/
9174+        pshufw     mm6,mm6,4Eh    /*8 Swap the two double-words using bitmask 01001110=4Eh*/
9175+        paddd      mm1,mm6        /*9 Add 4* swapped*/
9176+        movq       mm5,mm6        /*10 Copy*/
9177+        pand       mm6,mm7        /*11 Get low double-word only*/
9178+        paddd      mm2,mm6        /*12 Add 4* in front one step*/
9179+        pxor       mm6,mm5        /*13 Get high double-word only*/
9180+        paddd      mm0,mm6        /*14 Add 4* behind one step*/
9181+        movq       mm0,mm1        /*15 Shift along*/
9182+        movq       mm1,mm2        /*16 Shift along*/
9183+        /*Warming iteration two 17-32********************/
9184+        movq       mm4,[eax+8]    /*17 Load new data*/
9185+        paddd      mm0,mm4        /*18 Add 1* behind two steps*/
9186+        movq       mm2,mm4        /*19 Start with 1* in front two steps*/
9187+        pslld      mm4,1          /*20*/
9188+        paddd      mm1,mm4        /*21 Add 2* same place*/
9189+        pslld      mm4,1          /*22*/
9190+        paddd      mm1,mm4        /*23 Add 4* same place*/
9191+        pshufw     mm4,mm4,4Eh    /*24 Swap the two double-words using bitmask 01001110=4Eh*/
9192+        paddd      mm1,mm4        /*25 Add 4* swapped*/
9193+        movq       mm3,mm4        /*26 Copy*/
9194+        pand       mm4,mm7        /*27 Get low double-word only*/
9195+        paddd      mm2,mm4        /*28 Add 4* in front one step*/
9196+        pxor       mm4,mm3        /*29 Get high double-word only*/
9197+        paddd      mm0,mm4        /*30 Add 4* behind one step*/
9198+        movq       mm0,mm1        /*31 Shift along*/
9199+        movq       mm1,mm2        /*32 Shift along*/
9200+
9201+        /*Loop********************/
9202+loopstart:
9203+        /*First part of loop 33-47********/
9204+        movq        mm6,[eax+16]   /*33 Load new data*/
9205+         /*Stall*/
9206+        paddd       mm0,mm6        /*34 Add 1* behind two steps*/
9207+         movq       mm2,mm6        /*35 Start with 1* in front two steps*/
9208+        movq        mm4,[eax+24]   /*48 Load new data*/
9209+         pslld      mm6,1          /*36*/
9210+        paddd       mm1,mm6        /*37 Add 2* same place*/
9211+         pslld      mm6,1          /*38*/
9212+        paddd       mm1,mm6        /*39 Add 4* same place*/
9213+         pshufw     mm6,mm6,4Eh    /*40 Swap the two double-words using bitmask 01001110=4Eh*/
9214+        paddd       mm1,mm4        /*49 Add 1* behind two steps*/
9215+         movq       mm5,mm6        /*41 Copy*/
9216+        paddd       mm1,mm6        /*42 Add 4* swapped*/
9217+         pand       mm6,mm7        /*43 Get low double-word only*/
9218+        paddd       mm2,mm6        /*44 Add 4* in front one step*/
9219+         pxor       mm6,mm5        /*45 Get high double-word only*/
9220+        paddd       mm0,mm6        /*46 Add 4* behind one step*/
9221+         movq       mm6,mm4        /*50a Copy*/
9222+        pslld       mm4,1          /*51*/
9223+         /*Stall*/
9224+        movq        [eax],mm0      /*47 Store result two steps behind*/
9225+        /*Second part of loop 48-66********/
9226+         movq       mm0,mm6        /*50b Start with 1* in front two steps*/
9227+        paddd       mm2,mm4        /*52 Add 2* same place*/
9228+         pslld      mm4,1          /*53*/
9229+        paddd       mm2,mm4        /*54 Add 4* same place*/
9230+         pshufw     mm4,mm4,4Eh    /*55 Swap the two double-words using bitmask 01001110=4Eh*/
9231+        paddd       mm2,mm4        /*56 Add 4* swapped*/
9232+         movq       mm3,mm4        /*57 Copy*/
9233+        pand        mm4,mm7        /*58 Get low double-word only*/
9234+         /*Stall*/
9235+        paddd       mm0,mm4        /*59 Add 4* in front one step*/
9236+         pxor       mm4,mm3        /*60 Get high double-word only*/
9237+        paddd       mm1,mm4        /*61 Add 4* behind one step*/
9238+         add        eax,16         /*65*/
9239+        dec         esi            /*66*/
9240+         /*Stall*/
9241+        movq        [eax-8],mm1    /*62 Store result two steps behind*/
9242+         movq       mm1,mm0        /*63 Shift along*/
9243+        movq        mm0,mm2        /*64 Shift along*/
9244+        jnz loopstart
9245+
9246+        emms
9247+    }
9248+
9249+#else
9250+    int c;
9251+
9252+    for(c=0;c<nc-4;c++)
9253+    {
9254+        g[c]=g[c]+(g[c+1]<<2)+(g[c+2]<<2)+(g[c+2]<<1)+(g[c+3]<<2)+g[c+4];
9255+    }
9256+#endif /*DB_USE_MMX*/
9257+}
9258+
9259+/*Filter horizontally the three rows gxx,gxy,gyy of length 128 into the strength subrow s
9260+of length 124. gxx,gxy and gyy are assumed to be starting at (i,j-2) if s[i][j] is sought.
9261+s should be 16 byte aligned*/
9262+inline void db_HarrisStrength_row_s(float *s,int *gxx,int *gxy,int *gyy,int nc)
9263+{
9264+    float k;
9265+
9266+    k=0.06f;
9267+
9268+    db_Filter14641_128_i(gxx,nc);
9269+    db_Filter14641_128_i(gxy,nc);
9270+    db_Filter14641_128_i(gyy,nc);
9271+
9272+#ifdef DB_USE_SIMD
9273+
9274+
9275+    _asm
9276+    {
9277+        mov esi,15
9278+        mov eax,gxx
9279+        mov ebx,gxy
9280+        mov ecx,gyy
9281+        mov edx,s
9282+
9283+        /*broadcast k to all positions of xmm7*/
9284+        movss   xmm7,k
9285+        shufps  xmm7,xmm7,0
9286+
9287+        /*****Warm up 1-10**************************************/
9288+        cvtpi2ps  xmm0,[eax+8] /*1 Convert two integers into floating point of low double-word*/
9289+         /*Stall*/
9290+        cvtpi2ps  xmm1,[ebx+8] /*4 Convert two integers into floating point of low double-word*/
9291+         movlhps  xmm0,xmm0    /*2 Move them to the high double-word*/
9292+        cvtpi2ps  xmm2,[ecx+8] /*7 Convert two integers into floating point of low double-word*/
9293+         movlhps  xmm1,xmm1    /*5 Move them to the high double-word*/
9294+        cvtpi2ps  xmm0,[eax]   /*3 Convert two integers into floating point of low double-word*/
9295+         movlhps  xmm2,xmm2    /*8 Move them to the high double-word*/
9296+        cvtpi2ps  xmm1,[ebx]   /*6 Convert two integers into floating point of low double-word*/
9297+         movaps   xmm3,xmm0    /*10 Copy Cxx*/
9298+        cvtpi2ps  xmm2,[ecx]   /*9 Convert two integers into floating point of low double-word*/
9299+         /*Stall*/
9300+loopstart:
9301+        /*****First part of loop 11-18***********************/
9302+        mulps     xmm0,xmm2     /*11 Multiply to get Gxx*Gyy*/
9303+         addps    xmm2,xmm3     /*12 Add to get Gxx+Gyy*/
9304+        cvtpi2ps  xmm4,[eax+24] /*19 Convert two integers into floating point of low double-word*/
9305+         mulps    xmm1,xmm1     /*13 Multiply to get Gxy*Gxy*/
9306+        mulps     xmm2,xmm2     /*14 Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/
9307+         movlhps  xmm4,xmm4     /*20 Move them to the high double-word*/
9308+        cvtpi2ps  xmm4,[eax+16] /*21 Convert two integers into floating point of low double-word*/
9309+         /*Stall*/
9310+        subps     xmm0,xmm1     /*15 Subtract to get Gxx*Gyy-Gxy*Gxy*/
9311+         mulps    xmm2,xmm7     /*16 Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/
9312+        cvtpi2ps  xmm5,[ebx+24] /*22 Convert two integers into floating point of low double-word*/
9313+         /*Stall*/
9314+        movlhps   xmm5,xmm5     /*23 Move them to the high double-word*/
9315+         /*Stall*/
9316+        cvtpi2ps  xmm5,[ebx+16] /*24 Convert two integers into floating point of low double-word*/
9317+         subps    xmm0,xmm2     /*17 Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/
9318+        cvtpi2ps  xmm6,[ecx+24] /*25 Convert two integers into floating point of low double-word*/
9319+         /*Stall*/
9320+        movaps    [edx],xmm0    /*18 Store*/
9321+        /*****Second part of loop 26-40***********************/
9322+         movlhps  xmm6,xmm6     /*26 Move them to the high double-word*/
9323+        cvtpi2ps  xmm6,[ecx+16] /*27 Convert two integers into floating point of low double-word*/
9324+         movaps   xmm3,xmm4     /*28 Copy Cxx*/
9325+        mulps     xmm4,xmm6     /*29 Multiply to get Gxx*Gyy*/
9326+         addps    xmm6,xmm3     /*30 Add to get Gxx+Gyy*/
9327+        cvtpi2ps  xmm0,[eax+40] /*(1 Next) Convert two integers into floating point of low double-word*/
9328+         mulps    xmm5,xmm5     /*31 Multiply to get Gxy*Gxy*/
9329+        cvtpi2ps  xmm1,[ebx+40] /*(4 Next) Convert two integers into floating point of low double-word*/
9330+         mulps    xmm6,xmm6     /*32 Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/
9331+        cvtpi2ps  xmm2,[ecx+40] /*(7 Next) Convert two integers into floating point of low double-word*/
9332+         movlhps  xmm0,xmm0     /*(2 Next) Move them to the high double-word*/
9333+        subps     xmm4,xmm5     /*33 Subtract to get Gxx*Gyy-Gxy*Gxy*/
9334+         movlhps  xmm1,xmm1     /*(5 Next) Move them to the high double-word*/
9335+        cvtpi2ps  xmm0,[eax+32] /*(3 Next)Convert two integers into floating point of low double-word*/
9336+         mulps    xmm6,xmm7     /*34 Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/
9337+        cvtpi2ps  xmm1,[ebx+32] /*(6 Next) Convert two integers into floating point of low double-word*/
9338+         movlhps  xmm2,xmm2     /*(8 Next) Move them to the high double-word*/
9339+        movaps    xmm3,xmm0     /*(10 Next) Copy Cxx*/
9340+         add      eax,32        /*37*/
9341+        subps     xmm4,xmm6     /*35 Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/
9342+         add      ebx,32        /*38*/
9343+        cvtpi2ps  xmm2,[ecx+32] /*(9 Next) Convert two integers into floating point of low double-word*/
9344+         /*Stall*/
9345+        movaps    [edx+16],xmm4 /*36 Store*/
9346+         /*Stall*/
9347+        add       ecx,32        /*39*/
9348+         add      edx,32        /*40*/
9349+        dec       esi           /*41*/
9350+        jnz loopstart
9351+
9352+        /****Cool down***************/
9353+        mulps    xmm0,xmm2    /*Multiply to get Gxx*Gyy*/
9354+        addps    xmm2,xmm3    /*Add to get Gxx+Gyy*/
9355+        mulps    xmm1,xmm1    /*Multiply to get Gxy*Gxy*/
9356+        mulps    xmm2,xmm2    /*Multiply to get (Gxx+Gyy)*(Gxx+Gyy)*/
9357+        subps    xmm0,xmm1    /*Subtract to get Gxx*Gyy-Gxy*Gxy*/
9358+        mulps    xmm2,xmm7    /*Multiply to get k*(Gxx+Gyy)*(Gxx+Gyy)*/
9359+        subps    xmm0,xmm2    /*Subtract to get Gxx*Gyy-Gxy*Gxy-k*(Gxx+Gyy)*(Gxx+Gyy)*/
9360+        movaps   [edx],xmm0   /*Store*/
9361+    }
9362+
9363+#else
9364+    float Gxx,Gxy,Gyy,det,trc;
9365+    int c;
9366+
9367+    //for(c=0;c<124;c++)
9368+    for(c=0;c<nc-4;c++)
9369+    {
9370+        Gxx=(float)gxx[c];
9371+        Gxy=(float)gxy[c];
9372+        Gyy=(float)gyy[c];
9373+
9374+        det=Gxx*Gyy-Gxy*Gxy;
9375+        trc=Gxx+Gyy;
9376+        s[c]=det-k*trc*trc;
9377+    }
9378+#endif /*DB_USE_SIMD*/
9379+}
9380+
9381+/*Compute the Harris corner strength of the chunk [left,top,right,bottom] of img and
9382+store it into the corresponding region of s. left and top have to be at least 3 and
9383+right and bottom have to be at most width-4,height-4*/
9384+inline void db_HarrisStrengthChunk_f(float **s,const float * const *img,int left,int top,int right,int bottom,
9385+                                      /*temp should point to at least
9386+                                      13*(right-left+5) of allocated memory*/
9387+                                      float *temp)
9388+{
9389+    float *Ix[5],*Iy[5];
9390+    float *gxx,*gxy,*gyy;
9391+    int i,chunk_width,chunk_width_p4;
9392+
9393+    chunk_width=right-left+1;
9394+    chunk_width_p4=chunk_width+4;
9395+    gxx=temp;
9396+    gxy=gxx+chunk_width_p4;
9397+    gyy=gxy+chunk_width_p4;
9398+    for(i=0;i<5;i++)
9399+    {
9400+        Ix[i]=gyy+chunk_width_p4+(2*i*chunk_width_p4);
9401+        Iy[i]=Ix[i]+chunk_width_p4;
9402+    }
9403+
9404+    /*Fill four rows of the wrap-around derivative buffers*/
9405+    for(i=top-2;i<top+2;i++) db_IxIyRow_f(Ix[i%5],Iy[i%5],img,i,left-2,chunk_width_p4);
9406+
9407+    /*For each output row*/
9408+    for(i=top;i<=bottom;i++)
9409+    {
9410+        /*Step the derivative buffers*/
9411+        db_IxIyRow_f(Ix[(i+2)%5],Iy[(i+2)%5],img,(i+2),left-2,chunk_width_p4);
9412+
9413+        /*Filter Ix2,IxIy,Iy2 vertically into gxx,gxy,gyy*/
9414+        db_gxx_gxy_gyy_row_f(gxx,gxy,gyy,chunk_width_p4,
9415+                                 Ix[(i-2)%5],Ix[(i-1)%5],Ix[i%5],Ix[(i+1)%5],Ix[(i+2)%5],
9416+                                 Iy[(i-2)%5],Iy[(i-1)%5],Iy[i%5],Iy[(i+1)%5],Iy[(i+2)%5]);
9417+
9418+        /*Filter gxx,gxy,gyy horizontally and compute corner response s*/
9419+        db_HarrisStrength_row_f(s,gxx,gxy,gyy,i,left,chunk_width);
9420+    }
9421+}
9422+
9423+/*Compute the Harris corner strength of the chunk [left,top,left+123,bottom] of img and
9424+store it into the corresponding region of s. left and top have to be at least 3 and
9425+right and bottom have to be at most width-4,height-4. The left of the region in s should
9426+be 16 byte aligned*/
9427+inline void db_HarrisStrengthChunk_u(float **s,const unsigned char * const *img,int left,int top,int bottom,
9428+                                      /*temp should point to at least
9429+                                      18*128 of allocated memory*/
9430+                                      int *temp, int nc)
9431+{
9432+    int *Ixx[5],*Ixy[5],*Iyy[5];
9433+    int *gxx,*gxy,*gyy;
9434+    int i;
9435+
9436+    gxx=temp;
9437+    gxy=gxx+128;
9438+    gyy=gxy+128;
9439+    for(i=0;i<5;i++)
9440+    {
9441+        Ixx[i]=gyy+(3*i+1)*128;
9442+        Ixy[i]=gyy+(3*i+2)*128;
9443+        Iyy[i]=gyy+(3*i+3)*128;
9444+    }
9445+
9446+    /*Fill four rows of the wrap-around derivative buffers*/
9447+    for(i=top-2;i<top+2;i++) db_IxIyRow_u(Ixx[i%5],img,i,left-2,nc);
9448+
9449+    /*For each output row*/
9450+    for(i=top;i<=bottom;i++)
9451+    {
9452+        /*Step the derivative buffers*/
9453+        db_IxIyRow_u(Ixx[(i+2)%5],img,(i+2),left-2,nc);
9454+
9455+        /*Filter Ix2,IxIy,Iy2 vertically into gxx,gxy,gyy*/
9456+        db_gxx_gxy_gyy_row_s(gxx,Ixx[(i-2)%5],Ixx[(i-1)%5],Ixx[i%5],Ixx[(i+1)%5],Ixx[(i+2)%5],nc);
9457+
9458+        /*Filter gxx,gxy,gyy horizontally and compute corner response s*/
9459+        db_HarrisStrength_row_s(s[i]+left,gxx,gxy,gyy,nc);
9460+    }
9461+
9462+}
9463+
9464+/*Compute Harris corner strength of img. Strength is returned for the region
9465+with (3,3) as upper left and (w-4,h-4) as lower right, positioned in the
9466+same place in s. In other words,image should be at least 7 pixels wide and 7 pixels high
9467+for a meaningful result*/
9468+void db_HarrisStrength_f(float **s,const float * const *img,int w,int h,
9469+                                    /*temp should point to at least
9470+                                    13*(chunk_width+4) of allocated memory*/
9471+                                    float *temp,
9472+                                    int chunk_width)
9473+{
9474+    int x,next_x,last,right;
9475+
9476+    last=w-4;
9477+    for(x=3;x<=last;x=next_x)
9478+    {
9479+        next_x=x+chunk_width;
9480+        right=next_x-1;
9481+        if(right>last) right=last;
9482+        /*Compute the Harris strength of a chunk*/
9483+        db_HarrisStrengthChunk_f(s,img,x,3,right,h-4,temp);
9484+    }
9485+}
9486+
9487+/*Compute Harris corner strength of img. Strength is returned for the region
9488+with (3,3) as upper left and (w-4,h-4) as lower right, positioned in the
9489+same place in s. In other words,image should be at least 7 pixels wide and 7 pixels high
9490+for a meaningful result.Moreover, the image should be overallocated by 256 bytes.
9491+s[i][3] should by 16 byte aligned for any i*/
9492+void db_HarrisStrength_u(float **s, const unsigned char * const *img,int w,int h,
9493+                                    /*temp should point to at least
9494+                                    18*128 of allocated memory*/
9495+                                    int *temp)
9496+{
9497+    int x,next_x,last;
9498+    int nc;
9499+
9500+    last=w-4;
9501+    for(x=3;x<=last;x=next_x)
9502+    {
9503+        next_x=x+124;
9504+
9505+        // mayban: to revert to the original full chunks state, change the line below to: nc = 128;
9506+        nc = db_mini(128,last-x+1);
9507+        //nc = 128;
9508+
9509+        /*Compute the Harris strength of a chunk*/
9510+        db_HarrisStrengthChunk_u(s,img,x,3,h-4,temp,nc);
9511+    }
9512+}
9513+
9514+inline float db_Max_128Aligned16_f(float *v)
9515+{
9516+#ifdef DB_USE_SIMD
9517+    float back;
9518+
9519+    _asm
9520+    {
9521+        mov eax,v
9522+
9523+        /*Chunk1*/
9524+        movaps xmm0,[eax]
9525+        movaps xmm1,[eax+16]
9526+        movaps xmm2,[eax+32]
9527+        movaps xmm3,[eax+48]
9528+        movaps xmm4,[eax+64]
9529+        movaps xmm5,[eax+80]
9530+        movaps xmm6,[eax+96]
9531+        movaps xmm7,[eax+112]
9532+
9533+        /*Chunk2*/
9534+        maxps xmm0,[eax+128]
9535+        maxps xmm1,[eax+144]
9536+        maxps xmm2,[eax+160]
9537+        maxps xmm3,[eax+176]
9538+        maxps xmm4,[eax+192]
9539+        maxps xmm5,[eax+208]
9540+        maxps xmm6,[eax+224]
9541+        maxps xmm7,[eax+240]
9542+
9543+        /*Chunk3*/
9544+        maxps xmm0,[eax+256]
9545+        maxps xmm1,[eax+272]
9546+        maxps xmm2,[eax+288]
9547+        maxps xmm3,[eax+304]
9548+        maxps xmm4,[eax+320]
9549+        maxps xmm5,[eax+336]
9550+        maxps xmm6,[eax+352]
9551+        maxps xmm7,[eax+368]
9552+
9553+        /*Chunk4*/
9554+        maxps xmm0,[eax+384]
9555+        maxps xmm1,[eax+400]
9556+        maxps xmm2,[eax+416]
9557+        maxps xmm3,[eax+432]
9558+        maxps xmm4,[eax+448]
9559+        maxps xmm5,[eax+464]
9560+        maxps xmm6,[eax+480]
9561+        maxps xmm7,[eax+496]
9562+
9563+        /*Collect*/
9564+        maxps   xmm0,xmm1
9565+        maxps   xmm2,xmm3
9566+        maxps   xmm4,xmm5
9567+        maxps   xmm6,xmm7
9568+        maxps   xmm0,xmm2
9569+        maxps   xmm4,xmm6
9570+        maxps   xmm0,xmm4
9571+        movhlps xmm1,xmm0
9572+        maxps   xmm0,xmm1
9573+        shufps  xmm1,xmm0,1
9574+        maxps   xmm0,xmm1
9575+        movss   back,xmm0
9576+    }
9577+
9578+    return(back);
9579+#else
9580+    float val,max_val;
9581+    float *p,*stop_p;
9582+    max_val=v[0];
9583+    for(p=v+1,stop_p=v+128;p!=stop_p;)
9584+    {
9585+        val= *p++;
9586+        if(val>max_val) max_val=val;
9587+    }
9588+    return(max_val);
9589+#endif /*DB_USE_SIMD*/
9590+}
9591+
9592+inline float db_Max_64Aligned16_f(float *v)
9593+{
9594+#ifdef DB_USE_SIMD
9595+    float back;
9596+
9597+    _asm
9598+    {
9599+        mov eax,v
9600+
9601+        /*Chunk1*/
9602+        movaps xmm0,[eax]
9603+        movaps xmm1,[eax+16]
9604+        movaps xmm2,[eax+32]
9605+        movaps xmm3,[eax+48]
9606+        movaps xmm4,[eax+64]
9607+        movaps xmm5,[eax+80]
9608+        movaps xmm6,[eax+96]
9609+        movaps xmm7,[eax+112]
9610+
9611+        /*Chunk2*/
9612+        maxps xmm0,[eax+128]
9613+        maxps xmm1,[eax+144]
9614+        maxps xmm2,[eax+160]
9615+        maxps xmm3,[eax+176]
9616+        maxps xmm4,[eax+192]
9617+        maxps xmm5,[eax+208]
9618+        maxps xmm6,[eax+224]
9619+        maxps xmm7,[eax+240]
9620+
9621+        /*Collect*/
9622+        maxps   xmm0,xmm1
9623+        maxps   xmm2,xmm3
9624+        maxps   xmm4,xmm5
9625+        maxps   xmm6,xmm7
9626+        maxps   xmm0,xmm2
9627+        maxps   xmm4,xmm6
9628+        maxps   xmm0,xmm4
9629+        movhlps xmm1,xmm0
9630+        maxps   xmm0,xmm1
9631+        shufps  xmm1,xmm0,1
9632+        maxps   xmm0,xmm1
9633+        movss   back,xmm0
9634+    }
9635+
9636+    return(back);
9637+#else
9638+    float val,max_val;
9639+    float *p,*stop_p;
9640+    max_val=v[0];
9641+    for(p=v+1,stop_p=v+64;p!=stop_p;)
9642+    {
9643+        val= *p++;
9644+        if(val>max_val) max_val=val;
9645+    }
9646+    return(max_val);
9647+#endif /*DB_USE_SIMD*/
9648+}
9649+
9650+inline float db_Max_32Aligned16_f(float *v)
9651+{
9652+#ifdef DB_USE_SIMD
9653+    float back;
9654+
9655+    _asm
9656+    {
9657+        mov eax,v
9658+
9659+        /*Chunk1*/
9660+        movaps xmm0,[eax]
9661+        movaps xmm1,[eax+16]
9662+        movaps xmm2,[eax+32]
9663+        movaps xmm3,[eax+48]
9664+        movaps xmm4,[eax+64]
9665+        movaps xmm5,[eax+80]
9666+        movaps xmm6,[eax+96]
9667+        movaps xmm7,[eax+112]
9668+
9669+        /*Collect*/
9670+        maxps   xmm0,xmm1
9671+        maxps   xmm2,xmm3
9672+        maxps   xmm4,xmm5
9673+        maxps   xmm6,xmm7
9674+        maxps   xmm0,xmm2
9675+        maxps   xmm4,xmm6
9676+        maxps   xmm0,xmm4
9677+        movhlps xmm1,xmm0
9678+        maxps   xmm0,xmm1
9679+        shufps  xmm1,xmm0,1
9680+        maxps   xmm0,xmm1
9681+        movss   back,xmm0
9682+    }
9683+
9684+    return(back);
9685+#else
9686+    float val,max_val;
9687+    float *p,*stop_p;
9688+    max_val=v[0];
9689+    for(p=v+1,stop_p=v+32;p!=stop_p;)
9690+    {
9691+        val= *p++;
9692+        if(val>max_val) max_val=val;
9693+    }
9694+    return(max_val);
9695+#endif /*DB_USE_SIMD*/
9696+}
9697+
9698+inline float db_Max_16Aligned16_f(float *v)
9699+{
9700+#ifdef DB_USE_SIMD
9701+    float back;
9702+
9703+    _asm
9704+    {
9705+        mov eax,v
9706+
9707+        /*Chunk1*/
9708+        movaps xmm0,[eax]
9709+        movaps xmm1,[eax+16]
9710+        movaps xmm2,[eax+32]
9711+        movaps xmm3,[eax+48]
9712+
9713+        /*Collect*/
9714+        maxps   xmm0,xmm1
9715+        maxps   xmm2,xmm3
9716+        maxps   xmm0,xmm2
9717+        movhlps xmm1,xmm0
9718+        maxps   xmm0,xmm1
9719+        shufps  xmm1,xmm0,1
9720+        maxps   xmm0,xmm1
9721+        movss   back,xmm0
9722+    }
9723+
9724+    return(back);
9725+#else
9726+    float val,max_val;
9727+    float *p,*stop_p;
9728+    max_val=v[0];
9729+    for(p=v+1,stop_p=v+16;p!=stop_p;)
9730+    {
9731+        val= *p++;
9732+        if(val>max_val) max_val=val;
9733+    }
9734+    return(max_val);
9735+#endif /*DB_USE_SIMD*/
9736+}
9737+
9738+inline float db_Max_8Aligned16_f(float *v)
9739+{
9740+#ifdef DB_USE_SIMD
9741+    float back;
9742+
9743+    _asm
9744+    {
9745+        mov eax,v
9746+
9747+        /*Chunk1*/
9748+        movaps xmm0,[eax]
9749+        movaps xmm1,[eax+16]
9750+
9751+        /*Collect*/
9752+        maxps   xmm0,xmm1
9753+        movhlps xmm1,xmm0
9754+        maxps   xmm0,xmm1
9755+        shufps  xmm1,xmm0,1
9756+        maxps   xmm0,xmm1
9757+        movss   back,xmm0
9758+    }
9759+
9760+    return(back);
9761+#else
9762+    float val,max_val;
9763+    float *p,*stop_p;
9764+    max_val=v[0];
9765+    for(p=v+1,stop_p=v+8;p!=stop_p;)
9766+    {
9767+        val= *p++;
9768+        if(val>max_val) max_val=val;
9769+    }
9770+    return(max_val);
9771+#endif /*DB_USE_SIMD*/
9772+}
9773+
9774+inline float db_Max_Aligned16_f(float *v,int size)
9775+{
9776+    float val,max_val;
9777+    float *stop_v;
9778+
9779+    max_val=v[0];
9780+    for(;size>=128;size-=128)
9781+    {
9782+        val=db_Max_128Aligned16_f(v);
9783+        v+=128;
9784+        if(val>max_val) max_val=val;
9785+    }
9786+    if(size&64)
9787+    {
9788+        val=db_Max_64Aligned16_f(v);
9789+        v+=64;
9790+        if(val>max_val) max_val=val;
9791+    }
9792+    if(size&32)
9793+    {
9794+        val=db_Max_32Aligned16_f(v);
9795+        v+=32;
9796+        if(val>max_val) max_val=val;
9797+    }
9798+    if(size&16)
9799+    {
9800+        val=db_Max_16Aligned16_f(v);
9801+        v+=16;
9802+        if(val>max_val) max_val=val;
9803+    }
9804+    if(size&8)
9805+    {
9806+        val=db_Max_8Aligned16_f(v);
9807+        v+=8;
9808+        if(val>max_val) max_val=val;
9809+    }
9810+    if(size&7)
9811+    {
9812+        for(stop_v=v+(size&7);v!=stop_v;)
9813+        {
9814+            val= *v++;
9815+            if(val>max_val) max_val=val;
9816+        }
9817+    }
9818+
9819+    return(max_val);
9820+}
9821+
9822+/*Find maximum value of img in the region starting at (left,top)
9823+and with width w and height h. img[left] should be 16 byte aligned*/
9824+float db_MaxImage_Aligned16_f(float **img,int left,int top,int w,int h)
9825+{
9826+    float val,max_val;
9827+    int i,stop_i;
9828+
9829+    if(w && h)
9830+    {
9831+        stop_i=top+h;
9832+        max_val=img[top][left];
9833+
9834+        for(i=top;i<stop_i;i++)
9835+        {
9836+            val=db_Max_Aligned16_f(img[i]+left,w);
9837+            if(val>max_val) max_val=val;
9838+        }
9839+        return(max_val);
9840+    }
9841+    return(0.0);
9842+}
9843+
9844+inline void db_MaxVector_128_Aligned16_f(float *m,float *v1,float *v2)
9845+{
9846+#ifdef DB_USE_SIMD
9847+    _asm
9848+    {
9849+        mov eax,v1
9850+        mov ebx,v2
9851+        mov ecx,m
9852+
9853+        /*Chunk1*/
9854+        movaps xmm0,[eax]
9855+        movaps xmm1,[eax+16]
9856+        movaps xmm2,[eax+32]
9857+        movaps xmm3,[eax+48]
9858+        movaps xmm4,[eax+64]
9859+        movaps xmm5,[eax+80]
9860+        movaps xmm6,[eax+96]
9861+        movaps xmm7,[eax+112]
9862+        maxps  xmm0,[ebx]
9863+        maxps  xmm1,[ebx+16]
9864+        maxps  xmm2,[ebx+32]
9865+        maxps  xmm3,[ebx+48]
9866+        maxps  xmm4,[ebx+64]
9867+        maxps  xmm5,[ebx+80]
9868+        maxps  xmm6,[ebx+96]
9869+        maxps  xmm7,[ebx+112]
9870+        movaps [ecx],xmm0
9871+        movaps [ecx+16],xmm1
9872+        movaps [ecx+32],xmm2
9873+        movaps [ecx+48],xmm3
9874+        movaps [ecx+64],xmm4
9875+        movaps [ecx+80],xmm5
9876+        movaps [ecx+96],xmm6
9877+        movaps [ecx+112],xmm7
9878+
9879+        /*Chunk2*/
9880+        movaps xmm0,[eax+128]
9881+        movaps xmm1,[eax+144]
9882+        movaps xmm2,[eax+160]
9883+        movaps xmm3,[eax+176]
9884+        movaps xmm4,[eax+192]
9885+        movaps xmm5,[eax+208]
9886+        movaps xmm6,[eax+224]
9887+        movaps xmm7,[eax+240]
9888+        maxps  xmm0,[ebx+128]
9889+        maxps  xmm1,[ebx+144]
9890+        maxps  xmm2,[ebx+160]
9891+        maxps  xmm3,[ebx+176]
9892+        maxps  xmm4,[ebx+192]
9893+        maxps  xmm5,[ebx+208]
9894+        maxps  xmm6,[ebx+224]
9895+        maxps  xmm7,[ebx+240]
9896+        movaps [ecx+128],xmm0
9897+        movaps [ecx+144],xmm1
9898+        movaps [ecx+160],xmm2
9899+        movaps [ecx+176],xmm3
9900+        movaps [ecx+192],xmm4
9901+        movaps [ecx+208],xmm5
9902+        movaps [ecx+224],xmm6
9903+        movaps [ecx+240],xmm7
9904+
9905+        /*Chunk3*/
9906+        movaps xmm0,[eax+256]
9907+        movaps xmm1,[eax+272]
9908+        movaps xmm2,[eax+288]
9909+        movaps xmm3,[eax+304]
9910+        movaps xmm4,[eax+320]
9911+        movaps xmm5,[eax+336]
9912+        movaps xmm6,[eax+352]
9913+        movaps xmm7,[eax+368]
9914+        maxps  xmm0,[ebx+256]
9915+        maxps  xmm1,[ebx+272]
9916+        maxps  xmm2,[ebx+288]
9917+        maxps  xmm3,[ebx+304]
9918+        maxps  xmm4,[ebx+320]
9919+        maxps  xmm5,[ebx+336]
9920+        maxps  xmm6,[ebx+352]
9921+        maxps  xmm7,[ebx+368]
9922+        movaps [ecx+256],xmm0
9923+        movaps [ecx+272],xmm1
9924+        movaps [ecx+288],xmm2
9925+        movaps [ecx+304],xmm3
9926+        movaps [ecx+320],xmm4
9927+        movaps [ecx+336],xmm5
9928+        movaps [ecx+352],xmm6
9929+        movaps [ecx+368],xmm7
9930+
9931+        /*Chunk4*/
9932+        movaps xmm0,[eax+384]
9933+        movaps xmm1,[eax+400]
9934+        movaps xmm2,[eax+416]
9935+        movaps xmm3,[eax+432]
9936+        movaps xmm4,[eax+448]
9937+        movaps xmm5,[eax+464]
9938+        movaps xmm6,[eax+480]
9939+        movaps xmm7,[eax+496]
9940+        maxps  xmm0,[ebx+384]
9941+        maxps  xmm1,[ebx+400]
9942+        maxps  xmm2,[ebx+416]
9943+        maxps  xmm3,[ebx+432]
9944+        maxps  xmm4,[ebx+448]
9945+        maxps  xmm5,[ebx+464]
9946+        maxps  xmm6,[ebx+480]
9947+        maxps  xmm7,[ebx+496]
9948+        movaps [ecx+384],xmm0
9949+        movaps [ecx+400],xmm1
9950+        movaps [ecx+416],xmm2
9951+        movaps [ecx+432],xmm3
9952+        movaps [ecx+448],xmm4
9953+        movaps [ecx+464],xmm5
9954+        movaps [ecx+480],xmm6
9955+        movaps [ecx+496],xmm7
9956+    }
9957+#else
9958+    int i;
9959+    float a,b;
9960+    for(i=0;i<128;i++)
9961+    {
9962+        a=v1[i];
9963+        b=v2[i];
9964+        if(a>=b) m[i]=a;
9965+        else m[i]=b;
9966+    }
9967+#endif /*DB_USE_SIMD*/
9968+}
9969+
9970+inline void db_MaxVector_128_SecondSourceDestAligned16_f(float *m,float *v1,float *v2)
9971+{
9972+#ifdef DB_USE_SIMD
9973+    _asm
9974+    {
9975+        mov eax,v1
9976+        mov ebx,v2
9977+        mov ecx,m
9978+
9979+        /*Chunk1*/
9980+        movups xmm0,[eax]
9981+        movups xmm1,[eax+16]
9982+        movups xmm2,[eax+32]
9983+        movups xmm3,[eax+48]
9984+        movups xmm4,[eax+64]
9985+        movups xmm5,[eax+80]
9986+        movups xmm6,[eax+96]
9987+        movups xmm7,[eax+112]
9988+        maxps  xmm0,[ebx]
9989+        maxps  xmm1,[ebx+16]
9990+        maxps  xmm2,[ebx+32]
9991+        maxps  xmm3,[ebx+48]
9992+        maxps  xmm4,[ebx+64]
9993+        maxps  xmm5,[ebx+80]
9994+        maxps  xmm6,[ebx+96]
9995+        maxps  xmm7,[ebx+112]
9996+        movaps [ecx],xmm0
9997+        movaps [ecx+16],xmm1
9998+        movaps [ecx+32],xmm2
9999+        movaps [ecx+48],xmm3
10000+        movaps [ecx+64],xmm4
10001+        movaps [ecx+80],xmm5
10002+        movaps [ecx+96],xmm6
10003+        movaps [ecx+112],xmm7
10004+
10005+        /*Chunk2*/
10006+        movups xmm0,[eax+128]
10007+        movups xmm1,[eax+144]
10008+        movups xmm2,[eax+160]
10009+        movups xmm3,[eax+176]
10010+        movups xmm4,[eax+192]
10011+        movups xmm5,[eax+208]
10012+        movups xmm6,[eax+224]
10013+        movups xmm7,[eax+240]
10014+        maxps  xmm0,[ebx+128]
10015+        maxps  xmm1,[ebx+144]
10016+        maxps  xmm2,[ebx+160]
10017+        maxps  xmm3,[ebx+176]
10018+        maxps  xmm4,[ebx+192]
10019+        maxps  xmm5,[ebx+208]
10020+        maxps  xmm6,[ebx+224]
10021+        maxps  xmm7,[ebx+240]
10022+        movaps [ecx+128],xmm0
10023+        movaps [ecx+144],xmm1
10024+        movaps [ecx+160],xmm2
10025+        movaps [ecx+176],xmm3
10026+        movaps [ecx+192],xmm4
10027+        movaps [ecx+208],xmm5
10028+        movaps [ecx+224],xmm6
10029+        movaps [ecx+240],xmm7
10030+
10031+        /*Chunk3*/
10032+        movups xmm0,[eax+256]
10033+        movups xmm1,[eax+272]
10034+        movups xmm2,[eax+288]
10035+        movups xmm3,[eax+304]
10036+        movups xmm4,[eax+320]
10037+        movups xmm5,[eax+336]
10038+        movups xmm6,[eax+352]
10039+        movups xmm7,[eax+368]
10040+        maxps  xmm0,[ebx+256]
10041+        maxps  xmm1,[ebx+272]
10042+        maxps  xmm2,[ebx+288]
10043+        maxps  xmm3,[ebx+304]
10044+        maxps  xmm4,[ebx+320]
10045+        maxps  xmm5,[ebx+336]
10046+        maxps  xmm6,[ebx+352]
10047+        maxps  xmm7,[ebx+368]
10048+        movaps [ecx+256],xmm0
10049+        movaps [ecx+272],xmm1
10050+        movaps [ecx+288],xmm2
10051+        movaps [ecx+304],xmm3
10052+        movaps [ecx+320],xmm4
10053+        movaps [ecx+336],xmm5
10054+        movaps [ecx+352],xmm6
10055+        movaps [ecx+368],xmm7
10056+
10057+        /*Chunk4*/
10058+        movups xmm0,[eax+384]
10059+        movups xmm1,[eax+400]
10060+        movups xmm2,[eax+416]
10061+        movups xmm3,[eax+432]
10062+        movups xmm4,[eax+448]
10063+        movups xmm5,[eax+464]
10064+        movups xmm6,[eax+480]
10065+        movups xmm7,[eax+496]
10066+        maxps  xmm0,[ebx+384]
10067+        maxps  xmm1,[ebx+400]
10068+        maxps  xmm2,[ebx+416]
10069+        maxps  xmm3,[ebx+432]
10070+        maxps  xmm4,[ebx+448]
10071+        maxps  xmm5,[ebx+464]
10072+        maxps  xmm6,[ebx+480]
10073+        maxps  xmm7,[ebx+496]
10074+        movaps [ecx+384],xmm0
10075+        movaps [ecx+400],xmm1
10076+        movaps [ecx+416],xmm2
10077+        movaps [ecx+432],xmm3
10078+        movaps [ecx+448],xmm4
10079+        movaps [ecx+464],xmm5
10080+        movaps [ecx+480],xmm6
10081+        movaps [ecx+496],xmm7
10082+    }
10083+#else
10084+    int i;
10085+    float a,b;
10086+    for(i=0;i<128;i++)
10087+    {
10088+        a=v1[i];
10089+        b=v2[i];
10090+        if(a>=b) m[i]=a;
10091+        else m[i]=b;
10092+    }
10093+#endif /*DB_USE_SIMD*/
10094+}
10095+
10096+/*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top), of width 124 and
10097+stopping at bottom. The output is shifted two steps left and overwrites 128 elements for each row.
10098+The input s should be of width at least 128, and exist for 2 pixels outside the specified region.
10099+s[i][left-2] and sf[i][left-2] should be 16 byte aligned. Top must be at least 3*/
10100+inline void db_MaxSuppressFilterChunk_5x5_Aligned16_f(float **sf,float **s,int left,int top,int bottom,
10101+                                      /*temp should point to at least
10102+                                      6*132 floats of 16-byte-aligned allocated memory*/
10103+                                      float *temp)
10104+{
10105+#ifdef DB_USE_SIMD
10106+    int i,lm2;
10107+    float *two[4];
10108+    float *four,*five;
10109+
10110+    lm2=left-2;
10111+
10112+    /*Set pointers to pre-allocated memory*/
10113+    four=temp;
10114+    five=four+132;
10115+    for(i=0;i<4;i++)
10116+    {
10117+        two[i]=five+(i+1)*132;
10118+    }
10119+
10120+    /*Set rests of four and five to zero to avoid
10121+    floating point exceptions*/
10122+    for(i=129;i<132;i++)
10123+    {
10124+        four[i]=0.0;
10125+        five[i]=0.0;
10126+    }
10127+
10128+    /*Fill three rows of the wrap-around max buffers*/
10129+    for(i=top-3;i<top;i++) db_MaxVector_128_Aligned16_f(two[i&3],s[i+1]+lm2,s[i+2]+lm2);
10130+
10131+    /*For each output row*/
10132+    for(;i<=bottom;i++)
10133+    {
10134+        /*Compute max of the lowest pair of rows in the five row window*/
10135+        db_MaxVector_128_Aligned16_f(two[i&3],s[i+1]+lm2,s[i+2]+lm2);
10136+        /*Compute max of the lowest and highest pair of rows in the five row window*/
10137+        db_MaxVector_128_Aligned16_f(four,two[i&3],two[(i-3)&3]);
10138+        /*Compute max of all rows*/
10139+        db_MaxVector_128_Aligned16_f(five,four,two[(i-1)&3]);
10140+        /*Compute max of 2x5 chunks*/
10141+        db_MaxVector_128_SecondSourceDestAligned16_f(five,five+1,five);
10142+        /*Compute max of pairs of 2x5 chunks*/
10143+        db_MaxVector_128_SecondSourceDestAligned16_f(five,five+3,five);
10144+        /*Compute max of pairs of 5x5 except middle*/
10145+        db_MaxVector_128_SecondSourceDestAligned16_f(sf[i]+lm2,four+2,five);
10146+    }
10147+
10148+#else
10149+    int i,j,right;
10150+    float sv;
10151+
10152+    right=left+128;
10153+    for(i=top;i<=bottom;i++) for(j=left;j<right;j++)
10154+    {
10155+        sv=s[i][j];
10156+
10157+        if( sv>s[i-2][j-2] && sv>s[i-2][j-1] && sv>s[i-2][j] && sv>s[i-2][j+1] && sv>s[i-2][j+2] &&
10158+            sv>s[i-1][j-2] && sv>s[i-1][j-1] && sv>s[i-1][j] && sv>s[i-1][j+1] && sv>s[i-1][j+2] &&
10159+            sv>s[  i][j-2] && sv>s[  i][j-1] &&                 sv>s[  i][j+1] && sv>s[  i][j+2] &&
10160+            sv>s[i+1][j-2] && sv>s[i+1][j-1] && sv>s[i+1][j] && sv>s[i+1][j+1] && sv>s[i+1][j+2] &&
10161+            sv>s[i+2][j-2] && sv>s[i+2][j-1] && sv>s[i+2][j] && sv>s[i+2][j+1] && sv>s[i+2][j+2])
10162+        {
10163+            sf[i][j-2]=0.0;
10164+        }
10165+        else sf[i][j-2]=sv;
10166+    }
10167+#endif /*DB_USE_SIMD*/
10168+}
10169+
10170+/*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top) and
10171+stopping at bottom. The output is shifted two steps left. The input s should exist for 2 pixels
10172+outside the specified region. s[i][left-2] and sf[i][left-2] should be 16 byte aligned.
10173+Top must be at least 3. Reading and writing from and to the input and output images is done
10174+as if the region had a width equal to a multiple of 124. If this is not the case, the images
10175+should be over-allocated and the input cleared for a sufficient region*/
10176+void db_MaxSuppressFilter_5x5_Aligned16_f(float **sf,float **s,int left,int top,int right,int bottom,
10177+                                          /*temp should point to at least
10178+                                          6*132 floats of 16-byte-aligned allocated memory*/
10179+                                          float *temp)
10180+{
10181+    int x,next_x;
10182+
10183+    for(x=left;x<=right;x=next_x)
10184+    {
10185+        next_x=x+124;
10186+        db_MaxSuppressFilterChunk_5x5_Aligned16_f(sf,s,x,top,bottom,temp);
10187+    }
10188+}
10189+
10190+/*Extract corners from the chunk (left,top) to (right,bottom). Store in x_temp,y_temp and s_temp
10191+which should point to space of at least as many positions as there are pixels in the chunk*/
10192+inline int db_CornersFromChunk(float **strength,int left,int top,int right,int bottom,float threshold,double *x_temp,double *y_temp,double *s_temp)
10193+{
10194+    int i,j,nr;
10195+    float s;
10196+
10197+    nr=0;
10198+    for(i=top;i<=bottom;i++) for(j=left;j<=right;j++)
10199+    {
10200+        s=strength[i][j];
10201+
10202+        if(s>=threshold &&
10203+            s>strength[i-2][j-2] && s>strength[i-2][j-1] && s>strength[i-2][j] && s>strength[i-2][j+1] && s>strength[i-2][j+2] &&
10204+            s>strength[i-1][j-2] && s>strength[i-1][j-1] && s>strength[i-1][j] && s>strength[i-1][j+1] && s>strength[i-1][j+2] &&
10205+            s>strength[  i][j-2] && s>strength[  i][j-1] &&                       s>strength[  i][j+1] && s>strength[  i][j+2] &&
10206+            s>strength[i+1][j-2] && s>strength[i+1][j-1] && s>strength[i+1][j] && s>strength[i+1][j+1] && s>strength[i+1][j+2] &&
10207+            s>strength[i+2][j-2] && s>strength[i+2][j-1] && s>strength[i+2][j] && s>strength[i+2][j+1] && s>strength[i+2][j+2])
10208+        {
10209+            x_temp[nr]=(double) j;
10210+            y_temp[nr]=(double) i;
10211+            s_temp[nr]=(double) s;
10212+            nr++;
10213+        }
10214+    }
10215+    return(nr);
10216+}
10217+
10218+
10219+//Sub-pixel accuracy using 2D quadratic interpolation.(YCJ)
10220+inline void db_SubPixel(float **strength, const double xd, const double yd, double &xs, double &ys)
10221+{
10222+    int x = (int) xd;
10223+    int y = (int) yd;
10224+
10225+    float fxx = strength[y][x-1] - strength[y][x] - strength[y][x] + strength[y][x+1];
10226+    float fyy = strength[y-1][x] - strength[y][x] - strength[y][x] + strength[y+1][x];
10227+    float fxy = (strength[y-1][x-1] - strength[y-1][x+1] - strength[y+1][x-1] + strength[y+1][x+1])/(float)4.0;
10228+
10229+    float denom = (fxx * fyy - fxy * fxy) * (float) 2.0;
10230+
10231+    xs = xd;
10232+    ys = yd;
10233+
10234+    if ( db_absf(denom) <= FLT_EPSILON )
10235+    {
10236+        return;
10237+    }
10238+    else
10239+    {
10240+        float fx = strength[y][x+1] - strength[y][x-1];
10241+        float fy = strength[y+1][x] - strength[y-1][x];
10242+
10243+        float dx = (fyy * fx - fxy * fy) / denom;
10244+        float dy = (fxx * fy - fxy * fx) / denom;
10245+
10246+        if ( db_absf(dx) > 1.0 || db_absf(dy) > 1.0 )
10247+        {
10248+            return;
10249+        }
10250+        else
10251+        {
10252+            xs -= dx;
10253+            ys -= dy;
10254+        }
10255+    }
10256+
10257+    return;
10258+}
10259+
10260+/*Extract corners from the image part from (left,top) to (right,bottom).
10261+Store in x and y, extracting at most satnr corners in each block of size (bw,bh).
10262+The pointer temp_d should point to at least 5*bw*bh positions.
10263+area_factor holds how many corners max to extract per 10000 pixels*/
10264+void db_ExtractCornersSaturated(float **strength,int left,int top,int right,int bottom,
10265+                                int bw,int bh,unsigned long area_factor,
10266+                                float threshold,double *temp_d,
10267+                                double *x_coord,double *y_coord,int *nr_corners)
10268+{
10269+    double *x_temp,*y_temp,*s_temp,*select_temp;
10270+    double loc_thresh;
10271+    unsigned long bwbh,area,saturation;
10272+    int x,next_x,last_x;
10273+    int y,next_y,last_y;
10274+    int nr,nr_points,i,stop;
10275+
10276+    bwbh=bw*bh;
10277+    x_temp=temp_d;
10278+    y_temp=x_temp+bwbh;
10279+    s_temp=y_temp+bwbh;
10280+    select_temp=s_temp+bwbh;
10281+
10282+#ifdef DB_SUB_PIXEL
10283+    // subpixel processing may sometimes push the corner ourside the real border
10284+    // increasing border size:
10285+    left++;
10286+    top++;
10287+    bottom--;
10288+    right--;
10289+#endif /*DB_SUB_PIXEL*/
10290+
10291+    nr_points=0;
10292+    for(y=top;y<=bottom;y=next_y)
10293+    {
10294+        next_y=y+bh;
10295+        last_y=next_y-1;
10296+        if(last_y>bottom) last_y=bottom;
10297+        for(x=left;x<=right;x=next_x)
10298+        {
10299+            next_x=x+bw;
10300+            last_x=next_x-1;
10301+            if(last_x>right) last_x=right;
10302+
10303+            area=(last_x-x+1)*(last_y-y+1);
10304+            saturation=(area*area_factor)/10000;
10305+            nr=db_CornersFromChunk(strength,x,y,last_x,last_y,threshold,x_temp,y_temp,s_temp);
10306+            if(nr)
10307+            {
10308+                if(((unsigned long)nr)>saturation) loc_thresh=db_LeanQuickSelect(s_temp,nr,nr-saturation,select_temp);
10309+                else loc_thresh=threshold;
10310+
10311+                stop=nr_points+saturation;
10312+                for(i=0;(i<nr)&&(nr_points<stop);i++)
10313+                {
10314+                    if(s_temp[i]>=loc_thresh)
10315+                    {
10316+                        #ifdef DB_SUB_PIXEL
10317+                               db_SubPixel(strength, x_temp[i], y_temp[i], x_coord[nr_points], y_coord[nr_points]);
10318+                        #else
10319+                               x_coord[nr_points]=x_temp[i];
10320+                               y_coord[nr_points]=y_temp[i];
10321+                        #endif
10322+
10323+                        nr_points++;
10324+                    }
10325+                }
10326+            }
10327+        }
10328+    }
10329+    *nr_corners=nr_points;
10330+}
10331+
10332+db_CornerDetector_f::db_CornerDetector_f()
10333+{
10334+    m_w=0; m_h=0;
10335+}
10336+
10337+db_CornerDetector_f::~db_CornerDetector_f()
10338+{
10339+    Clean();
10340+}
10341+
10342+void db_CornerDetector_f::Clean()
10343+{
10344+    if(m_w!=0)
10345+    {
10346+        delete [] m_temp_f;
10347+        delete [] m_temp_d;
10348+        db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h);
10349+    }
10350+    m_w=0; m_h=0;
10351+}
10352+
10353+unsigned long db_CornerDetector_f::Init(int im_width,int im_height,int target_nr_corners,
10354+                            int nr_horizontal_blocks,int nr_vertical_blocks,
10355+                            double absolute_threshold,double relative_threshold)
10356+{
10357+    int chunkwidth=208;
10358+    int block_width,block_height;
10359+    unsigned long area_factor;
10360+    int active_width,active_height;
10361+
10362+    active_width=db_maxi(1,im_width-10);
10363+    active_height=db_maxi(1,im_height-10);
10364+    block_width=db_maxi(1,active_width/nr_horizontal_blocks);
10365+    block_height=db_maxi(1,active_height/nr_vertical_blocks);
10366+
10367+    area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/
10368+        (((double)active_width)*((double)active_height)))));
10369+
10370+    return(Start(im_width,im_height,block_width,block_height,area_factor,
10371+        absolute_threshold,relative_threshold,chunkwidth));
10372+}
10373+
10374+unsigned long db_CornerDetector_f::Start(int im_width,int im_height,
10375+                             int block_width,int block_height,unsigned long area_factor,
10376+                             double absolute_threshold,double relative_threshold,int chunkwidth)
10377+{
10378+    Clean();
10379+
10380+    m_w=im_width;
10381+    m_h=im_height;
10382+    m_cw=chunkwidth;
10383+    m_bw=block_width;
10384+    m_bh=block_height;
10385+    m_area_factor=area_factor;
10386+    m_r_thresh=relative_threshold;
10387+    m_a_thresh=absolute_threshold;
10388+    m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000);
10389+
10390+    m_temp_f=new float[13*(m_cw+4)];
10391+    m_temp_d=new double[5*m_bw*m_bh];
10392+    m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h);
10393+
10394+    return(m_max_nr);
10395+}
10396+
10397+void db_CornerDetector_f::DetectCorners(const float * const *img,double *x_coord,double *y_coord,int *nr_corners) const
10398+{
10399+    float max_val,threshold;
10400+
10401+    db_HarrisStrength_f(m_strength,img,m_w,m_h,m_temp_f,m_cw);
10402+
10403+    if(m_r_thresh)
10404+    {
10405+        max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6);
10406+        threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh);
10407+    }
10408+    else threshold= (float) m_a_thresh;
10409+
10410+    db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold,
10411+        m_temp_d,x_coord,y_coord,nr_corners);
10412+}
10413+
10414+db_CornerDetector_u::db_CornerDetector_u()
10415+{
10416+    m_w=0; m_h=0;
10417+}
10418+
10419+db_CornerDetector_u::~db_CornerDetector_u()
10420+{
10421+    Clean();
10422+}
10423+
10424+db_CornerDetector_u::db_CornerDetector_u(const db_CornerDetector_u& cd)
10425+{
10426+    Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor,
10427+        cd.m_a_thresh, cd.m_r_thresh);
10428+}
10429+
10430+db_CornerDetector_u& db_CornerDetector_u::operator=(const db_CornerDetector_u& cd)
10431+{
10432+    if ( this == &cd ) return *this;
10433+
10434+    Clean();
10435+
10436+    Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor,
10437+        cd.m_a_thresh, cd.m_r_thresh);
10438+
10439+    return *this;
10440+}
10441+
10442+void db_CornerDetector_u::Clean()
10443+{
10444+    if(m_w!=0)
10445+    {
10446+        delete [] m_temp_i;
10447+        delete [] m_temp_d;
10448+        db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h);
10449+    }
10450+    m_w=0; m_h=0;
10451+}
10452+
10453+unsigned long db_CornerDetector_u::Init(int im_width,int im_height,int target_nr_corners,
10454+                            int nr_horizontal_blocks,int nr_vertical_blocks,
10455+                            double absolute_threshold,double relative_threshold)
10456+{
10457+    int block_width,block_height;
10458+    unsigned long area_factor;
10459+    int active_width,active_height;
10460+
10461+    active_width=db_maxi(1,im_width-10);
10462+    active_height=db_maxi(1,im_height-10);
10463+    block_width=db_maxi(1,active_width/nr_horizontal_blocks);
10464+    block_height=db_maxi(1,active_height/nr_vertical_blocks);
10465+
10466+    area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/
10467+        (((double)active_width)*((double)active_height)))));
10468+
10469+    return(Start(im_width,im_height,block_width,block_height,area_factor,
10470+        16.0*absolute_threshold,relative_threshold));
10471+}
10472+
10473+unsigned long db_CornerDetector_u::Start(int im_width,int im_height,
10474+                             int block_width,int block_height,unsigned long area_factor,
10475+                             double absolute_threshold,double relative_threshold)
10476+{
10477+    Clean();
10478+
10479+    m_w=im_width;
10480+    m_h=im_height;
10481+    m_bw=block_width;
10482+    m_bh=block_height;
10483+    m_area_factor=area_factor;
10484+    m_r_thresh=relative_threshold;
10485+    m_a_thresh=absolute_threshold;
10486+    m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000);
10487+
10488+    m_temp_i=new int[18*128];
10489+    m_temp_d=new double[5*m_bw*m_bh];
10490+    m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h);
10491+
10492+    return(m_max_nr);
10493+}
10494+
10495+void db_CornerDetector_u::DetectCorners(const unsigned char * const *img,double *x_coord,double *y_coord,int *nr_corners,
10496+                                        const unsigned char * const *msk, unsigned char fgnd) const
10497+{
10498+    float max_val,threshold;
10499+
10500+    db_HarrisStrength_u(m_strength,img,m_w,m_h,m_temp_i);
10501+
10502+
10503+    if(m_r_thresh)
10504+    {
10505+        max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6);
10506+        threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh);
10507+    }
10508+    else threshold= (float) m_a_thresh;
10509+
10510+    db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold,
10511+        m_temp_d,x_coord,y_coord,nr_corners);
10512+
10513+
10514+    if ( msk )
10515+    {
10516+        int nr_corners_mask=0;
10517+
10518+        for ( int i = 0; i < *nr_corners; ++i)
10519+        {
10520+            int cor_x = db_roundi(*(x_coord+i));
10521+            int cor_y = db_roundi(*(y_coord+i));
10522+            if ( msk[cor_y][cor_x] == fgnd )
10523+            {
10524+                x_coord[nr_corners_mask] = x_coord[i];
10525+                y_coord[nr_corners_mask] = y_coord[i];
10526+                nr_corners_mask++;
10527+            }
10528+        }
10529+        *nr_corners = nr_corners_mask;
10530+    }
10531+}
10532+
10533+void db_CornerDetector_u::ExtractCorners(float ** strength, double *x_coord, double *y_coord, int *nr_corners) {
10534+    if ( m_w!=0 )
10535+        db_ExtractCornersSaturated(strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,float(m_a_thresh),
10536+            m_temp_d,x_coord,y_coord,nr_corners);
10537+}
10538+
10539diff --git a/benchmark/feature_stab/db_vlvm/db_feature_detection.h b/benchmark/feature_stab/db_vlvm/db_feature_detection.h
10540new file mode 100644
10541index 00000000..68ffcc9a
10542--- /dev/null
10543+++ b/benchmark/feature_stab/db_vlvm/db_feature_detection.h
10544@@ -0,0 +1,179 @@
10545+/*
10546+ * Copyright (C) 2011 The Android Open Source Project
10547+ *
10548+ * Licensed under the Apache License, Version 2.0 (the "License");
10549+ * you may not use this file except in compliance with the License.
10550+ * You may obtain a copy of the License at
10551+ *
10552+ *      http://www.apache.org/licenses/LICENSE-2.0
10553+ *
10554+ * Unless required by applicable law or agreed to in writing, software
10555+ * distributed under the License is distributed on an "AS IS" BASIS,
10556+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10557+ * See the License for the specific language governing permissions and
10558+ * limitations under the License.
10559+ */
10560+
10561+/*$Id: db_feature_detection.h,v 1.3 2011/06/17 14:03:30 mbansal Exp $*/
10562+
10563+#ifndef DB_FEATURE_DETECTION_H
10564+#define DB_FEATURE_DETECTION_H
10565+
10566+/*****************************************************************
10567+*    Lean and mean begins here                                   *
10568+*****************************************************************/
10569+/*!
10570+ * \defgroup FeatureDetection Feature Detection
10571+ */
10572+#include "db_utilities.h"
10573+#include "db_utilities_constants.h"
10574+#include <stdlib.h> //for NULL
10575+
10576+/*!
10577+ * \class db_CornerDetector_f
10578+ * \ingroup FeatureDetection
10579+ * \brief Harris corner detector for float images.
10580+ *
10581+ *  This class performs Harris corner extraction on *float* images managed
10582+ * with functions in \ref LMImageBasicUtilities.
10583+ */
10584+class DB_API db_CornerDetector_f
10585+{
10586+public:
10587+    db_CornerDetector_f();
10588+    ~db_CornerDetector_f();
10589+
10590+    /*!
10591+     * Set parameters and pre-allocate memory. Return an upper bound
10592+     * on the number of corners detected in one frame.
10593+     * \param im_width      width
10594+     * \param im_height     height
10595+     * \param target_nr_corners
10596+     * \param nr_horizontal_blocks
10597+     * \param nr_vertical_blocks
10598+     * \param absolute_threshold
10599+     * \param relative_threshold
10600+     */
10601+    unsigned long Init(int im_width,int im_height,
10602+                            int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS,
10603+                            int nr_horizontal_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS,
10604+                            int nr_vertical_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS,
10605+                            double absolute_threshold=DB_DEFAULT_ABS_CORNER_THRESHOLD,
10606+                            double relative_threshold=DB_DEFAULT_REL_CORNER_THRESHOLD);
10607+
10608+    /*!
10609+     * Detect the corners.
10610+     * x_coord and y_coord should be pre-allocated arrays of length returned by Init().
10611+     * \param img   row array pointer
10612+     * \param x_coord   corner locations
10613+     * \param y_coord   corner locations
10614+     * \param nr_corners    actual number of corners computed
10615+     */
10616+    void DetectCorners(const float * const *img,double *x_coord,double *y_coord,int *nr_corners) const;
10617+    void SetAbsoluteThreshold(double a_thresh) { m_a_thresh = a_thresh; };
10618+    void SetRelativeThreshold(double r_thresh) { m_r_thresh = r_thresh; };
10619+protected:
10620+    void Clean();
10621+    unsigned long Start(int im_width,int im_height,
10622+            int block_width,int block_height,unsigned long area_factor,
10623+            double absolute_threshold,double relative_threshold,int chunkwidth);
10624+
10625+    int m_w,m_h,m_cw,m_bw,m_bh;
10626+    /*Area factor holds the maximum number of corners to detect
10627+    per 10000 pixels*/
10628+    unsigned long m_area_factor,m_max_nr;
10629+    double m_a_thresh,m_r_thresh;
10630+    float *m_temp_f;
10631+    double *m_temp_d;
10632+    float **m_strength,*m_strength_mem;
10633+};
10634+/*!
10635+ * \class db_CornerDetector_u
10636+ * \ingroup FeatureDetection
10637+ * \brief Harris corner detector for byte images.
10638+ *
10639+ *  This class performs Harris corner extraction on *byte* images managed
10640+ * with functions in \ref LMImageBasicUtilities.
10641+ */
10642+class DB_API db_CornerDetector_u
10643+{
10644+public:
10645+    db_CornerDetector_u();
10646+    virtual ~db_CornerDetector_u();
10647+
10648+    /*!
10649+     Copy ctor duplicates settings.
10650+     Memory is not copied.
10651+     */
10652+    db_CornerDetector_u(const db_CornerDetector_u& cd);
10653+    /*!
10654+     Assignment optor duplicates settings.
10655+     Memory not copied.
10656+     */
10657+    db_CornerDetector_u& operator=(const db_CornerDetector_u& cd);
10658+
10659+    /*!
10660+     * Set parameters and pre-allocate memory. Return an upper bound
10661+     * on the number of corners detected in one frame
10662+     */
10663+    virtual unsigned long Init(int im_width,int im_height,
10664+                            int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS,
10665+                            int nr_horizontal_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS,
10666+                            int nr_vertical_blocks=DB_DEFAULT_NR_FEATURE_BLOCKS,
10667+                            double absolute_threshold=DB_DEFAULT_ABS_CORNER_THRESHOLD,
10668+                            double relative_threshold=DB_DEFAULT_REL_CORNER_THRESHOLD);
10669+
10670+    /*!
10671+     * Detect the corners.
10672+     * Observe that the image should be overallocated by at least 256 bytes
10673+     * at the end.
10674+     * x_coord and y_coord should be pre-allocated arrays of length returned by Init().
10675+     * Specifying image mask will restrict corner output to foreground regions.
10676+     * Foreground value can be specified using fgnd. By default any >0 mask value
10677+     * is considered to be foreground
10678+     * \param img   row array pointer
10679+     * \param x_coord   corner locations
10680+     * \param y_coord   corner locations
10681+     * \param nr_corners    actual number of corners computed
10682+     * \param msk       row array pointer to mask image
10683+     * \param fgnd      foreground value in the mask
10684+     */
10685+    virtual void DetectCorners(const unsigned char * const *img,double *x_coord,double *y_coord,int *nr_corners,
10686+        const unsigned char * const * msk=NULL, unsigned char fgnd=255) const;
10687+
10688+    /*!
10689+     Set absolute feature threshold
10690+     */
10691+    virtual void SetAbsoluteThreshold(double a_thresh) { m_a_thresh = a_thresh; };
10692+    /*!
10693+     Set relative feature threshold
10694+     */
10695+    virtual void SetRelativeThreshold(double r_thresh) { m_r_thresh = r_thresh; };
10696+
10697+    /*!
10698+     Extract corners from a pre-computed strength image.
10699+     \param strength    Harris strength image
10700+     \param x_coord corner locations
10701+     \param y_coord corner locations
10702+     \param nr_corners  actual number of corners computed
10703+     */
10704+    virtual void ExtractCorners(float ** strength, double *x_coord, double *y_coord, int *nr_corners);
10705+protected:
10706+    virtual void Clean();
10707+    /*The absolute threshold to this function should be 16.0 times
10708+    normal*/
10709+    unsigned long Start(int im_width,int im_height,
10710+            int block_width,int block_height,unsigned long area_factor,
10711+            double absolute_threshold,double relative_threshold);
10712+
10713+    int m_w,m_h,m_bw,m_bh;
10714+    /*Area factor holds the maximum number of corners to detect
10715+    per 10000 pixels*/
10716+    unsigned long m_area_factor,m_max_nr;
10717+    double m_a_thresh,m_r_thresh;
10718+    int *m_temp_i;
10719+    double *m_temp_d;
10720+    float **m_strength,*m_strength_mem;
10721+};
10722+
10723+#endif /*DB_FEATURE_DETECTION_H*/
10724diff --git a/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp b/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp
10725new file mode 100644
10726index 00000000..891cac33
10727--- /dev/null
10728+++ b/benchmark/feature_stab/db_vlvm/db_feature_matching.cpp
10729@@ -0,0 +1,3409 @@
10730+/*
10731+ * Copyright (C) 2011 The Android Open Source Project
10732+ *
10733+ * Licensed under the Apache License, Version 2.0 (the "License");
10734+ * you may not use this file except in compliance with the License.
10735+ * You may obtain a copy of the License at
10736+ *
10737+ *      http://www.apache.org/licenses/LICENSE-2.0
10738+ *
10739+ * Unless required by applicable law or agreed to in writing, software
10740+ * distributed under the License is distributed on an "AS IS" BASIS,
10741+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10742+ * See the License for the specific language governing permissions and
10743+ * limitations under the License.
10744+ */
10745+
10746+/*$Id: db_feature_matching.cpp,v 1.4 2011/06/17 14:03:30 mbansal Exp $*/
10747+
10748+/*****************************************************************
10749+*    Lean and mean begins here                                   *
10750+*****************************************************************/
10751+
10752+#include "db_utilities.h"
10753+#include "db_feature_matching.h"
10754+#ifdef _VERBOSE_
10755+#include <iostream>
10756+#endif
10757+
10758+
10759+int AffineWarpPoint_NN_LUT_x[11][11];
10760+int AffineWarpPoint_NN_LUT_y[11][11];
10761+
10762+float AffineWarpPoint_BL_LUT_x[11][11];
10763+float AffineWarpPoint_BL_LUT_y[11][11];
10764+
10765+
10766+inline float db_SignedSquareNormCorr7x7_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g)
10767+{
10768+    unsigned char *pf,*pg;
10769+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
10770+    int xm_f,xm_g;
10771+
10772+    xm_f=x_f-3;
10773+    xm_g=x_g-3;
10774+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
10775+
10776+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
10777+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10778+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10779+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10780+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10781+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10782+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10783+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10784+
10785+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
10786+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10787+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10788+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10789+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10790+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10791+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10792+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10793+
10794+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
10795+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10796+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10797+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10798+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10799+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10800+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10801+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10802+
10803+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
10804+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10805+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10806+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10807+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10808+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10809+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10810+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10811+
10812+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
10813+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10814+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10815+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10816+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10817+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10818+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10819+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10820+
10821+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
10822+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10823+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10824+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10825+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10826+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10827+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10828+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10829+
10830+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
10831+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10832+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10833+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10834+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10835+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10836+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10837+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10838+
10839+    fg_corr=49.0f*fgsum-fsum*gsum;
10840+    den=(49.0f*f2sum-fsum*fsum)*(49.0f*g2sum-gsum*gsum);
10841+    if(den!=0.0)
10842+    {
10843+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
10844+        return(-fg_corr*fg_corr/den);
10845+    }
10846+    return(0.0);
10847+}
10848+
10849+inline float db_SignedSquareNormCorr9x9_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g)
10850+{
10851+    unsigned char *pf,*pg;
10852+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
10853+    int xm_f,xm_g;
10854+
10855+    xm_f=x_f-4;
10856+    xm_g=x_g-4;
10857+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
10858+
10859+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
10860+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10861+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10862+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10863+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10864+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10865+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10866+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10867+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10868+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10869+
10870+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
10871+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10872+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10873+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10874+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10875+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10876+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10877+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10878+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10879+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10880+
10881+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
10882+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10883+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10884+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10885+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10886+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10887+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10888+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10889+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10890+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10891+
10892+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
10893+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10894+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10895+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10896+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10897+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10898+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10899+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10900+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10901+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10902+
10903+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
10904+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10905+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10906+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10907+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10908+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10909+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10910+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10911+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10912+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10913+
10914+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
10915+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10916+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10917+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10918+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10919+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10920+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10921+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10922+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10923+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10924+
10925+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
10926+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10927+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10928+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10929+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10930+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10931+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10932+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10933+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10934+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10935+
10936+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
10937+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10938+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10939+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10940+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10941+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10942+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10943+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10944+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10945+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10946+
10947+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
10948+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10949+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10950+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10951+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10952+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10953+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10954+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10955+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10956+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10957+
10958+    fg_corr=81.0f*fgsum-fsum*gsum;
10959+    den=(81.0f*f2sum-fsum*fsum)*(81.0f*g2sum-gsum*gsum);
10960+    if(den!=0.0)
10961+    {
10962+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
10963+        return(-fg_corr*fg_corr/den);
10964+    }
10965+    return(0.0);
10966+}
10967+
10968+inline float db_SignedSquareNormCorr11x11_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g)
10969+{
10970+    unsigned char *pf,*pg;
10971+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
10972+    int xm_f,xm_g;
10973+
10974+    xm_f=x_f-5;
10975+    xm_g=x_g-5;
10976+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
10977+
10978+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
10979+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10980+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10981+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10982+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10983+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10984+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10985+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10986+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10987+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10988+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10989+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10990+
10991+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
10992+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10993+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10994+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10995+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10996+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10997+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10998+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
10999+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11000+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11001+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11002+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11003+
11004+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
11005+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11006+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11007+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11008+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11009+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11010+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11011+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11012+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11013+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11014+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11015+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11016+
11017+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
11018+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11019+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11020+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11021+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11022+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11023+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11024+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11025+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11026+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11027+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11028+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11029+
11030+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
11031+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11032+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11033+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11034+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11035+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11036+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11037+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11038+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11039+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11040+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11041+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11042+
11043+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
11044+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11045+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11046+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11047+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11048+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11049+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11050+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11051+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11052+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11053+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11054+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11055+
11056+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
11057+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11058+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11059+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11060+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11061+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11062+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11063+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11064+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11065+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11066+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11067+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11068+
11069+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
11070+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11071+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11072+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11073+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11074+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11075+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11076+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11077+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11078+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11079+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11080+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11081+
11082+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
11083+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11084+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11085+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11086+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11087+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11088+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11089+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11090+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11091+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11092+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11093+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11094+
11095+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
11096+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11097+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11098+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11099+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11100+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11101+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11102+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11103+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11104+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11105+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11106+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11107+
11108+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
11109+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11110+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11111+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11112+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11113+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11114+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11115+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11116+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11117+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11118+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11119+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
11120+
11121+    fg_corr=121.0f*fgsum-fsum*gsum;
11122+    den=(121.0f*f2sum-fsum*fsum)*(121.0f*g2sum-gsum*gsum);
11123+    if(den!=0.0)
11124+    {
11125+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
11126+        return(-fg_corr*fg_corr/den);
11127+    }
11128+    return(0.0);
11129+}
11130+
11131+inline void db_SignedSquareNormCorr11x11_Pre_u(unsigned char **f_img,int x_f,int y_f,float *sum,float *recip)
11132+{
11133+    unsigned char *pf;
11134+    float den;
11135+    int f,f2sum,fsum;
11136+    int xm_f;
11137+
11138+    xm_f=x_f-5;
11139+
11140+    pf=f_img[y_f-5]+xm_f;
11141+    f= *pf++; f2sum=f*f;  fsum=f;
11142+    f= *pf++; f2sum+=f*f; fsum+=f;
11143+    f= *pf++; f2sum+=f*f; fsum+=f;
11144+    f= *pf++; f2sum+=f*f; fsum+=f;
11145+    f= *pf++; f2sum+=f*f; fsum+=f;
11146+    f= *pf++; f2sum+=f*f; fsum+=f;
11147+    f= *pf++; f2sum+=f*f; fsum+=f;
11148+    f= *pf++; f2sum+=f*f; fsum+=f;
11149+    f= *pf++; f2sum+=f*f; fsum+=f;
11150+    f= *pf++; f2sum+=f*f; fsum+=f;
11151+    f= *pf;   f2sum+=f*f; fsum+=f;
11152+
11153+    pf=f_img[y_f-4]+xm_f;
11154+    f= *pf++; f2sum+=f*f; fsum+=f;
11155+    f= *pf++; f2sum+=f*f; fsum+=f;
11156+    f= *pf++; f2sum+=f*f; fsum+=f;
11157+    f= *pf++; f2sum+=f*f; fsum+=f;
11158+    f= *pf++; f2sum+=f*f; fsum+=f;
11159+    f= *pf++; f2sum+=f*f; fsum+=f;
11160+    f= *pf++; f2sum+=f*f; fsum+=f;
11161+    f= *pf++; f2sum+=f*f; fsum+=f;
11162+    f= *pf++; f2sum+=f*f; fsum+=f;
11163+    f= *pf++; f2sum+=f*f; fsum+=f;
11164+    f= *pf;   f2sum+=f*f; fsum+=f;
11165+
11166+    pf=f_img[y_f-3]+xm_f;
11167+    f= *pf++; f2sum+=f*f; fsum+=f;
11168+    f= *pf++; f2sum+=f*f; fsum+=f;
11169+    f= *pf++; f2sum+=f*f; fsum+=f;
11170+    f= *pf++; f2sum+=f*f; fsum+=f;
11171+    f= *pf++; f2sum+=f*f; fsum+=f;
11172+    f= *pf++; f2sum+=f*f; fsum+=f;
11173+    f= *pf++; f2sum+=f*f; fsum+=f;
11174+    f= *pf++; f2sum+=f*f; fsum+=f;
11175+    f= *pf++; f2sum+=f*f; fsum+=f;
11176+    f= *pf++; f2sum+=f*f; fsum+=f;
11177+    f= *pf;   f2sum+=f*f; fsum+=f;
11178+
11179+    pf=f_img[y_f-2]+xm_f;
11180+    f= *pf++; f2sum+=f*f; fsum+=f;
11181+    f= *pf++; f2sum+=f*f; fsum+=f;
11182+    f= *pf++; f2sum+=f*f; fsum+=f;
11183+    f= *pf++; f2sum+=f*f; fsum+=f;
11184+    f= *pf++; f2sum+=f*f; fsum+=f;
11185+    f= *pf++; f2sum+=f*f; fsum+=f;
11186+    f= *pf++; f2sum+=f*f; fsum+=f;
11187+    f= *pf++; f2sum+=f*f; fsum+=f;
11188+    f= *pf++; f2sum+=f*f; fsum+=f;
11189+    f= *pf++; f2sum+=f*f; fsum+=f;
11190+    f= *pf;   f2sum+=f*f; fsum+=f;
11191+
11192+    pf=f_img[y_f-1]+xm_f;
11193+    f= *pf++; f2sum+=f*f; fsum+=f;
11194+    f= *pf++; f2sum+=f*f; fsum+=f;
11195+    f= *pf++; f2sum+=f*f; fsum+=f;
11196+    f= *pf++; f2sum+=f*f; fsum+=f;
11197+    f= *pf++; f2sum+=f*f; fsum+=f;
11198+    f= *pf++; f2sum+=f*f; fsum+=f;
11199+    f= *pf++; f2sum+=f*f; fsum+=f;
11200+    f= *pf++; f2sum+=f*f; fsum+=f;
11201+    f= *pf++; f2sum+=f*f; fsum+=f;
11202+    f= *pf++; f2sum+=f*f; fsum+=f;
11203+    f= *pf;   f2sum+=f*f; fsum+=f;
11204+
11205+    pf=f_img[y_f]+xm_f;
11206+    f= *pf++; f2sum+=f*f; fsum+=f;
11207+    f= *pf++; f2sum+=f*f; fsum+=f;
11208+    f= *pf++; f2sum+=f*f; fsum+=f;
11209+    f= *pf++; f2sum+=f*f; fsum+=f;
11210+    f= *pf++; f2sum+=f*f; fsum+=f;
11211+    f= *pf++; f2sum+=f*f; fsum+=f;
11212+    f= *pf++; f2sum+=f*f; fsum+=f;
11213+    f= *pf++; f2sum+=f*f; fsum+=f;
11214+    f= *pf++; f2sum+=f*f; fsum+=f;
11215+    f= *pf++; f2sum+=f*f; fsum+=f;
11216+    f= *pf;   f2sum+=f*f; fsum+=f;
11217+
11218+    pf=f_img[y_f+1]+xm_f;
11219+    f= *pf++; f2sum+=f*f; fsum+=f;
11220+    f= *pf++; f2sum+=f*f; fsum+=f;
11221+    f= *pf++; f2sum+=f*f; fsum+=f;
11222+    f= *pf++; f2sum+=f*f; fsum+=f;
11223+    f= *pf++; f2sum+=f*f; fsum+=f;
11224+    f= *pf++; f2sum+=f*f; fsum+=f;
11225+    f= *pf++; f2sum+=f*f; fsum+=f;
11226+    f= *pf++; f2sum+=f*f; fsum+=f;
11227+    f= *pf++; f2sum+=f*f; fsum+=f;
11228+    f= *pf++; f2sum+=f*f; fsum+=f;
11229+    f= *pf;   f2sum+=f*f; fsum+=f;
11230+
11231+    pf=f_img[y_f+2]+xm_f;
11232+    f= *pf++; f2sum+=f*f; fsum+=f;
11233+    f= *pf++; f2sum+=f*f; fsum+=f;
11234+    f= *pf++; f2sum+=f*f; fsum+=f;
11235+    f= *pf++; f2sum+=f*f; fsum+=f;
11236+    f= *pf++; f2sum+=f*f; fsum+=f;
11237+    f= *pf++; f2sum+=f*f; fsum+=f;
11238+    f= *pf++; f2sum+=f*f; fsum+=f;
11239+    f= *pf++; f2sum+=f*f; fsum+=f;
11240+    f= *pf++; f2sum+=f*f; fsum+=f;
11241+    f= *pf++; f2sum+=f*f; fsum+=f;
11242+    f= *pf;   f2sum+=f*f; fsum+=f;
11243+
11244+    pf=f_img[y_f+3]+xm_f;
11245+    f= *pf++; f2sum+=f*f; fsum+=f;
11246+    f= *pf++; f2sum+=f*f; fsum+=f;
11247+    f= *pf++; f2sum+=f*f; fsum+=f;
11248+    f= *pf++; f2sum+=f*f; fsum+=f;
11249+    f= *pf++; f2sum+=f*f; fsum+=f;
11250+    f= *pf++; f2sum+=f*f; fsum+=f;
11251+    f= *pf++; f2sum+=f*f; fsum+=f;
11252+    f= *pf++; f2sum+=f*f; fsum+=f;
11253+    f= *pf++; f2sum+=f*f; fsum+=f;
11254+    f= *pf++; f2sum+=f*f; fsum+=f;
11255+    f= *pf;   f2sum+=f*f; fsum+=f;
11256+
11257+    pf=f_img[y_f+4]+xm_f;
11258+    f= *pf++; f2sum+=f*f; fsum+=f;
11259+    f= *pf++; f2sum+=f*f; fsum+=f;
11260+    f= *pf++; f2sum+=f*f; fsum+=f;
11261+    f= *pf++; f2sum+=f*f; fsum+=f;
11262+    f= *pf++; f2sum+=f*f; fsum+=f;
11263+    f= *pf++; f2sum+=f*f; fsum+=f;
11264+    f= *pf++; f2sum+=f*f; fsum+=f;
11265+    f= *pf++; f2sum+=f*f; fsum+=f;
11266+    f= *pf++; f2sum+=f*f; fsum+=f;
11267+    f= *pf++; f2sum+=f*f; fsum+=f;
11268+    f= *pf;   f2sum+=f*f; fsum+=f;
11269+
11270+    pf=f_img[y_f+5]+xm_f;
11271+    f= *pf++; f2sum+=f*f; fsum+=f;
11272+    f= *pf++; f2sum+=f*f; fsum+=f;
11273+    f= *pf++; f2sum+=f*f; fsum+=f;
11274+    f= *pf++; f2sum+=f*f; fsum+=f;
11275+    f= *pf++; f2sum+=f*f; fsum+=f;
11276+    f= *pf++; f2sum+=f*f; fsum+=f;
11277+    f= *pf++; f2sum+=f*f; fsum+=f;
11278+    f= *pf++; f2sum+=f*f; fsum+=f;
11279+    f= *pf++; f2sum+=f*f; fsum+=f;
11280+    f= *pf++; f2sum+=f*f; fsum+=f;
11281+    f= *pf;   f2sum+=f*f; fsum+=f;
11282+
11283+    *sum= (float) fsum;
11284+    den=(121.0f*f2sum-fsum*fsum);
11285+    *recip=(float)(((den!=0.0)?1.0/den:0.0));
11286+}
11287+
11288+inline void db_SignedSquareNormCorr5x5_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip)
11289+{
11290+    float den;
11291+    int f2sum,fsum;
11292+    int xm_f=x_f-2;
11293+
11294+#ifndef DB_USE_SSE2
11295+    const unsigned char *pf;
11296+    short f;
11297+
11298+    pf=f_img[y_f-2]+xm_f;
11299+    f= *pf++; f2sum=f*f; fsum=f; (*patch++)=f;
11300+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11301+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11302+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11303+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11304+
11305+    pf=f_img[y_f-1]+xm_f;
11306+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11307+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11308+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11309+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11310+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11311+
11312+    pf=f_img[y_f]+xm_f;
11313+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11314+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11315+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11316+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11317+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11318+
11319+    pf=f_img[y_f+1]+xm_f;
11320+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11321+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11322+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11323+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11324+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11325+
11326+    pf=f_img[y_f+2]+xm_f;
11327+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11328+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11329+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11330+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11331+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11332+    //int xwi;
11333+    //int ywi;
11334+    //f2sum=0;
11335+    //fsum=0;
11336+    //for (int r=-5;r<=5;r++){
11337+    //  ywi=y_f+r;
11338+    //  for (int c=-5;c<=5;c++){
11339+    //      xwi=x_f+c;
11340+    //      f=f_img[ywi][xwi];
11341+    //      f2sum+=f*f;
11342+    //      fsum+=f;
11343+    //      (*patch++)=f;
11344+    //  }
11345+    //}
11346+    (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0;
11347+    (*patch++)=0; (*patch++)=0;
11348+#endif /* DB_USE_SSE2 */
11349+
11350+    *sum= (float) fsum;
11351+    den=(25.0f*f2sum-fsum*fsum);
11352+    *recip= (float)((den!=0.0)?1.0/den:0.0);
11353+}
11354+
11355+inline void db_SignedSquareNormCorr21x21_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip)
11356+{
11357+    float den;
11358+    int f2sum,fsum;
11359+    short f;
11360+
11361+    int xwi;
11362+    int ywi;
11363+    f2sum=0;
11364+    fsum=0;
11365+    for (int r=-10;r<=10;r++){
11366+        ywi=y_f+r;
11367+        for (int c=-10;c<=10;c++){
11368+            xwi=x_f+c;
11369+            f=f_img[ywi][xwi];
11370+            f2sum+=f*f;
11371+            fsum+=f;
11372+            (*patch++)=f;
11373+        }
11374+    }
11375+
11376+    for(int i=442; i<512; i++)
11377+        (*patch++)=0;
11378+
11379+    *sum= (float) fsum;
11380+    den=(441.0f*f2sum-fsum*fsum);
11381+    *recip= (float)((den!=0.0)?1.0/den:0.0);
11382+
11383+
11384+}
11385+
11386+/* Lay out the image in the patch, computing norm and
11387+*/
11388+inline void db_SignedSquareNormCorr11x11_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip)
11389+{
11390+    float den;
11391+    int f2sum,fsum;
11392+    int xm_f=x_f-5;
11393+
11394+#ifndef DB_USE_SSE2
11395+    const unsigned char *pf;
11396+    short f;
11397+
11398+    pf=f_img[y_f-5]+xm_f;
11399+    f= *pf++; f2sum=f*f;  fsum=f;  (*patch++)=f;
11400+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11401+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11402+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11403+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11404+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11405+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11406+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11407+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11408+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11409+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11410+
11411+    pf=f_img[y_f-4]+xm_f;
11412+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11413+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11414+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11415+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11416+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11417+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11418+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11419+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11420+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11421+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11422+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11423+
11424+    pf=f_img[y_f-3]+xm_f;
11425+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11426+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11427+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11428+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11429+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11430+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11431+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11432+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11433+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11434+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11435+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11436+
11437+    pf=f_img[y_f-2]+xm_f;
11438+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11439+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11440+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11441+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11442+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11443+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11444+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11445+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11446+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11447+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11448+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11449+
11450+    pf=f_img[y_f-1]+xm_f;
11451+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11452+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11453+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11454+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11455+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11456+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11457+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11458+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11459+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11460+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11461+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11462+
11463+    pf=f_img[y_f]+xm_f;
11464+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11465+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11466+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11467+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11468+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11469+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11470+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11471+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11472+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11473+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11474+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11475+
11476+    pf=f_img[y_f+1]+xm_f;
11477+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11478+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11479+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11480+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11481+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11482+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11483+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11484+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11485+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11486+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11487+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11488+
11489+    pf=f_img[y_f+2]+xm_f;
11490+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11491+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11492+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11493+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11494+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11495+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11496+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11497+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11498+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11499+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11500+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11501+
11502+    pf=f_img[y_f+3]+xm_f;
11503+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11504+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11505+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11506+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11507+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11508+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11509+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11510+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11511+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11512+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11513+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11514+
11515+    pf=f_img[y_f+4]+xm_f;
11516+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11517+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11518+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11519+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11520+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11521+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11522+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11523+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11524+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11525+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11526+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11527+
11528+    pf=f_img[y_f+5]+xm_f;
11529+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11530+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11531+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11532+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11533+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11534+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11535+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11536+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11537+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11538+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
11539+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
11540+
11541+    //int xwi;
11542+    //int ywi;
11543+    //f2sum=0;
11544+    //fsum=0;
11545+    //for (int r=-5;r<=5;r++){
11546+    //  ywi=y_f+r;
11547+    //  for (int c=-5;c<=5;c++){
11548+    //      xwi=x_f+c;
11549+    //      f=f_img[ywi][xwi];
11550+    //      f2sum+=f*f;
11551+    //      fsum+=f;
11552+    //      (*patch++)=f;
11553+    //  }
11554+    //}
11555+
11556+    (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0;
11557+    (*patch++)=0; (*patch++)=0;
11558+#else
11559+    const unsigned char *pf0 =f_img[y_f-5]+xm_f;
11560+    const unsigned char *pf1 =f_img[y_f-4]+xm_f;
11561+    const unsigned char *pf2 =f_img[y_f-3]+xm_f;
11562+    const unsigned char *pf3 =f_img[y_f-2]+xm_f;
11563+    const unsigned char *pf4 =f_img[y_f-1]+xm_f;
11564+    const unsigned char *pf5 =f_img[y_f  ]+xm_f;
11565+    const unsigned char *pf6 =f_img[y_f+1]+xm_f;
11566+    const unsigned char *pf7 =f_img[y_f+2]+xm_f;
11567+    const unsigned char *pf8 =f_img[y_f+3]+xm_f;
11568+    const unsigned char *pf9 =f_img[y_f+4]+xm_f;
11569+    const unsigned char *pf10=f_img[y_f+5]+xm_f;
11570+
11571+    /* pixel mask */
11572+    const unsigned char pm[16] = {
11573+        0xFF,0xFF,
11574+        0xFF,0xFF,
11575+        0xFF,0xFF,
11576+        0,0,0,0,0,
11577+        0,0,0,0,0};
11578+    const unsigned char * pm_p = pm;
11579+
11580+    _asm
11581+    {
11582+        mov         ecx,patch   /* load patch pointer */
11583+        mov         ebx, pm_p   /* load pixel mask pointer */
11584+        movdqu      xmm1,[ebx]  /* load pixel mask */
11585+
11586+        pxor        xmm5,xmm5   /* set xmm5 to 0 accumulator for sum squares */
11587+        pxor        xmm4,xmm4   /* set xmm4 to 0 accumulator for sum */
11588+        pxor        xmm0,xmm0   /* set xmm0 to 0 */
11589+
11590+        /* row 0 */
11591+        mov         eax,pf0     /* load image pointer */
11592+        movdqu      xmm7,[eax]  /* load 16 pixels */
11593+        movdqa      xmm6,xmm7
11594+
11595+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11596+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11597+
11598+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11599+
11600+        movdqa      [ecx+0*22],xmm7 /* move short values to patch */
11601+        movdqa      [ecx+0*22+16],xmm6  /* move short values to patch */
11602+
11603+        paddusw     xmm4,xmm7   /* accumulate sums */
11604+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11605+        paddd       xmm5,xmm7   /* accumulate sum squares */
11606+
11607+        paddw       xmm4,xmm6   /* accumulate sums */
11608+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11609+        paddd       xmm5,xmm6   /* accumulate sum squares */
11610+
11611+        /* row 1 */
11612+        mov         eax,pf1     /* load image pointer */
11613+        movdqu      xmm7,[eax]  /* load 16 pixels */
11614+        movdqa      xmm6,xmm7
11615+
11616+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11617+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11618+
11619+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11620+
11621+        movdqu      [ecx+1*22],xmm7 /* move short values to patch */
11622+        movdqu      [ecx+1*22+16],xmm6  /* move short values to patch */
11623+
11624+        paddusw     xmm4,xmm7   /* accumulate sums */
11625+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11626+        paddd       xmm5,xmm7   /* accumulate sum squares */
11627+
11628+        paddw       xmm4,xmm6   /* accumulate sums */
11629+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11630+        paddd       xmm5,xmm6   /* accumulate sum squares */
11631+
11632+        /* row 2 */
11633+        mov         eax,pf2     /* load image pointer */
11634+        movdqu      xmm7,[eax]  /* load 16 pixels */
11635+        movdqa      xmm6,xmm7
11636+
11637+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11638+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11639+
11640+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11641+
11642+        movdqu      [ecx+2*22],xmm7 /* move short values to patch */
11643+        movdqu      [ecx+2*22+16],xmm6  /* move short values to patch */
11644+
11645+        paddusw     xmm4,xmm7   /* accumulate sums */
11646+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11647+        paddd       xmm5,xmm7   /* accumulate sum squares */
11648+
11649+        paddw       xmm4,xmm6   /* accumulate sums */
11650+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11651+        paddd       xmm5,xmm6   /* accumulate sum squares */
11652+
11653+        /* row 3 */
11654+        mov         eax,pf3     /* load image pointer */
11655+        movdqu      xmm7,[eax]  /* load 16 pixels */
11656+        movdqa      xmm6,xmm7
11657+
11658+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11659+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11660+
11661+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11662+
11663+        movdqu      [ecx+3*22],xmm7 /* move short values to patch */
11664+        movdqu      [ecx+3*22+16],xmm6  /* move short values to patch */
11665+
11666+        paddusw     xmm4,xmm7   /* accumulate sums */
11667+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11668+        paddd       xmm5,xmm7   /* accumulate sum squares */
11669+
11670+        paddw       xmm4,xmm6   /* accumulate sums */
11671+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11672+        paddd       xmm5,xmm6   /* accumulate sum squares */
11673+
11674+        /* row 4 */
11675+        mov         eax,pf4     /* load image pointer */
11676+        movdqu      xmm7,[eax]  /* load 16 pixels */
11677+        movdqa      xmm6,xmm7
11678+
11679+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11680+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11681+
11682+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11683+
11684+        movdqu      [ecx+4*22],xmm7 /* move short values to patch */
11685+        movdqu      [ecx+4*22+16],xmm6  /* move short values to patch */
11686+
11687+        paddusw     xmm4,xmm7   /* accumulate sums */
11688+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11689+        paddd       xmm5,xmm7   /* accumulate sum squares */
11690+
11691+        paddw       xmm4,xmm6   /* accumulate sums */
11692+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11693+        paddd       xmm5,xmm6   /* accumulate sum squares */
11694+
11695+        /* row 5 */
11696+        mov         eax,pf5     /* load image pointer */
11697+        movdqu      xmm7,[eax]  /* load 16 pixels */
11698+        movdqa      xmm6,xmm7
11699+
11700+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11701+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11702+
11703+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11704+
11705+        movdqu      [ecx+5*22],xmm7 /* move short values to patch */
11706+        movdqu      [ecx+5*22+16],xmm6  /* move short values to patch */
11707+
11708+        paddusw     xmm4,xmm7   /* accumulate sums */
11709+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11710+        paddd       xmm5,xmm7   /* accumulate sum squares */
11711+
11712+        paddw       xmm4,xmm6   /* accumulate sums */
11713+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11714+        paddd       xmm5,xmm6   /* accumulate sum squares */
11715+
11716+        /* row 6 */
11717+        mov         eax,pf6     /* load image pointer */
11718+        movdqu      xmm7,[eax]  /* load 16 pixels */
11719+        movdqa      xmm6,xmm7
11720+
11721+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11722+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11723+
11724+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11725+
11726+        movdqu      [ecx+6*22],xmm7 /* move short values to patch */
11727+        movdqu      [ecx+6*22+16],xmm6  /* move short values to patch */
11728+
11729+        paddusw     xmm4,xmm7   /* accumulate sums */
11730+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11731+        paddd       xmm5,xmm7   /* accumulate sum squares */
11732+
11733+        paddw       xmm4,xmm6   /* accumulate sums */
11734+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11735+        paddd       xmm5,xmm6   /* accumulate sum squares */
11736+
11737+        /* row 7 */
11738+        mov         eax,pf7     /* load image pointer */
11739+        movdqu      xmm7,[eax]  /* load 16 pixels */
11740+        movdqa      xmm6,xmm7
11741+
11742+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11743+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11744+
11745+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11746+
11747+        movdqu      [ecx+7*22],xmm7 /* move short values to patch */
11748+        movdqu      [ecx+7*22+16],xmm6  /* move short values to patch */
11749+
11750+        paddusw     xmm4,xmm7   /* accumulate sums */
11751+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11752+        paddd       xmm5,xmm7   /* accumulate sum squares */
11753+
11754+        paddw       xmm4,xmm6   /* accumulate sums */
11755+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11756+        paddd       xmm5,xmm6   /* accumulate sum squares */
11757+
11758+        /* row 8 */
11759+        mov         eax,pf8     /* load image pointer */
11760+        movdqu      xmm7,[eax]  /* load 16 pixels */
11761+        movdqa      xmm6,xmm7
11762+
11763+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11764+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11765+
11766+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11767+
11768+        movdqa      [ecx+8*22],xmm7 /* move short values to patch */
11769+        movdqa      [ecx+8*22+16],xmm6  /* move short values to patch */
11770+
11771+        paddusw     xmm4,xmm7   /* accumulate sums */
11772+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11773+        paddd       xmm5,xmm7   /* accumulate sum squares */
11774+
11775+        paddw       xmm4,xmm6   /* accumulate sums */
11776+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11777+        paddd       xmm5,xmm6   /* accumulate sum squares */
11778+
11779+        /* row 9 */
11780+        mov         eax,pf9     /* load image pointer */
11781+        movdqu      xmm7,[eax]  /* load 16 pixels */
11782+        movdqa      xmm6,xmm7
11783+
11784+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11785+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11786+
11787+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11788+
11789+        movdqu      [ecx+9*22],xmm7 /* move short values to patch */
11790+        movdqu      [ecx+9*22+16],xmm6  /* move short values to patch */
11791+
11792+        paddusw     xmm4,xmm7   /* accumulate sums */
11793+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11794+        paddd       xmm5,xmm7   /* accumulate sum squares */
11795+
11796+        paddw       xmm4,xmm6   /* accumulate sums */
11797+        pmaddwd     xmm6,xmm6   /* multiply 16 bit uints into 16 bit uints */
11798+        paddd       xmm5,xmm6   /* accumulate sum squares */
11799+
11800+        /* row 10 */
11801+        mov         eax,pf10    /* load image pointer */
11802+        movdqu      xmm7,[eax]  /* load 16 pixels */
11803+        movdqa      xmm6,xmm7
11804+
11805+        punpcklbw   xmm7,xmm0   /* unpack low pixels (first 8)*/
11806+        punpckhbw   xmm6,xmm0   /* unpack high pixels (last 8)*/
11807+
11808+        pand        xmm6,xmm1   /* mask out pixels 12-16 */
11809+
11810+        movdqu      [ecx+10*22],xmm7    /* move short values to patch */
11811+        movdqu      [ecx+10*22+16],xmm6 /* move short values to patch */
11812+
11813+        paddusw     xmm4,xmm7   /* accumulate sums */
11814+        pmaddwd     xmm7,xmm7   /* multiply 16 bit ints and add into 32 bit ints */
11815+        paddd       xmm5,xmm7   /* accumulate sum squares */
11816+
11817+        paddw       xmm4,xmm6   /* accumulate sums */
11818+        pmaddwd     xmm6,xmm6   /* multiply 16 bit ints and add into 32 bit ints */
11819+        paddd       xmm5,xmm6   /* accumulate sum squares */
11820+
11821+        /* add up the sum squares */
11822+        movhlps     xmm0,xmm5   /* high half to low half */
11823+        paddd       xmm5,xmm0   /* add high to low */
11824+        pshuflw     xmm0,xmm5, 0xE /* reshuffle */
11825+        paddd       xmm5,xmm0   /* add remaining */
11826+        movd        f2sum,xmm5
11827+
11828+        /* add up the sum */
11829+        movhlps     xmm0,xmm4
11830+        paddw       xmm4,xmm0   /* halves added */
11831+        pshuflw     xmm0,xmm4,0xE
11832+        paddw       xmm4,xmm0   /* quarters added */
11833+        pshuflw     xmm0,xmm4,0x1
11834+        paddw       xmm4,xmm0   /* eighth added */
11835+        movd        fsum, xmm4
11836+
11837+        emms
11838+    }
11839+
11840+    fsum = fsum & 0xFFFF;
11841+
11842+    patch[126] = 0;
11843+    patch[127] = 0;
11844+#endif /* DB_USE_SSE2 */
11845+
11846+    *sum= (float) fsum;
11847+    den=(121.0f*f2sum-fsum*fsum);
11848+    *recip= (float)((den!=0.0)?1.0/den:0.0);
11849+}
11850+
11851+void AffineWarpPointOffset(float &r_w,float &c_w,double Hinv[9],int r,int c)
11852+{
11853+    r_w=(float)(Hinv[3]*c+Hinv[4]*r);
11854+    c_w=(float)(Hinv[0]*c+Hinv[1]*r);
11855+}
11856+
11857+
11858+
11859+/*!
11860+Prewarp the patches with given affine transform. For a given homogeneous point "x", "H*x" is
11861+the warped point and for any displacement "d" in the warped image resulting in point "y", the
11862+corresponding point in the original image is given by "Hinv*y", which can be simplified for affine H.
11863+If "affine" is 1, then nearest neighbor method is used, else if it is 2, then
11864+bilinear method is used.
11865+ */
11866+inline void db_SignedSquareNormCorr11x11_PreAlign_AffinePatchWarp_u(short *patch,const unsigned char * const *f_img,
11867+                                                                    int xi,int yi,float *sum,float *recip,
11868+                                                                    const double Hinv[9],int affine)
11869+{
11870+    float den;
11871+    short f;
11872+    int f2sum,fsum;
11873+
11874+    f2sum=0;
11875+    fsum=0;
11876+
11877+    if (affine==1)
11878+    {
11879+        for (int r=0;r<11;r++){
11880+            for (int c=0;c<11;c++){
11881+                f=f_img[yi+AffineWarpPoint_NN_LUT_y[r][c]][xi+AffineWarpPoint_NN_LUT_x[r][c]];
11882+                f2sum+=f*f;
11883+                fsum+=f;
11884+                (*patch++)=f;
11885+            }
11886+        }
11887+    }
11888+    else if (affine==2)
11889+    {
11890+        for (int r=0;r<11;r++){
11891+            for (int c=0;c<11;c++){
11892+                f=db_BilinearInterpolation(yi+AffineWarpPoint_BL_LUT_y[r][c]
11893+                ,xi+AffineWarpPoint_BL_LUT_x[r][c],f_img);
11894+                f2sum+=f*f;
11895+                fsum+=f;
11896+                (*patch++)=f;
11897+            }
11898+        }
11899+    }
11900+
11901+
11902+
11903+    (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0; (*patch++)=0;
11904+    (*patch++)=0; (*patch++)=0;
11905+
11906+    *sum= (float) fsum;
11907+    den=(121.0f*f2sum-fsum*fsum);
11908+    *recip= (float)((den!=0.0)?1.0/den:0.0);
11909+}
11910+
11911+
11912+inline float db_SignedSquareNormCorr11x11_Post_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g,
11913+                                                float fsum_gsum,float f_recip_g_recip)
11914+{
11915+    unsigned char *pf,*pg;
11916+    int fgsum;
11917+    float fg_corr;
11918+    int xm_f,xm_g;
11919+
11920+    xm_f=x_f-5;
11921+    xm_g=x_g-5;
11922+
11923+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
11924+    fgsum=(*pf++)*(*pg++);  fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11925+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11926+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11927+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11928+
11929+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
11930+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11931+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11932+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11933+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11934+
11935+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
11936+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11937+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11938+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11939+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11940+
11941+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
11942+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11943+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11944+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11945+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11946+
11947+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
11948+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11949+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11950+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11951+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11952+
11953+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
11954+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11955+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11956+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11957+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11958+
11959+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
11960+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11961+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11962+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11963+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11964+
11965+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
11966+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11967+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11968+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11969+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11970+
11971+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
11972+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11973+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11974+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11975+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11976+
11977+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
11978+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11979+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11980+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11981+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11982+
11983+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
11984+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11985+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11986+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
11987+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
11988+
11989+    fg_corr=121.0f*fgsum-fsum_gsum;
11990+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
11991+    return(-fg_corr*fg_corr*f_recip_g_recip);
11992+}
11993+
11994+float db_SignedSquareNormCorr21x21Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip)
11995+{
11996+    float fgsum,fg_corr;
11997+
11998+    fgsum= (float) db_ScalarProduct512_s(f_patch,g_patch);
11999+
12000+    fg_corr=441.0f*fgsum-fsum_gsum;
12001+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
12002+    return(-fg_corr*fg_corr*f_recip_g_recip);
12003+}
12004+
12005+
12006+float db_SignedSquareNormCorr11x11Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip)
12007+{
12008+    float fgsum,fg_corr;
12009+
12010+    fgsum= (float) db_ScalarProduct128_s(f_patch,g_patch);
12011+
12012+    fg_corr=121.0f*fgsum-fsum_gsum;
12013+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
12014+    return(-fg_corr*fg_corr*f_recip_g_recip);
12015+}
12016+
12017+float db_SignedSquareNormCorr5x5Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip)
12018+{
12019+    float fgsum,fg_corr;
12020+
12021+    fgsum= (float) db_ScalarProduct32_s(f_patch,g_patch);
12022+
12023+    fg_corr=25.0f*fgsum-fsum_gsum;
12024+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
12025+    return(-fg_corr*fg_corr*f_recip_g_recip);
12026+}
12027+
12028+
12029+inline float db_SignedSquareNormCorr15x15_u(unsigned char **f_img,unsigned char **g_img,int x_f,int y_f,int x_g,int y_g)
12030+{
12031+    unsigned char *pf,*pg;
12032+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
12033+    int xm_f,xm_g;
12034+
12035+    xm_f=x_f-7;
12036+    xm_g=x_g-7;
12037+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
12038+
12039+    pf=f_img[y_f-7]+xm_f; pg=g_img[y_g-7]+xm_g;
12040+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12041+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12042+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12043+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12044+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12045+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12046+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12047+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12048+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12049+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12050+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12051+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12052+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12053+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12054+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12055+
12056+    pf=f_img[y_f-6]+xm_f; pg=g_img[y_g-6]+xm_g;
12057+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12058+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12059+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12060+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12061+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12062+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12063+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12064+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12065+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12066+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12067+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12068+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12069+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12070+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12071+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12072+
12073+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
12074+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12075+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12076+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12077+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12078+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12079+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12080+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12081+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12082+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12083+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12084+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12085+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12086+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12087+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12088+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12089+
12090+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
12091+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12092+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12093+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12094+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12095+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12096+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12097+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12098+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12099+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12100+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12101+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12102+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12103+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12104+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12105+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12106+
12107+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
12108+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12109+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12110+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12111+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12112+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12113+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12114+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12115+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12116+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12117+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12118+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12119+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12120+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12121+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12122+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12123+
12124+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
12125+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12126+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12127+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12128+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12129+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12130+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12131+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12132+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12133+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12134+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12135+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12136+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12137+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12138+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12139+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12140+
12141+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
12142+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12143+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12144+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12145+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12146+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12147+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12148+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12149+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12150+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12151+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12152+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12153+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12154+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12155+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12156+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12157+
12158+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
12159+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12160+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12161+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12162+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12163+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12164+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12165+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12166+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12167+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12168+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12169+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12170+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12171+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12172+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12173+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12174+
12175+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
12176+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12177+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12178+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12179+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12180+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12181+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12182+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12183+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12184+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12185+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12186+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12187+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12188+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12189+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12190+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12191+
12192+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
12193+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12194+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12195+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12196+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12197+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12198+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12199+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12200+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12201+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12202+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12203+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12204+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12205+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12206+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12207+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12208+
12209+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
12210+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12211+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12212+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12213+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12214+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12215+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12216+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12217+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12218+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12219+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12220+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12221+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12222+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12223+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12224+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12225+
12226+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
12227+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12228+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12229+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12230+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12231+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12232+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12233+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12234+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12235+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12236+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12237+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12238+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12239+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12240+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12241+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12242+
12243+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
12244+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12245+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12246+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12247+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12248+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12249+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12250+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12251+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12252+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12253+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12254+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12255+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12256+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12257+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12258+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12259+
12260+    pf=f_img[y_f+6]+xm_f; pg=g_img[y_g+6]+xm_g;
12261+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12262+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12263+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12264+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12265+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12266+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12267+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12268+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12269+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12270+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12271+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12272+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12273+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12274+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12275+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12276+
12277+    pf=f_img[y_f+7]+xm_f; pg=g_img[y_g+7]+xm_g;
12278+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12279+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12280+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12281+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12282+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12283+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12284+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12285+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12286+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12287+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12288+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12289+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12290+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12291+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12292+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12293+
12294+    fg_corr=225.0f*fgsum-fsum*gsum;
12295+    den=(225.0f*f2sum-fsum*fsum)*(225.0f*g2sum-gsum*gsum);
12296+    if(den!=0.0)
12297+    {
12298+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
12299+        return(-fg_corr*fg_corr/den);
12300+    }
12301+    return(0.0);
12302+}
12303+
12304+inline float db_SignedSquareNormCorr7x7_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g)
12305+{
12306+    float f,g,*pf,*pg,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
12307+    int xm_f,xm_g;
12308+
12309+    xm_f=x_f-3;
12310+    xm_g=x_g-3;
12311+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
12312+
12313+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
12314+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12315+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12316+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12317+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12318+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12319+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12320+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12321+
12322+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
12323+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12324+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12325+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12326+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12327+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12328+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12329+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12330+
12331+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
12332+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12333+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12334+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12335+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12336+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12337+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12338+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12339+
12340+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
12341+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12342+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12343+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12344+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12345+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12346+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12347+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12348+
12349+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
12350+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12351+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12352+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12353+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12354+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12355+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12356+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12357+
12358+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
12359+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12360+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12361+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12362+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12363+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12364+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12365+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12366+
12367+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
12368+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12369+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12370+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12371+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12372+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12373+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12374+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12375+
12376+    fg_corr=49.0f*fgsum-fsum*gsum;
12377+    den=(49.0f*f2sum-fsum*fsum)*(49.0f*g2sum-gsum*gsum);
12378+    if(den!=0.0)
12379+    {
12380+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
12381+        return(-fg_corr*fg_corr/den);
12382+    }
12383+    return(0.0);
12384+}
12385+
12386+inline float db_SignedSquareNormCorr9x9_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g)
12387+{
12388+    float f,g,*pf,*pg,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
12389+    int xm_f,xm_g;
12390+
12391+    xm_f=x_f-4;
12392+    xm_g=x_g-4;
12393+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
12394+
12395+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
12396+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12397+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12398+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12399+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12400+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12401+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12402+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12403+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12404+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12405+
12406+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
12407+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12408+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12409+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12410+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12411+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12412+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12413+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12414+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12415+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12416+
12417+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
12418+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12419+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12420+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12421+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12422+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12423+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12424+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12425+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12426+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12427+
12428+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
12429+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12430+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12431+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12432+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12433+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12434+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12435+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12436+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12437+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12438+
12439+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
12440+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12441+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12442+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12443+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12444+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12445+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12446+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12447+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12448+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12449+
12450+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
12451+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12452+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12453+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12454+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12455+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12456+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12457+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12458+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12459+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12460+
12461+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
12462+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12463+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12464+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12465+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12466+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12467+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12468+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12469+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12470+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12471+
12472+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
12473+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12474+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12475+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12476+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12477+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12478+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12479+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12480+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12481+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12482+
12483+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
12484+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12485+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12486+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12487+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12488+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12489+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12490+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12491+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12492+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12493+
12494+    fg_corr=81.0f*fgsum-fsum*gsum;
12495+    den=(81.0f*f2sum-fsum*fsum)*(81.0f*g2sum-gsum*gsum);
12496+    if(den!=0.0)
12497+    {
12498+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
12499+        return(-fg_corr*fg_corr/den);
12500+    }
12501+    return(0.0);
12502+}
12503+
12504+inline float db_SignedSquareNormCorr11x11_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g)
12505+{
12506+    float *pf,*pg;
12507+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
12508+    int xm_f,xm_g;
12509+
12510+    xm_f=x_f-5;
12511+    xm_g=x_g-5;
12512+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
12513+
12514+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
12515+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12516+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12517+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12518+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12519+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12520+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12521+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12522+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12523+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12524+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12525+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12526+
12527+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
12528+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12529+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12530+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12531+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12532+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12533+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12534+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12535+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12536+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12537+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12538+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12539+
12540+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
12541+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12542+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12543+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12544+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12545+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12546+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12547+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12548+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12549+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12550+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12551+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12552+
12553+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
12554+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12555+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12556+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12557+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12558+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12559+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12560+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12561+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12562+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12563+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12564+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12565+
12566+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
12567+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12568+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12569+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12570+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12571+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12572+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12573+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12574+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12575+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12576+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12577+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12578+
12579+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
12580+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12581+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12582+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12583+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12584+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12585+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12586+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12587+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12588+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12589+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12590+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12591+
12592+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
12593+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12594+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12595+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12596+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12597+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12598+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12599+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12600+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12601+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12602+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12603+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12604+
12605+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
12606+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12607+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12608+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12609+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12610+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12611+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12612+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12613+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12614+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12615+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12616+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12617+
12618+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
12619+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12620+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12621+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12622+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12623+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12624+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12625+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12626+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12627+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12628+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12629+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12630+
12631+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
12632+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12633+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12634+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12635+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12636+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12637+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12638+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12639+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12640+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12641+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12642+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12643+
12644+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
12645+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12646+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12647+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12648+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12649+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12650+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12651+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12652+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12653+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12654+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12655+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
12656+
12657+    fg_corr=121.0f*fgsum-fsum*gsum;
12658+    den=(121.0f*f2sum-fsum*fsum)*(121.0f*g2sum-gsum*gsum);
12659+    if(den!=0.0)
12660+    {
12661+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
12662+        return(-fg_corr*fg_corr/den);
12663+    }
12664+    return(0.0);
12665+}
12666+
12667+inline void db_SignedSquareNormCorr11x11_Pre_f(float **f_img,int x_f,int y_f,float *sum,float *recip)
12668+{
12669+    float *pf,den;
12670+    float f,f2sum,fsum;
12671+    int xm_f;
12672+
12673+    xm_f=x_f-5;
12674+
12675+    pf=f_img[y_f-5]+xm_f;
12676+    f= *pf++; f2sum=f*f;  fsum=f;
12677+    f= *pf++; f2sum+=f*f; fsum+=f;
12678+    f= *pf++; f2sum+=f*f; fsum+=f;
12679+    f= *pf++; f2sum+=f*f; fsum+=f;
12680+    f= *pf++; f2sum+=f*f; fsum+=f;
12681+    f= *pf++; f2sum+=f*f; fsum+=f;
12682+    f= *pf++; f2sum+=f*f; fsum+=f;
12683+    f= *pf++; f2sum+=f*f; fsum+=f;
12684+    f= *pf++; f2sum+=f*f; fsum+=f;
12685+    f= *pf++; f2sum+=f*f; fsum+=f;
12686+    f= *pf;   f2sum+=f*f; fsum+=f;
12687+
12688+    pf=f_img[y_f-4]+xm_f;
12689+    f= *pf++; f2sum+=f*f; fsum+=f;
12690+    f= *pf++; f2sum+=f*f; fsum+=f;
12691+    f= *pf++; f2sum+=f*f; fsum+=f;
12692+    f= *pf++; f2sum+=f*f; fsum+=f;
12693+    f= *pf++; f2sum+=f*f; fsum+=f;
12694+    f= *pf++; f2sum+=f*f; fsum+=f;
12695+    f= *pf++; f2sum+=f*f; fsum+=f;
12696+    f= *pf++; f2sum+=f*f; fsum+=f;
12697+    f= *pf++; f2sum+=f*f; fsum+=f;
12698+    f= *pf++; f2sum+=f*f; fsum+=f;
12699+    f= *pf;   f2sum+=f*f; fsum+=f;
12700+
12701+    pf=f_img[y_f-3]+xm_f;
12702+    f= *pf++; f2sum+=f*f; fsum+=f;
12703+    f= *pf++; f2sum+=f*f; fsum+=f;
12704+    f= *pf++; f2sum+=f*f; fsum+=f;
12705+    f= *pf++; f2sum+=f*f; fsum+=f;
12706+    f= *pf++; f2sum+=f*f; fsum+=f;
12707+    f= *pf++; f2sum+=f*f; fsum+=f;
12708+    f= *pf++; f2sum+=f*f; fsum+=f;
12709+    f= *pf++; f2sum+=f*f; fsum+=f;
12710+    f= *pf++; f2sum+=f*f; fsum+=f;
12711+    f= *pf++; f2sum+=f*f; fsum+=f;
12712+    f= *pf;   f2sum+=f*f; fsum+=f;
12713+
12714+    pf=f_img[y_f-2]+xm_f;
12715+    f= *pf++; f2sum+=f*f; fsum+=f;
12716+    f= *pf++; f2sum+=f*f; fsum+=f;
12717+    f= *pf++; f2sum+=f*f; fsum+=f;
12718+    f= *pf++; f2sum+=f*f; fsum+=f;
12719+    f= *pf++; f2sum+=f*f; fsum+=f;
12720+    f= *pf++; f2sum+=f*f; fsum+=f;
12721+    f= *pf++; f2sum+=f*f; fsum+=f;
12722+    f= *pf++; f2sum+=f*f; fsum+=f;
12723+    f= *pf++; f2sum+=f*f; fsum+=f;
12724+    f= *pf++; f2sum+=f*f; fsum+=f;
12725+    f= *pf;   f2sum+=f*f; fsum+=f;
12726+
12727+    pf=f_img[y_f-1]+xm_f;
12728+    f= *pf++; f2sum+=f*f; fsum+=f;
12729+    f= *pf++; f2sum+=f*f; fsum+=f;
12730+    f= *pf++; f2sum+=f*f; fsum+=f;
12731+    f= *pf++; f2sum+=f*f; fsum+=f;
12732+    f= *pf++; f2sum+=f*f; fsum+=f;
12733+    f= *pf++; f2sum+=f*f; fsum+=f;
12734+    f= *pf++; f2sum+=f*f; fsum+=f;
12735+    f= *pf++; f2sum+=f*f; fsum+=f;
12736+    f= *pf++; f2sum+=f*f; fsum+=f;
12737+    f= *pf++; f2sum+=f*f; fsum+=f;
12738+    f= *pf;   f2sum+=f*f; fsum+=f;
12739+
12740+    pf=f_img[y_f]+xm_f;
12741+    f= *pf++; f2sum+=f*f; fsum+=f;
12742+    f= *pf++; f2sum+=f*f; fsum+=f;
12743+    f= *pf++; f2sum+=f*f; fsum+=f;
12744+    f= *pf++; f2sum+=f*f; fsum+=f;
12745+    f= *pf++; f2sum+=f*f; fsum+=f;
12746+    f= *pf++; f2sum+=f*f; fsum+=f;
12747+    f= *pf++; f2sum+=f*f; fsum+=f;
12748+    f= *pf++; f2sum+=f*f; fsum+=f;
12749+    f= *pf++; f2sum+=f*f; fsum+=f;
12750+    f= *pf++; f2sum+=f*f; fsum+=f;
12751+    f= *pf;   f2sum+=f*f; fsum+=f;
12752+
12753+    pf=f_img[y_f+1]+xm_f;
12754+    f= *pf++; f2sum+=f*f; fsum+=f;
12755+    f= *pf++; f2sum+=f*f; fsum+=f;
12756+    f= *pf++; f2sum+=f*f; fsum+=f;
12757+    f= *pf++; f2sum+=f*f; fsum+=f;
12758+    f= *pf++; f2sum+=f*f; fsum+=f;
12759+    f= *pf++; f2sum+=f*f; fsum+=f;
12760+    f= *pf++; f2sum+=f*f; fsum+=f;
12761+    f= *pf++; f2sum+=f*f; fsum+=f;
12762+    f= *pf++; f2sum+=f*f; fsum+=f;
12763+    f= *pf++; f2sum+=f*f; fsum+=f;
12764+    f= *pf;   f2sum+=f*f; fsum+=f;
12765+
12766+    pf=f_img[y_f+2]+xm_f;
12767+    f= *pf++; f2sum+=f*f; fsum+=f;
12768+    f= *pf++; f2sum+=f*f; fsum+=f;
12769+    f= *pf++; f2sum+=f*f; fsum+=f;
12770+    f= *pf++; f2sum+=f*f; fsum+=f;
12771+    f= *pf++; f2sum+=f*f; fsum+=f;
12772+    f= *pf++; f2sum+=f*f; fsum+=f;
12773+    f= *pf++; f2sum+=f*f; fsum+=f;
12774+    f= *pf++; f2sum+=f*f; fsum+=f;
12775+    f= *pf++; f2sum+=f*f; fsum+=f;
12776+    f= *pf++; f2sum+=f*f; fsum+=f;
12777+    f= *pf;   f2sum+=f*f; fsum+=f;
12778+
12779+    pf=f_img[y_f+3]+xm_f;
12780+    f= *pf++; f2sum+=f*f; fsum+=f;
12781+    f= *pf++; f2sum+=f*f; fsum+=f;
12782+    f= *pf++; f2sum+=f*f; fsum+=f;
12783+    f= *pf++; f2sum+=f*f; fsum+=f;
12784+    f= *pf++; f2sum+=f*f; fsum+=f;
12785+    f= *pf++; f2sum+=f*f; fsum+=f;
12786+    f= *pf++; f2sum+=f*f; fsum+=f;
12787+    f= *pf++; f2sum+=f*f; fsum+=f;
12788+    f= *pf++; f2sum+=f*f; fsum+=f;
12789+    f= *pf++; f2sum+=f*f; fsum+=f;
12790+    f= *pf;   f2sum+=f*f; fsum+=f;
12791+
12792+    pf=f_img[y_f+4]+xm_f;
12793+    f= *pf++; f2sum+=f*f; fsum+=f;
12794+    f= *pf++; f2sum+=f*f; fsum+=f;
12795+    f= *pf++; f2sum+=f*f; fsum+=f;
12796+    f= *pf++; f2sum+=f*f; fsum+=f;
12797+    f= *pf++; f2sum+=f*f; fsum+=f;
12798+    f= *pf++; f2sum+=f*f; fsum+=f;
12799+    f= *pf++; f2sum+=f*f; fsum+=f;
12800+    f= *pf++; f2sum+=f*f; fsum+=f;
12801+    f= *pf++; f2sum+=f*f; fsum+=f;
12802+    f= *pf++; f2sum+=f*f; fsum+=f;
12803+    f= *pf;   f2sum+=f*f; fsum+=f;
12804+
12805+    pf=f_img[y_f+5]+xm_f;
12806+    f= *pf++; f2sum+=f*f; fsum+=f;
12807+    f= *pf++; f2sum+=f*f; fsum+=f;
12808+    f= *pf++; f2sum+=f*f; fsum+=f;
12809+    f= *pf++; f2sum+=f*f; fsum+=f;
12810+    f= *pf++; f2sum+=f*f; fsum+=f;
12811+    f= *pf++; f2sum+=f*f; fsum+=f;
12812+    f= *pf++; f2sum+=f*f; fsum+=f;
12813+    f= *pf++; f2sum+=f*f; fsum+=f;
12814+    f= *pf++; f2sum+=f*f; fsum+=f;
12815+    f= *pf++; f2sum+=f*f; fsum+=f;
12816+    f= *pf;   f2sum+=f*f; fsum+=f;
12817+
12818+    *sum=fsum;
12819+    den=(121.0f*f2sum-fsum*fsum);
12820+    *recip= (float) ((den!=0.0)?1.0/den:0.0);
12821+}
12822+
12823+inline void db_SignedSquareNormCorr11x11_PreAlign_f(float *patch,const float * const *f_img,int x_f,int y_f,float *sum,float *recip)
12824+{
12825+    const float *pf;
12826+    float den,f,f2sum,fsum;
12827+    int xm_f;
12828+
12829+    xm_f=x_f-5;
12830+
12831+    pf=f_img[y_f-5]+xm_f;
12832+    f= *pf++; f2sum=f*f;  fsum=f;  (*patch++)=f;
12833+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12834+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12835+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12836+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12837+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12838+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12839+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12840+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12841+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12842+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12843+
12844+    pf=f_img[y_f-4]+xm_f;
12845+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12846+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12847+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12848+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12849+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12850+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12851+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12852+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12853+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12854+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12855+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12856+
12857+    pf=f_img[y_f-3]+xm_f;
12858+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12859+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12860+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12861+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12862+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12863+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12864+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12865+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12866+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12867+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12868+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12869+
12870+    pf=f_img[y_f-2]+xm_f;
12871+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12872+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12873+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12874+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12875+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12876+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12877+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12878+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12879+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12880+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12881+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12882+
12883+    pf=f_img[y_f-1]+xm_f;
12884+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12885+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12886+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12887+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12888+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12889+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12890+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12891+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12892+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12893+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12894+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12895+
12896+    pf=f_img[y_f]+xm_f;
12897+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12898+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12899+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12900+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12901+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12902+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12903+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12904+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12905+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12906+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12907+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12908+
12909+    pf=f_img[y_f+1]+xm_f;
12910+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12911+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12912+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12913+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12914+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12915+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12916+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12917+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12918+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12919+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12920+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12921+
12922+    pf=f_img[y_f+2]+xm_f;
12923+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12924+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12925+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12926+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12927+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12928+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12929+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12930+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12931+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12932+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12933+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12934+
12935+    pf=f_img[y_f+3]+xm_f;
12936+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12937+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12938+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12939+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12940+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12941+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12942+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12943+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12944+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12945+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12946+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12947+
12948+    pf=f_img[y_f+4]+xm_f;
12949+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12950+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12951+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12952+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12953+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12954+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12955+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12956+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12957+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12958+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12959+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12960+
12961+    pf=f_img[y_f+5]+xm_f;
12962+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12963+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12964+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12965+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12966+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12967+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12968+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12969+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12970+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12971+    f= *pf++; f2sum+=f*f; fsum+=f; (*patch++)=f;
12972+    f= *pf;   f2sum+=f*f; fsum+=f; (*patch++)=f;
12973+
12974+    (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0; (*patch++)=0.0;
12975+    (*patch++)=0.0; (*patch++)=0.0;
12976+
12977+    *sum=fsum;
12978+    den=(121.0f*f2sum-fsum*fsum);
12979+    *recip= (float) ((den!=0.0)?1.0/den:0.0);
12980+}
12981+
12982+inline float db_SignedSquareNormCorr11x11_Post_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g,
12983+                                                float fsum_gsum,float f_recip_g_recip)
12984+{
12985+    float *pf,*pg;
12986+    float fgsum,fg_corr;
12987+    int xm_f,xm_g;
12988+
12989+    xm_f=x_f-5;
12990+    xm_g=x_g-5;
12991+
12992+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
12993+    fgsum=(*pf++)*(*pg++);  fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
12994+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
12995+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
12996+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
12997+
12998+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
12999+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13000+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13001+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13002+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13003+
13004+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
13005+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13006+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13007+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13008+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13009+
13010+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
13011+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13012+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13013+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13014+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13015+
13016+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
13017+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13018+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13019+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13020+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13021+
13022+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
13023+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13024+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13025+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13026+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13027+
13028+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
13029+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13030+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13031+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13032+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13033+
13034+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
13035+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13036+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13037+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13038+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13039+
13040+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
13041+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13042+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13043+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13044+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13045+
13046+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
13047+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13048+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13049+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13050+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13051+
13052+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
13053+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13054+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13055+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++); fgsum+=(*pf++)*(*pg++);
13056+    fgsum+=(*pf++)*(*pg++); fgsum+=(*pf)*(*pg);
13057+
13058+    fg_corr=121.0f*fgsum-fsum_gsum;
13059+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
13060+    return(-fg_corr*fg_corr*f_recip_g_recip);
13061+}
13062+
13063+inline float db_SignedSquareNormCorr11x11Aligned_Post_f(const float *f_patch,const float *g_patch,float fsum_gsum,float f_recip_g_recip)
13064+{
13065+    float fgsum,fg_corr;
13066+
13067+    fgsum=db_ScalarProduct128Aligned16_f(f_patch,g_patch);
13068+
13069+    fg_corr=121.0f*fgsum-fsum_gsum;
13070+    if(fg_corr>=0.0) return(fg_corr*fg_corr*f_recip_g_recip);
13071+    return(-fg_corr*fg_corr*f_recip_g_recip);
13072+}
13073+
13074+inline float db_SignedSquareNormCorr15x15_f(float **f_img,float **g_img,int x_f,int y_f,int x_g,int y_g)
13075+{
13076+    float *pf,*pg;
13077+    float f,g,fgsum,f2sum,g2sum,fsum,gsum,fg_corr,den;
13078+    int xm_f,xm_g;
13079+
13080+    xm_f=x_f-7;
13081+    xm_g=x_g-7;
13082+    fgsum=0.0; f2sum=0.0; g2sum=0.0; fsum=0.0; gsum=0.0;
13083+
13084+    pf=f_img[y_f-7]+xm_f; pg=g_img[y_g-7]+xm_g;
13085+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13086+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13087+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13088+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13089+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13090+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13091+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13092+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13093+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13094+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13095+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13096+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13097+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13098+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13099+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13100+
13101+    pf=f_img[y_f-6]+xm_f; pg=g_img[y_g-6]+xm_g;
13102+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13103+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13104+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13105+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13106+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13107+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13108+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13109+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13110+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13111+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13112+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13113+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13114+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13115+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13116+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13117+
13118+    pf=f_img[y_f-5]+xm_f; pg=g_img[y_g-5]+xm_g;
13119+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13120+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13121+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13122+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13123+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13124+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13125+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13126+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13127+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13128+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13129+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13130+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13131+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13132+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13133+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13134+
13135+    pf=f_img[y_f-4]+xm_f; pg=g_img[y_g-4]+xm_g;
13136+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13137+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13138+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13139+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13140+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13141+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13142+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13143+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13144+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13145+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13146+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13147+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13148+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13149+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13150+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13151+
13152+    pf=f_img[y_f-3]+xm_f; pg=g_img[y_g-3]+xm_g;
13153+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13154+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13155+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13156+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13157+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13158+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13159+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13160+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13161+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13162+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13163+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13164+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13165+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13166+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13167+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13168+
13169+    pf=f_img[y_f-2]+xm_f; pg=g_img[y_g-2]+xm_g;
13170+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13171+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13172+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13173+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13174+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13175+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13176+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13177+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13178+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13179+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13180+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13181+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13182+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13183+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13184+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13185+
13186+    pf=f_img[y_f-1]+xm_f; pg=g_img[y_g-1]+xm_g;
13187+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13188+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13189+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13190+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13191+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13192+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13193+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13194+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13195+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13196+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13197+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13198+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13199+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13200+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13201+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13202+
13203+    pf=f_img[y_f]+xm_f; pg=g_img[y_g]+xm_g;
13204+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13205+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13206+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13207+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13208+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13209+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13210+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13211+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13212+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13213+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13214+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13215+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13216+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13217+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13218+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13219+
13220+    pf=f_img[y_f+1]+xm_f; pg=g_img[y_g+1]+xm_g;
13221+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13222+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13223+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13224+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13225+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13226+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13227+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13228+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13229+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13230+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13231+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13232+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13233+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13234+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13235+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13236+
13237+    pf=f_img[y_f+2]+xm_f; pg=g_img[y_g+2]+xm_g;
13238+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13239+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13240+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13241+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13242+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13243+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13244+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13245+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13246+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13247+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13248+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13249+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13250+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13251+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13252+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13253+
13254+    pf=f_img[y_f+3]+xm_f; pg=g_img[y_g+3]+xm_g;
13255+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13256+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13257+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13258+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13259+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13260+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13261+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13262+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13263+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13264+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13265+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13266+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13267+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13268+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13269+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13270+
13271+    pf=f_img[y_f+4]+xm_f; pg=g_img[y_g+4]+xm_g;
13272+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13273+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13274+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13275+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13276+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13277+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13278+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13279+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13280+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13281+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13282+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13283+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13284+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13285+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13286+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13287+
13288+    pf=f_img[y_f+5]+xm_f; pg=g_img[y_g+5]+xm_g;
13289+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13290+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13291+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13292+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13293+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13294+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13295+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13296+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13297+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13298+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13299+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13300+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13301+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13302+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13303+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13304+
13305+    pf=f_img[y_f+6]+xm_f; pg=g_img[y_g+6]+xm_g;
13306+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13307+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13308+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13309+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13310+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13311+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13312+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13313+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13314+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13315+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13316+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13317+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13318+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13319+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13320+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13321+
13322+    pf=f_img[y_f+7]+xm_f; pg=g_img[y_g+7]+xm_g;
13323+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13324+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13325+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13326+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13327+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13328+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13329+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13330+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13331+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13332+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13333+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13334+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13335+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13336+    f= *pf++; g= *pg++; fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13337+    f= *pf;   g= *pg;   fgsum+=f*g; f2sum+=f*f; g2sum+=g*g; fsum+=f; gsum+=g;
13338+
13339+    fg_corr=225.0f*fgsum-fsum*gsum;
13340+    den=(225.0f*f2sum-fsum*fsum)*(225.0f*g2sum-gsum*gsum);
13341+    if(den!=0.0)
13342+    {
13343+        if(fg_corr>=0.0) return(fg_corr*fg_corr/den);
13344+        return(-fg_corr*fg_corr/den);
13345+    }
13346+    return(0.0);
13347+}
13348+
13349+db_Bucket_f** db_AllocBuckets_f(int nr_h,int nr_v,int bd)
13350+{
13351+    int i,j;
13352+    db_Bucket_f **bp,*b;
13353+
13354+    b=new db_Bucket_f [(nr_h+2)*(nr_v+2)];
13355+    bp=new db_Bucket_f* [(nr_v+2)];
13356+    bp=bp+1;
13357+    for(i= -1;i<=nr_v;i++)
13358+    {
13359+        bp[i]=b+1+(nr_h+2)*(i+1);
13360+        for(j= -1;j<=nr_h;j++)
13361+        {
13362+            bp[i][j].ptr=new db_PointInfo_f [bd];
13363+        }
13364+    }
13365+
13366+    return(bp);
13367+}
13368+
13369+db_Bucket_u** db_AllocBuckets_u(int nr_h,int nr_v,int bd)
13370+{
13371+    int i,j;
13372+    db_Bucket_u **bp,*b;
13373+
13374+    b=new db_Bucket_u [(nr_h+2)*(nr_v+2)];
13375+    bp=new db_Bucket_u* [(nr_v+2)];
13376+    bp=bp+1;
13377+    for(i= -1;i<=nr_v;i++)
13378+    {
13379+        bp[i]=b+1+(nr_h+2)*(i+1);
13380+        for(j= -1;j<=nr_h;j++)
13381+        {
13382+            bp[i][j].ptr=new db_PointInfo_u [bd];
13383+        }
13384+    }
13385+
13386+    return(bp);
13387+}
13388+
13389+void db_FreeBuckets_f(db_Bucket_f **bp,int nr_h,int nr_v)
13390+{
13391+    int i,j;
13392+
13393+    for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++)
13394+    {
13395+        delete [] bp[i][j].ptr;
13396+    }
13397+    delete [] (bp[-1]-1);
13398+    delete [] (bp-1);
13399+}
13400+
13401+void db_FreeBuckets_u(db_Bucket_u **bp,int nr_h,int nr_v)
13402+{
13403+    int i,j;
13404+
13405+    for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++)
13406+    {
13407+        delete [] bp[i][j].ptr;
13408+    }
13409+    delete [] (bp[-1]-1);
13410+    delete [] (bp-1);
13411+}
13412+
13413+void db_EmptyBuckets_f(db_Bucket_f **bp,int nr_h,int nr_v)
13414+{
13415+    int i,j;
13416+    for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) bp[i][j].nr=0;
13417+}
13418+
13419+void db_EmptyBuckets_u(db_Bucket_u **bp,int nr_h,int nr_v)
13420+{
13421+    int i,j;
13422+    for(i= -1;i<=nr_v;i++) for(j= -1;j<=nr_h;j++) bp[i][j].nr=0;
13423+}
13424+
13425+float* db_FillBuckets_f(float *patch_space,const float * const *f_img,db_Bucket_f **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners)
13426+{
13427+    int i,xi,yi,xpos,ypos,nr;
13428+    db_Bucket_f *br;
13429+    db_PointInfo_f *pir;
13430+
13431+    db_EmptyBuckets_f(bp,nr_h,nr_v);
13432+    for(i=0;i<nr_corners;i++)
13433+    {
13434+        xi=(int) x[i];
13435+        yi=(int) y[i];
13436+        xpos=xi/bw;
13437+        ypos=yi/bh;
13438+        if(xpos>=0 && xpos<nr_h && ypos>=0 && ypos<nr_v)
13439+        {
13440+            br=&bp[ypos][xpos];
13441+            nr=br->nr;
13442+            if(nr<bd)
13443+            {
13444+                pir=&(br->ptr[nr]);
13445+                pir->x=xi;
13446+                pir->y=yi;
13447+                pir->id=i;
13448+                pir->pir=0;
13449+                pir->patch=patch_space;
13450+                br->nr=nr+1;
13451+
13452+                db_SignedSquareNormCorr11x11_PreAlign_f(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13453+                patch_space+=128;
13454+            }
13455+        }
13456+    }
13457+    return(patch_space);
13458+}
13459+
13460+short* db_FillBuckets_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners,int use_smaller_matching_window, int use_21)
13461+{
13462+    int i,xi,yi,xpos,ypos,nr;
13463+    db_Bucket_u *br;
13464+    db_PointInfo_u *pir;
13465+
13466+    db_EmptyBuckets_u(bp,nr_h,nr_v);
13467+    for(i=0;i<nr_corners;i++)
13468+    {
13469+        xi=(int)db_roundi(x[i]);
13470+        yi=(int)db_roundi(y[i]);
13471+        xpos=xi/bw;
13472+        ypos=yi/bh;
13473+        if(xpos>=0 && xpos<nr_h && ypos>=0 && ypos<nr_v)
13474+        {
13475+            br=&bp[ypos][xpos];
13476+            nr=br->nr;
13477+            if(nr<bd)
13478+            {
13479+                pir=&(br->ptr[nr]);
13480+                pir->x=xi;
13481+                pir->y=yi;
13482+                pir->id=i;
13483+                pir->pir=0;
13484+                pir->patch=patch_space;
13485+                br->nr=nr+1;
13486+
13487+                if(use_21)
13488+                {
13489+                    db_SignedSquareNormCorr21x21_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13490+                    patch_space+=512;
13491+                }
13492+                else
13493+                {
13494+                if(!use_smaller_matching_window)
13495+                {
13496+                    db_SignedSquareNormCorr11x11_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13497+                    patch_space+=128;
13498+                }
13499+                else
13500+                {
13501+                    db_SignedSquareNormCorr5x5_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13502+                    patch_space+=32;
13503+                }
13504+                }
13505+            }
13506+        }
13507+    }
13508+    return(patch_space);
13509+}
13510+
13511+
13512+
13513+float* db_FillBucketsPrewarped_f(float *patch_space,const float *const *f_img,db_Bucket_f **bp,int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,int nr_corners,const double H[9])
13514+{
13515+    int i,xi,yi,xpos,ypos,nr,wxi,wyi;
13516+    db_Bucket_f *br;
13517+    db_PointInfo_f *pir;
13518+    double xd[2],wx[2];
13519+
13520+    db_EmptyBuckets_f(bp,nr_h,nr_v);
13521+    for(i=0;i<nr_corners;i++)
13522+    {
13523+        xd[0]=x[i];
13524+        xd[1]=y[i];
13525+        xi=(int) xd[0];
13526+        yi=(int) xd[1];
13527+        db_ImageHomographyInhomogenous(wx,H,xd);
13528+        wxi=(int) wx[0];
13529+        wyi=(int) wx[1];
13530+
13531+        xpos=((wxi+bw)/bw)-1;
13532+        ypos=((wyi+bh)/bh)-1;
13533+        if(xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v)
13534+        {
13535+            br=&bp[ypos][xpos];
13536+            nr=br->nr;
13537+            if(nr<bd)
13538+            {
13539+                pir=&(br->ptr[nr]);
13540+                pir->x=wxi;
13541+                pir->y=wyi;
13542+                pir->id=i;
13543+                pir->pir=0;
13544+                pir->patch=patch_space;
13545+                br->nr=nr+1;
13546+
13547+                db_SignedSquareNormCorr11x11_PreAlign_f(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13548+                patch_space+=128;
13549+            }
13550+        }
13551+    }
13552+    return(patch_space);
13553+}
13554+
13555+short* db_FillBucketsPrewarped_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp,
13556+                                 int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,
13557+                                 int nr_corners,const double H[9])
13558+{
13559+    int i,xi,yi,xpos,ypos,nr,wxi,wyi;
13560+    db_Bucket_u *br;
13561+    db_PointInfo_u *pir;
13562+    double xd[2],wx[2];
13563+
13564+    db_EmptyBuckets_u(bp,nr_h,nr_v);
13565+    for(i=0;i<nr_corners;i++)
13566+    {
13567+        xd[0]=x[i];
13568+        xd[1]=y[i];
13569+        xi=(int) db_roundi(xd[0]);
13570+        yi=(int) db_roundi(xd[1]);
13571+        db_ImageHomographyInhomogenous(wx,H,xd);
13572+        wxi=(int) wx[0];
13573+        wyi=(int) wx[1];
13574+
13575+        xpos=((wxi+bw)/bw)-1;
13576+        ypos=((wyi+bh)/bh)-1;
13577+        if(xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v)
13578+        {
13579+            br=&bp[ypos][xpos];
13580+            nr=br->nr;
13581+            if(nr<bd)
13582+            {
13583+                pir=&(br->ptr[nr]);
13584+                pir->x=wxi;
13585+                pir->y=wyi;
13586+                pir->id=i;
13587+                pir->pir=0;
13588+                pir->patch=patch_space;
13589+                br->nr=nr+1;
13590+
13591+                db_SignedSquareNormCorr11x11_PreAlign_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip));
13592+                patch_space+=128;
13593+            }
13594+        }
13595+    }
13596+    return(patch_space);
13597+}
13598+
13599+
13600+
13601+short* db_FillBucketsPrewarpedAffine_u(short *patch_space,const unsigned char * const *f_img,db_Bucket_u **bp,
13602+                                 int bw,int bh,int nr_h,int nr_v,int bd,const double *x,const double *y,
13603+                                 int nr_corners,const double H[9],const double Hinv[9],const int warpboundsp[4],
13604+                                 int affine)
13605+{
13606+    int i,xi,yi,xpos,ypos,nr,wxi,wyi;
13607+    db_Bucket_u *br;
13608+    db_PointInfo_u *pir;
13609+    double xd[2],wx[2];
13610+
13611+    db_EmptyBuckets_u(bp,nr_h,nr_v);
13612+    for(i=0;i<nr_corners;i++)
13613+    {
13614+        xd[0]=x[i];
13615+        xd[1]=y[i];
13616+        xi=(int) db_roundi(xd[0]);
13617+        yi=(int) db_roundi(xd[1]);
13618+        db_ImageHomographyInhomogenous(wx,H,xd);
13619+        wxi=(int) wx[0];
13620+        wyi=(int) wx[1];
13621+
13622+        xpos=((wxi+bw)/bw)-1;
13623+        ypos=((wyi+bh)/bh)-1;
13624+
13625+
13626+        if (xpos>= -1 && xpos<=nr_h && ypos>= -1 && ypos<=nr_v)
13627+        {
13628+            if( xi>warpboundsp[0] && xi<warpboundsp[1] && yi>warpboundsp[2] && yi<warpboundsp[3])
13629+            {
13630+
13631+                br=&bp[ypos][xpos];
13632+                nr=br->nr;
13633+                if(nr<bd)
13634+                {
13635+                    pir=&(br->ptr[nr]);
13636+                    pir->x=wxi;
13637+                    pir->y=wyi;
13638+                    pir->id=i;
13639+                    pir->pir=0;
13640+                    pir->patch=patch_space;
13641+                    br->nr=nr+1;
13642+
13643+                    db_SignedSquareNormCorr11x11_PreAlign_AffinePatchWarp_u(patch_space,f_img,xi,yi,&(pir->sum),&(pir->recip),Hinv,affine);
13644+                    patch_space+=128;
13645+                }
13646+            }
13647+        }
13648+    }
13649+    return(patch_space);
13650+}
13651+
13652+
13653+
13654+inline void db_MatchPointPair_f(db_PointInfo_f *pir_l,db_PointInfo_f *pir_r,
13655+                            unsigned long kA,unsigned long kB)
13656+{
13657+    int x_l,y_l,x_r,y_r,xm,ym;
13658+    double score;
13659+
13660+    x_l=pir_l->x;
13661+    y_l=pir_l->y;
13662+    x_r=pir_r->x;
13663+    y_r=pir_r->y;
13664+    xm=x_l-x_r;
13665+    ym=y_l-y_r;
13666+    /*Check if disparity is within the maximum disparity
13667+    with the formula xm^2*256+ym^2*kA<kB
13668+    where kA=256*w^2/h^2
13669+    and   kB=256*max_disp^2*w^2*/
13670+    if(((xm*xm)<<8)+ym*ym*kA<kB)
13671+    {
13672+        /*Correlate*/
13673+        score=db_SignedSquareNormCorr11x11Aligned_Post_f(pir_l->patch,pir_r->patch,
13674+            (pir_l->sum)*(pir_r->sum),
13675+            (pir_l->recip)*(pir_r->recip));
13676+
13677+        if((!(pir_l->pir)) || (score>pir_l->s))
13678+        {
13679+            /*Update left corner*/
13680+            pir_l->s=score;
13681+            pir_l->pir=pir_r;
13682+        }
13683+        if((!(pir_r->pir)) || (score>pir_r->s))
13684+        {
13685+            /*Update right corner*/
13686+            pir_r->s=score;
13687+            pir_r->pir=pir_l;
13688+        }
13689+    }
13690+}
13691+
13692+inline void db_MatchPointPair_u(db_PointInfo_u *pir_l,db_PointInfo_u *pir_r,
13693+                            unsigned long kA,unsigned long kB, unsigned int rect_window,bool use_smaller_matching_window, int use_21)
13694+{
13695+    int xm,ym;
13696+    double score;
13697+    bool compute_score;
13698+
13699+
13700+    if( rect_window )
13701+        compute_score = ((unsigned)db_absi(pir_l->x - pir_r->x)<kA && (unsigned)db_absi(pir_l->y - pir_r->y)<kB);
13702+    else
13703+    {   /*Check if disparity is within the maximum disparity
13704+        with the formula xm^2*256+ym^2*kA<kB
13705+        where kA=256*w^2/h^2
13706+        and   kB=256*max_disp^2*w^2*/
13707+        xm= pir_l->x - pir_r->x;
13708+        ym= pir_l->y - pir_r->y;
13709+        compute_score = ((xm*xm)<<8)+ym*ym*kA < kB;
13710+    }
13711+
13712+    if ( compute_score )
13713+    {
13714+        if(use_21)
13715+        {
13716+            score=db_SignedSquareNormCorr21x21Aligned_Post_s(pir_l->patch,pir_r->patch,
13717+                (pir_l->sum)*(pir_r->sum),
13718+                (pir_l->recip)*(pir_r->recip));
13719+        }
13720+        else
13721+        {
13722+        /*Correlate*/
13723+        if(!use_smaller_matching_window)
13724+        {
13725+            score=db_SignedSquareNormCorr11x11Aligned_Post_s(pir_l->patch,pir_r->patch,
13726+                (pir_l->sum)*(pir_r->sum),
13727+                (pir_l->recip)*(pir_r->recip));
13728+        }
13729+        else
13730+        {
13731+            score=db_SignedSquareNormCorr5x5Aligned_Post_s(pir_l->patch,pir_r->patch,
13732+                (pir_l->sum)*(pir_r->sum),
13733+                (pir_l->recip)*(pir_r->recip));
13734+        }
13735+        }
13736+
13737+        if((!(pir_l->pir)) || (score>pir_l->s))
13738+        {
13739+            /*Update left corner*/
13740+            pir_l->s=score;
13741+            pir_l->pir=pir_r;
13742+        }
13743+        if((!(pir_r->pir)) || (score>pir_r->s))
13744+        {
13745+            /*Update right corner*/
13746+            pir_r->s=score;
13747+            pir_r->pir=pir_l;
13748+        }
13749+    }
13750+}
13751+
13752+inline void db_MatchPointAgainstBucket_f(db_PointInfo_f *pir_l,db_Bucket_f *b_r,
13753+                                       unsigned long kA,unsigned long kB)
13754+{
13755+    int p_r,nr;
13756+    db_PointInfo_f *pir_r;
13757+
13758+    nr=b_r->nr;
13759+    pir_r=b_r->ptr;
13760+    for(p_r=0;p_r<nr;p_r++) db_MatchPointPair_f(pir_l,pir_r+p_r,kA,kB);
13761+}
13762+
13763+inline void db_MatchPointAgainstBucket_u(db_PointInfo_u *pir_l,db_Bucket_u *b_r,
13764+                                       unsigned long kA,unsigned long kB,int rect_window, bool use_smaller_matching_window, int use_21)
13765+{
13766+    int p_r,nr;
13767+    db_PointInfo_u *pir_r;
13768+
13769+    nr=b_r->nr;
13770+    pir_r=b_r->ptr;
13771+
13772+    for(p_r=0;p_r<nr;p_r++) db_MatchPointPair_u(pir_l,pir_r+p_r,kA,kB, rect_window, use_smaller_matching_window, use_21);
13773+
13774+}
13775+
13776+void db_MatchBuckets_f(db_Bucket_f **bp_l,db_Bucket_f **bp_r,int nr_h,int nr_v,
13777+                     unsigned long kA,unsigned long kB)
13778+{
13779+    int i,j,k,a,b,br_nr;
13780+    db_Bucket_f *br;
13781+    db_PointInfo_f *pir_l;
13782+
13783+    /*For all buckets*/
13784+    for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++)
13785+    {
13786+        br=&bp_l[i][j];
13787+        br_nr=br->nr;
13788+        /*For all points in bucket*/
13789+        for(k=0;k<br_nr;k++)
13790+        {
13791+            pir_l=br->ptr+k;
13792+            for(a=i-1;a<=i+1;a++)
13793+            {
13794+                for(b=j-1;b<=j+1;b++)
13795+                {
13796+                    db_MatchPointAgainstBucket_f(pir_l,&bp_r[a][b],kA,kB);
13797+                }
13798+            }
13799+        }
13800+    }
13801+}
13802+
13803+void db_MatchBuckets_u(db_Bucket_u **bp_l,db_Bucket_u **bp_r,int nr_h,int nr_v,
13804+                     unsigned long kA,unsigned long kB,int rect_window,bool use_smaller_matching_window, int use_21)
13805+{
13806+    int i,j,k,a,b,br_nr;
13807+    db_Bucket_u *br;
13808+    db_PointInfo_u *pir_l;
13809+
13810+    /*For all buckets*/
13811+    for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++)
13812+    {
13813+        br=&bp_l[i][j];
13814+        br_nr=br->nr;
13815+        /*For all points in bucket*/
13816+        for(k=0;k<br_nr;k++)
13817+        {
13818+            pir_l=br->ptr+k;
13819+            for(a=i-1;a<=i+1;a++)
13820+            {
13821+                for(b=j-1;b<=j+1;b++)
13822+                {
13823+                    db_MatchPointAgainstBucket_u(pir_l,&bp_r[a][b],kA,kB,rect_window,use_smaller_matching_window, use_21);
13824+                }
13825+            }
13826+        }
13827+    }
13828+}
13829+
13830+void db_CollectMatches_f(db_Bucket_f **bp_l,int nr_h,int nr_v,unsigned long target,int *id_l,int *id_r,int *nr_matches)
13831+{
13832+    int i,j,k,br_nr;
13833+    unsigned long count;
13834+    db_Bucket_f *br;
13835+    db_PointInfo_f *pir,*pir2;
13836+
13837+    count=0;
13838+    /*For all buckets*/
13839+    for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++)
13840+    {
13841+        br=&bp_l[i][j];
13842+        br_nr=br->nr;
13843+        /*For all points in bucket*/
13844+        for(k=0;k<br_nr;k++)
13845+        {
13846+            pir=br->ptr+k;
13847+            pir2=pir->pir;
13848+            if(pir2)
13849+            {
13850+                /*This point has a best match*/
13851+                if((pir2->pir)==pir)
13852+                {
13853+                    /*We have a mutually consistent match*/
13854+                    if(count<target)
13855+                    {
13856+                        id_l[count]=pir->id;
13857+                        id_r[count]=pir2->id;
13858+                        count++;
13859+                    }
13860+                }
13861+            }
13862+        }
13863+    }
13864+    *nr_matches=count;
13865+}
13866+
13867+void db_CollectMatches_u(db_Bucket_u **bp_l,int nr_h,int nr_v,unsigned long target,int *id_l,int *id_r,int *nr_matches)
13868+{
13869+    int i,j,k,br_nr;
13870+    unsigned long count;
13871+    db_Bucket_u *br;
13872+    db_PointInfo_u *pir,*pir2;
13873+
13874+    count=0;
13875+    /*For all buckets*/
13876+    for(i=0;i<nr_v;i++) for(j=0;j<nr_h;j++)
13877+    {
13878+        br=&bp_l[i][j];
13879+        br_nr=br->nr;
13880+        /*For all points in bucket*/
13881+        for(k=0;k<br_nr;k++)
13882+        {
13883+            pir=br->ptr+k;
13884+            pir2=pir->pir;
13885+            if(pir2)
13886+            {
13887+                /*This point has a best match*/
13888+                if((pir2->pir)==pir)
13889+                {
13890+                    /*We have a mutually consistent match*/
13891+                    if(count<target)
13892+                    {
13893+                        id_l[count]=pir->id;
13894+                        id_r[count]=pir2->id;
13895+                        count++;
13896+                    }
13897+                }
13898+            }
13899+        }
13900+    }
13901+    *nr_matches=count;
13902+}
13903+
13904+db_Matcher_f::db_Matcher_f()
13905+{
13906+    m_w=0; m_h=0;
13907+}
13908+
13909+db_Matcher_f::~db_Matcher_f()
13910+{
13911+    Clean();
13912+}
13913+
13914+void db_Matcher_f::Clean()
13915+{
13916+    if(m_w)
13917+    {
13918+        /*Free buckets*/
13919+        db_FreeBuckets_f(m_bp_l,m_nr_h,m_nr_v);
13920+        db_FreeBuckets_f(m_bp_r,m_nr_h,m_nr_v);
13921+        /*Free space for patch layouts*/
13922+        delete [] m_patch_space;
13923+    }
13924+    m_w=0; m_h=0;
13925+}
13926+
13927+unsigned long db_Matcher_f::Init(int im_width,int im_height,double max_disparity,int target_nr_corners)
13928+{
13929+    Clean();
13930+    m_w=im_width;
13931+    m_h=im_height;
13932+    m_bw=db_maxi(1,(int) (max_disparity*((double)im_width)));
13933+    m_bh=db_maxi(1,(int) (max_disparity*((double)im_height)));
13934+    m_nr_h=1+(im_width-1)/m_bw;
13935+    m_nr_v=1+(im_height-1)/m_bh;
13936+    m_bd=db_maxi(1,(int)(((double)target_nr_corners)*
13937+        max_disparity*max_disparity));
13938+    m_target=target_nr_corners;
13939+    m_kA=(long)(256.0*((double)(m_w*m_w))/((double)(m_h*m_h)));
13940+    m_kB=(long)(256.0*max_disparity*max_disparity*((double)(m_w*m_w)));
13941+
13942+    /*Alloc bucket structure*/
13943+    m_bp_l=db_AllocBuckets_f(m_nr_h,m_nr_v,m_bd);
13944+    m_bp_r=db_AllocBuckets_f(m_nr_h,m_nr_v,m_bd);
13945+
13946+    /*Alloc 16byte-aligned space for patch layouts*/
13947+    m_patch_space=new float [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*128+16];
13948+    m_aligned_patch_space=db_AlignPointer_f(m_patch_space,16);
13949+
13950+    return(m_target);
13951+}
13952+
13953+void db_Matcher_f::Match(const float * const *l_img,const float * const *r_img,
13954+        const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r,
13955+        int *id_l,int *id_r,int *nr_matches,const double H[9])
13956+{
13957+    float *ps;
13958+
13959+    /*Insert the corners into bucket structure*/
13960+    ps=db_FillBuckets_f(m_aligned_patch_space,l_img,m_bp_l,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_l,y_l,nr_l);
13961+    if(H==0) db_FillBuckets_f(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r);
13962+    else db_FillBucketsPrewarped_f(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,H);
13963+
13964+    /*Compute all the necessary match scores*/
13965+    db_MatchBuckets_f(m_bp_l,m_bp_r,m_nr_h,m_nr_v,m_kA,m_kB);
13966+
13967+    /*Collect the correspondences*/
13968+    db_CollectMatches_f(m_bp_l,m_nr_h,m_nr_v,m_target,id_l,id_r,nr_matches);
13969+}
13970+
13971+db_Matcher_u::db_Matcher_u()
13972+{
13973+    m_w=0; m_h=0;
13974+    m_rect_window = 0;
13975+    m_bw=m_bh=m_nr_h=m_nr_v=m_bd=m_target=0;
13976+    m_bp_l=m_bp_r=0;
13977+    m_patch_space=m_aligned_patch_space=0;
13978+}
13979+
13980+db_Matcher_u::db_Matcher_u(const db_Matcher_u& cm)
13981+{
13982+    Init(cm.m_w, cm.m_h, cm.m_max_disparity, cm.m_target, cm.m_max_disparity_v);
13983+}
13984+
13985+db_Matcher_u& db_Matcher_u::operator= (const db_Matcher_u& cm)
13986+{
13987+    if ( this == &cm ) return *this;
13988+    Init(cm.m_w, cm.m_h, cm.m_max_disparity, cm.m_target, cm.m_max_disparity_v);
13989+    return *this;
13990+}
13991+
13992+
13993+db_Matcher_u::~db_Matcher_u()
13994+{
13995+    Clean();
13996+}
13997+
13998+void db_Matcher_u::Clean()
13999+{
14000+    if(m_w)
14001+    {
14002+        /*Free buckets*/
14003+        db_FreeBuckets_u(m_bp_l,m_nr_h,m_nr_v);
14004+        db_FreeBuckets_u(m_bp_r,m_nr_h,m_nr_v);
14005+        /*Free space for patch layouts*/
14006+        delete [] m_patch_space;
14007+    }
14008+    m_w=0; m_h=0;
14009+}
14010+
14011+
14012+unsigned long db_Matcher_u::Init(int im_width,int im_height,double max_disparity,int target_nr_corners,
14013+                                 double max_disparity_v, bool use_smaller_matching_window, int use_21)
14014+{
14015+    Clean();
14016+    m_w=im_width;
14017+    m_h=im_height;
14018+    m_max_disparity=max_disparity;
14019+    m_max_disparity_v=max_disparity_v;
14020+
14021+    if ( max_disparity_v != DB_DEFAULT_NO_DISPARITY )
14022+    {
14023+        m_rect_window = 1;
14024+
14025+        m_bw=db_maxi(1,(int)(max_disparity*((double)im_width)));
14026+        m_bh=db_maxi(1,(int)(max_disparity_v*((double)im_height)));
14027+
14028+        m_bd=db_maxi(1,(int)(((double)target_nr_corners)*max_disparity*max_disparity_v));
14029+
14030+        m_kA=(int)(max_disparity*m_w);
14031+        m_kB=(int)(max_disparity_v*m_h);
14032+
14033+    } else
14034+    {
14035+        m_bw=(int)db_maxi(1,(int)(max_disparity*((double)im_width)));
14036+        m_bh=(int)db_maxi(1,(int)(max_disparity*((double)im_height)));
14037+
14038+        m_bd=db_maxi(1,(int)(((double)target_nr_corners)*max_disparity*max_disparity));
14039+
14040+        m_kA=(long)(256.0*((double)(m_w*m_w))/((double)(m_h*m_h)));
14041+        m_kB=(long)(256.0*max_disparity*max_disparity*((double)(m_w*m_w)));
14042+    }
14043+
14044+    m_nr_h=1+(im_width-1)/m_bw;
14045+    m_nr_v=1+(im_height-1)/m_bh;
14046+
14047+    m_target=target_nr_corners;
14048+
14049+    /*Alloc bucket structure*/
14050+    m_bp_l=db_AllocBuckets_u(m_nr_h,m_nr_v,m_bd);
14051+    m_bp_r=db_AllocBuckets_u(m_nr_h,m_nr_v,m_bd);
14052+
14053+    m_use_smaller_matching_window = use_smaller_matching_window;
14054+    m_use_21 = use_21;
14055+
14056+    if(m_use_21)
14057+    {
14058+        /*Alloc 64byte-aligned space for patch layouts*/
14059+        m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*512+64];
14060+        m_aligned_patch_space=db_AlignPointer_s(m_patch_space,64);
14061+    }
14062+    else
14063+    {
14064+    if(!m_use_smaller_matching_window)
14065+    {
14066+        /*Alloc 16byte-aligned space for patch layouts*/
14067+        m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*128+16];
14068+        m_aligned_patch_space=db_AlignPointer_s(m_patch_space,16);
14069+    }
14070+    else
14071+    {
14072+        /*Alloc 4byte-aligned space for patch layouts*/
14073+        m_patch_space=new short [2*(m_nr_h+2)*(m_nr_v+2)*m_bd*32+4];
14074+        m_aligned_patch_space=db_AlignPointer_s(m_patch_space,4);
14075+    }
14076+    }
14077+
14078+    return(m_target);
14079+}
14080+
14081+void db_Matcher_u::Match(const unsigned char * const *l_img,const unsigned char * const *r_img,
14082+        const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r,
14083+        int *id_l,int *id_r,int *nr_matches,const double H[9],int affine)
14084+{
14085+    short *ps;
14086+
14087+    /*Insert the corners into bucket structure*/
14088+    ps=db_FillBuckets_u(m_aligned_patch_space,l_img,m_bp_l,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_l,y_l,nr_l,m_use_smaller_matching_window,m_use_21);
14089+    if(H==0)
14090+        db_FillBuckets_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,m_use_smaller_matching_window,m_use_21);
14091+    else
14092+    {
14093+        if (affine)
14094+        {
14095+            double Hinv[9];
14096+            db_InvertAffineTransform(Hinv,H);
14097+            float r_w, c_w;
14098+            float stretch_x[2];
14099+            float stretch_y[2];
14100+            AffineWarpPointOffset(r_w,c_w,Hinv, 5,5);
14101+            stretch_x[0]=db_absf(c_w);stretch_y[0]=db_absf(r_w);
14102+            AffineWarpPointOffset(r_w,c_w,Hinv, 5,-5);
14103+            stretch_x[1]=db_absf(c_w);stretch_y[1]=db_absf(r_w);
14104+            int max_stretxh_x=(int) (db_maxd(stretch_x[0],stretch_x[1]));
14105+            int max_stretxh_y=(int) (db_maxd(stretch_y[0],stretch_y[1]));
14106+            int warpbounds[4]={max_stretxh_x,m_w-1-max_stretxh_x,max_stretxh_y,m_h-1-max_stretxh_y};
14107+
14108+            for (int r=-5;r<=5;r++){
14109+                for (int c=-5;c<=5;c++){
14110+                    AffineWarpPointOffset(r_w,c_w,Hinv,r,c);
14111+                    AffineWarpPoint_BL_LUT_y[r+5][c+5]=r_w;
14112+                    AffineWarpPoint_BL_LUT_x[r+5][c+5]=c_w;
14113+
14114+                    AffineWarpPoint_NN_LUT_y[r+5][c+5]=db_roundi(r_w);
14115+                    AffineWarpPoint_NN_LUT_x[r+5][c+5]=db_roundi(c_w);
14116+
14117+                }
14118+            }
14119+
14120+            db_FillBucketsPrewarpedAffine_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,
14121+                x_r,y_r,nr_r,H,Hinv,warpbounds,affine);
14122+        }
14123+        else
14124+            db_FillBucketsPrewarped_u(ps,r_img,m_bp_r,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,x_r,y_r,nr_r,H);
14125+    }
14126+
14127+
14128+    /*Compute all the necessary match scores*/
14129+    db_MatchBuckets_u(m_bp_l,m_bp_r,m_nr_h,m_nr_v,m_kA,m_kB, m_rect_window,m_use_smaller_matching_window,m_use_21);
14130+
14131+    /*Collect the correspondences*/
14132+    db_CollectMatches_u(m_bp_l,m_nr_h,m_nr_v,m_target,id_l,id_r,nr_matches);
14133+}
14134+
14135+int db_Matcher_u::IsAllocated()
14136+{
14137+    return (int)(m_w != 0);
14138+}
14139diff --git a/benchmark/feature_stab/db_vlvm/db_feature_matching.h b/benchmark/feature_stab/db_vlvm/db_feature_matching.h
14140new file mode 100644
14141index 00000000..6c056b9a
14142--- /dev/null
14143+++ b/benchmark/feature_stab/db_vlvm/db_feature_matching.h
14144@@ -0,0 +1,260 @@
14145+/*
14146+ * Copyright (C) 2011 The Android Open Source Project
14147+ *
14148+ * Licensed under the Apache License, Version 2.0 (the "License");
14149+ * you may not use this file except in compliance with the License.
14150+ * You may obtain a copy of the License at
14151+ *
14152+ *      http://www.apache.org/licenses/LICENSE-2.0
14153+ *
14154+ * Unless required by applicable law or agreed to in writing, software
14155+ * distributed under the License is distributed on an "AS IS" BASIS,
14156+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14157+ * See the License for the specific language governing permissions and
14158+ * limitations under the License.
14159+ */
14160+
14161+/*$Id: db_feature_matching.h,v 1.3 2011/06/17 14:03:30 mbansal Exp $*/
14162+
14163+#ifndef DB_FEATURE_MATCHING_H
14164+#define DB_FEATURE_MATCHING_H
14165+
14166+/*****************************************************************
14167+*    Lean and mean begins here                                   *
14168+*****************************************************************/
14169+/*!
14170+ * \defgroup FeatureMatching Feature Matching
14171+ */
14172+#include "db_utilities.h"
14173+#include "db_utilities_constants.h"
14174+
14175+DB_API void db_SignedSquareNormCorr21x21_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip);
14176+DB_API void db_SignedSquareNormCorr11x11_PreAlign_u(short *patch,const unsigned char * const *f_img,int x_f,int y_f,float *sum,float *recip);
14177+float db_SignedSquareNormCorr21x21Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip);
14178+float db_SignedSquareNormCorr11x11Aligned_Post_s(const short *f_patch,const short *g_patch,float fsum_gsum,float f_recip_g_recip);
14179+
14180+class db_PointInfo_f
14181+{
14182+public:
14183+    /*Coordinates of point*/
14184+    int x;
14185+    int y;
14186+    /*Id nr of point*/
14187+    int id;
14188+    /*Best match score*/
14189+    double s;
14190+    /*Best match candidate*/
14191+    db_PointInfo_f *pir;
14192+    /*Precomputed coefficients
14193+    of image patch*/
14194+    float sum;
14195+    float recip;
14196+    /*Pointer to patch layout*/
14197+    const float *patch;
14198+};
14199+
14200+class db_Bucket_f
14201+{
14202+public:
14203+    db_PointInfo_f *ptr;
14204+    int nr;
14205+};
14206+
14207+class db_PointInfo_u
14208+{
14209+public:
14210+    /*Coordinates of point*/
14211+    int x;
14212+    int y;
14213+    /*Id nr of point*/
14214+    int id;
14215+    /*Best match score*/
14216+    double s;
14217+    /*Best match candidate*/
14218+    db_PointInfo_u *pir;
14219+    /*Precomputed coefficients
14220+    of image patch*/
14221+    float sum;
14222+    float recip;
14223+    /*Pointer to patch layout*/
14224+    const short *patch;
14225+};
14226+
14227+class db_Bucket_u
14228+{
14229+public:
14230+    db_PointInfo_u *ptr;
14231+    int nr;
14232+};
14233+/*!
14234+ * \class db_Matcher_f
14235+ * \ingroup FeatureMatching
14236+ * \brief Feature matcher for float images.
14237+ *
14238+ * Normalized correlation feature matcher for <b>float</b> images.
14239+ * Correlation window size is constant and set to 11x11.
14240+ * See \ref FeatureDetection to detect Harris corners.
14241+ * Images are managed with functions in \ref LMImageBasicUtilities.
14242+ */
14243+class DB_API db_Matcher_f
14244+{
14245+public:
14246+    db_Matcher_f();
14247+    ~db_Matcher_f();
14248+
14249+    /*!
14250+     * Set parameters and pre-allocate memory. Return an upper bound
14251+     * on the number of matches.
14252+     * \param im_width          width
14253+     * \param im_height         height
14254+     * \param max_disparity     maximum distance (as fraction of image size) between matches
14255+     * \param target_nr_corners maximum number of matches
14256+     * \return maximum number of matches
14257+     */
14258+    unsigned long Init(int im_width,int im_height,
14259+        double max_disparity=DB_DEFAULT_MAX_DISPARITY,
14260+        int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS);
14261+
14262+    /*!
14263+     * Match two sets of features.
14264+     * If the prewarp H is not NULL it will be applied to the features
14265+     * in the right image before matching.
14266+     * Parameters id_l and id_r must point to arrays of size target_nr_corners
14267+     * (returned by Init()).
14268+     * The results of matching are in id_l and id_r.
14269+     * Interpretaqtion of results: if id_l[i] = m and id_r[i] = n,
14270+     * feature at (x_l[m],y_l[m]) matched to (x_r[n],y_r[n]).
14271+     * \param l_img     left image
14272+     * \param r_img     right image
14273+     * \param x_l       left x coordinates of features
14274+     * \param y_l       left y coordinates of features
14275+     * \param nr_l      number of features in left image
14276+     * \param x_r       right x coordinates of features
14277+     * \param y_r       right y coordinates of features
14278+     * \param nr_r      number of features in right image
14279+     * \param id_l      indices of left features that matched
14280+     * \param id_r      indices of right features that matched
14281+     * \param nr_matches    number of features actually matched
14282+     * \param H         image homography (prewarp) to be applied to right image features
14283+     */
14284+    void Match(const float * const *l_img,const float * const *r_img,
14285+        const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r,
14286+        int *id_l,int *id_r,int *nr_matches,const double H[9]=0);
14287+
14288+protected:
14289+    void Clean();
14290+
14291+    int m_w,m_h,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,m_target;
14292+    unsigned long m_kA,m_kB;
14293+    db_Bucket_f **m_bp_l;
14294+    db_Bucket_f **m_bp_r;
14295+    float *m_patch_space,*m_aligned_patch_space;
14296+};
14297+/*!
14298+ * \class db_Matcher_u
14299+ * \ingroup FeatureMatching
14300+ * \brief Feature matcher for byte images.
14301+ *
14302+ * Normalized correlation feature matcher for <b>byte</b> images.
14303+ * Correlation window size is constant and set to 11x11.
14304+ * See \ref FeatureDetection to detect Harris corners.
14305+ * Images are managed with functions in \ref LMImageBasicUtilities.
14306+ *
14307+ * If the prewarp matrix H is supplied, the feature coordinates are warped by H before being placed in
14308+ * appropriate buckets. If H is an affine transform and the "affine" parameter is set to 1 or 2,
14309+ * then the correlation patches themselves are warped before being placed in the patch space.
14310+ */
14311+class DB_API db_Matcher_u
14312+{
14313+public:
14314+    db_Matcher_u();
14315+
14316+    int GetPatchSize(){return 11;};
14317+
14318+    virtual ~db_Matcher_u();
14319+
14320+    /*!
14321+     Copy ctor duplicates settings.
14322+     Memory not copied.
14323+     */
14324+    db_Matcher_u(const db_Matcher_u& cm);
14325+
14326+    /*!
14327+     Assignment optor duplicates settings
14328+     Memory not copied.
14329+     */
14330+    db_Matcher_u& operator= (const db_Matcher_u& cm);
14331+
14332+    /*!
14333+     * Set parameters and pre-allocate memory. Return an upper bound
14334+     * on the number of matches.
14335+     * If max_disparity_v is DB_DEFAULT_NO_DISPARITY, look for matches
14336+     * in a ellipse around a feature of radius max_disparity*im_width by max_disparity*im_height.
14337+     * If max_disparity_v is specified, use a rectangle max_disparity*im_width by max_disparity_v*im_height.
14338+     * \param im_width          width
14339+     * \param im_height         height
14340+     * \param max_disparity     maximum distance (as fraction of image size) between matches
14341+     * \param target_nr_corners maximum number of matches
14342+     * \param max_disparity_v   maximum vertical disparity (distance between matches)
14343+     * \param use_smaller_matching_window   if set to true, uses a correlation window of 5x5 instead of the default 11x11
14344+     * \return maximum number of matches
14345+     */
14346+    virtual unsigned long Init(int im_width,int im_height,
14347+        double max_disparity=DB_DEFAULT_MAX_DISPARITY,
14348+        int target_nr_corners=DB_DEFAULT_TARGET_NR_CORNERS,
14349+        double max_disparity_v=DB_DEFAULT_NO_DISPARITY,
14350+        bool use_smaller_matching_window=false, int use_21=0);
14351+
14352+    /*!
14353+     * Match two sets of features.
14354+     * If the prewarp H is not NULL it will be applied to the features
14355+     * in the right image before matching.
14356+     * Parameters id_l and id_r must point to arrays of size target_nr_corners
14357+     * (returned by Init()).
14358+     * The results of matching are in id_l and id_r.
14359+     * Interpretaqtion of results: if id_l[i] = m and id_r[i] = n,
14360+     * feature at (x_l[m],y_l[m]) matched to (x_r[n],y_r[n]).
14361+     * \param l_img     left image
14362+     * \param r_img     right image
14363+     * \param x_l       left x coordinates of features
14364+     * \param y_l       left y coordinates of features
14365+     * \param nr_l      number of features in left image
14366+     * \param x_r       right x coordinates of features
14367+     * \param y_r       right y coordinates of features
14368+     * \param nr_r      number of features in right image
14369+     * \param id_l      indices of left features that matched
14370+     * \param id_r      indices of right features that matched
14371+     * \param nr_matches    number of features actually matched
14372+     * \param H         image homography (prewarp) to be applied to right image features
14373+     * \param affine    prewarp the 11x11 patches by given affine transform. 0 means no warping,
14374+                        1 means nearest neighbor, 2 means bilinear warping.
14375+     */
14376+    virtual void Match(const unsigned char * const *l_img,const unsigned char * const *r_img,
14377+        const double *x_l,const double *y_l,int nr_l,const double *x_r,const double *y_r,int nr_r,
14378+        int *id_l,int *id_r,int *nr_matches,const double H[9]=0,int affine=0);
14379+
14380+    /*!
14381+     * Checks if Init() was called.
14382+     * \return 1 if Init() was called, 0 otherwise.
14383+     */
14384+    int IsAllocated();
14385+
14386+protected:
14387+    virtual void Clean();
14388+
14389+
14390+    int m_w,m_h,m_bw,m_bh,m_nr_h,m_nr_v,m_bd,m_target;
14391+    unsigned long m_kA,m_kB;
14392+    db_Bucket_u **m_bp_l;
14393+    db_Bucket_u **m_bp_r;
14394+    short *m_patch_space,*m_aligned_patch_space;
14395+
14396+    double m_max_disparity, m_max_disparity_v;
14397+    int m_rect_window;
14398+    bool m_use_smaller_matching_window;
14399+    int m_use_21;
14400+};
14401+
14402+
14403+
14404+#endif /*DB_FEATURE_MATCHING_H*/
14405diff --git a/benchmark/feature_stab/db_vlvm/db_framestitching.cpp b/benchmark/feature_stab/db_vlvm/db_framestitching.cpp
14406new file mode 100644
14407index 00000000..b574f7a0
14408--- /dev/null
14409+++ b/benchmark/feature_stab/db_vlvm/db_framestitching.cpp
14410@@ -0,0 +1,169 @@
14411+/*
14412+ * Copyright (C) 2011 The Android Open Source Project
14413+ *
14414+ * Licensed under the Apache License, Version 2.0 (the "License");
14415+ * you may not use this file except in compliance with the License.
14416+ * You may obtain a copy of the License at
14417+ *
14418+ *      http://www.apache.org/licenses/LICENSE-2.0
14419+ *
14420+ * Unless required by applicable law or agreed to in writing, software
14421+ * distributed under the License is distributed on an "AS IS" BASIS,
14422+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14423+ * See the License for the specific language governing permissions and
14424+ * limitations under the License.
14425+ */
14426+
14427+/* $Id: db_framestitching.cpp,v 1.2 2011/06/17 14:03:30 mbansal Exp $ */
14428+
14429+#include "db_utilities.h"
14430+#include "db_framestitching.h"
14431+
14432+
14433+
14434+/*****************************************************************
14435+*    Lean and mean begins here                                   *
14436+*****************************************************************/
14437+
14438+inline void db_RotationFromMOuterProductSum(double R[9],double *score,double M[9])
14439+{
14440+    double N[16],q[4],lambda[4],lambda_max;
14441+    double y[4];
14442+    int nr_roots;
14443+
14444+    N[0]=   M[0]+M[4]+M[8];
14445+    N[5]=   M[0]-M[4]-M[8];
14446+    N[10]= -M[0]+M[4]-M[8];
14447+    N[15]= -M[0]-M[4]+M[8];
14448+    N[1] =N[4] =M[5]-M[7];
14449+    N[2] =N[8] =M[6]-M[2];
14450+    N[3] =N[12]=M[1]-M[3];
14451+    N[6] =N[9] =M[1]+M[3];
14452+    N[7] =N[13]=M[6]+M[2];
14453+    N[11]=N[14]=M[5]+M[7];
14454+
14455+    /*get the quaternion representing the rotation
14456+    by finding the eigenvector corresponding to the most
14457+    positive eigenvalue. Force eigenvalue solutions, since the matrix
14458+    is symmetric and solutions might otherwise be lost
14459+    when the data is planar*/
14460+    db_RealEigenvalues4x4(lambda,&nr_roots,N,1);
14461+    if(nr_roots)
14462+    {
14463+        lambda_max=lambda[0];
14464+        if(nr_roots>=2)
14465+        {
14466+            if(lambda[1]>lambda_max) lambda_max=lambda[1];
14467+            if(nr_roots>=3)
14468+            {
14469+                if(lambda[2]>lambda_max) lambda_max=lambda[2];
14470+                {
14471+                    if(nr_roots>=4) if(lambda[3]>lambda_max) lambda_max=lambda[3];
14472+                }
14473+            }
14474+        }
14475+    }
14476+    else lambda_max=1.0;
14477+    db_EigenVector4x4(q,lambda_max,N);
14478+
14479+    /*Compute the rotation matrix*/
14480+    db_QuaternionToRotation(R,q);
14481+
14482+    if(score)
14483+    {
14484+        /*Compute score=transpose(q)*N*q */
14485+        db_Multiply4x4_4x1(y,N,q);
14486+        *score=db_ScalarProduct4(q,y);
14487+    }
14488+}
14489+
14490+void db_StitchSimilarity3DRaw(double *scale,double R[9],double t[3],
14491+                            double **Xp,double **X,int nr_points,int orientation_preserving,
14492+                            int allow_scaling,int allow_rotation,int allow_translation)
14493+{
14494+    int i;
14495+    double c[3],cp[3],r[3],rp[3],M[9],s,sp,sc;
14496+    double Rr[9],score_p,score_r;
14497+    double *temp,*temp_p;
14498+
14499+    if(allow_translation)
14500+    {
14501+        db_PointCentroid3D(c,X,nr_points);
14502+        db_PointCentroid3D(cp,Xp,nr_points);
14503+    }
14504+    else
14505+    {
14506+        db_Zero3(c);
14507+        db_Zero3(cp);
14508+    }
14509+
14510+    db_Zero9(M);
14511+    s=sp=0;
14512+    for(i=0;i<nr_points;i++)
14513+    {
14514+        temp=   *X++;
14515+        temp_p= *Xp++;
14516+        r[0]=(*temp++)-c[0];
14517+        r[1]=(*temp++)-c[1];
14518+        r[2]=(*temp++)-c[2];
14519+        rp[0]=(*temp_p++)-cp[0];
14520+        rp[1]=(*temp_p++)-cp[1];
14521+        rp[2]=(*temp_p++)-cp[2];
14522+
14523+        M[0]+=r[0]*rp[0];
14524+        M[1]+=r[0]*rp[1];
14525+        M[2]+=r[0]*rp[2];
14526+        M[3]+=r[1]*rp[0];
14527+        M[4]+=r[1]*rp[1];
14528+        M[5]+=r[1]*rp[2];
14529+        M[6]+=r[2]*rp[0];
14530+        M[7]+=r[2]*rp[1];
14531+        M[8]+=r[2]*rp[2];
14532+
14533+        s+=db_sqr(r[0])+db_sqr(r[1])+db_sqr(r[2]);
14534+        sp+=db_sqr(rp[0])+db_sqr(rp[1])+db_sqr(rp[2]);
14535+    }
14536+
14537+    /*Compute scale*/
14538+    if(allow_scaling) sc=sqrt(db_SafeDivision(sp,s));
14539+    else sc=1.0;
14540+    *scale=sc;
14541+
14542+    /*Compute rotation*/
14543+    if(allow_rotation)
14544+    {
14545+        if(orientation_preserving)
14546+        {
14547+            db_RotationFromMOuterProductSum(R,0,M);
14548+        }
14549+        else
14550+        {
14551+            /*Try preserving*/
14552+            db_RotationFromMOuterProductSum(R,&score_p,M);
14553+            /*Try reversing*/
14554+            M[6]= -M[6];
14555+            M[7]= -M[7];
14556+            M[8]= -M[8];
14557+            db_RotationFromMOuterProductSum(Rr,&score_r,M);
14558+            if(score_r>score_p)
14559+            {
14560+                /*Reverse is better*/
14561+                R[0]=Rr[0]; R[1]=Rr[1]; R[2]= -Rr[2];
14562+                R[3]=Rr[3]; R[4]=Rr[4]; R[5]= -Rr[5];
14563+                R[6]=Rr[6]; R[7]=Rr[7]; R[8]= -Rr[8];
14564+            }
14565+        }
14566+    }
14567+    else db_Identity3x3(R);
14568+
14569+    /*Compute translation*/
14570+    if(allow_translation)
14571+    {
14572+        t[0]=cp[0]-sc*(R[0]*c[0]+R[1]*c[1]+R[2]*c[2]);
14573+        t[1]=cp[1]-sc*(R[3]*c[0]+R[4]*c[1]+R[5]*c[2]);
14574+        t[2]=cp[2]-sc*(R[6]*c[0]+R[7]*c[1]+R[8]*c[2]);
14575+    }
14576+    else db_Zero3(t);
14577+}
14578+
14579+
14580diff --git a/benchmark/feature_stab/db_vlvm/db_framestitching.h b/benchmark/feature_stab/db_vlvm/db_framestitching.h
14581new file mode 100644
14582index 00000000..5fef5f37
14583--- /dev/null
14584+++ b/benchmark/feature_stab/db_vlvm/db_framestitching.h
14585@@ -0,0 +1,94 @@
14586+/*
14587+ * Copyright (C) 2011 The Android Open Source Project
14588+ *
14589+ * Licensed under the Apache License, Version 2.0 (the "License");
14590+ * you may not use this file except in compliance with the License.
14591+ * You may obtain a copy of the License at
14592+ *
14593+ *      http://www.apache.org/licenses/LICENSE-2.0
14594+ *
14595+ * Unless required by applicable law or agreed to in writing, software
14596+ * distributed under the License is distributed on an "AS IS" BASIS,
14597+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14598+ * See the License for the specific language governing permissions and
14599+ * limitations under the License.
14600+ */
14601+
14602+/* $Id: db_framestitching.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
14603+
14604+#ifndef DB_FRAMESTITCHING_H
14605+#define DB_FRAMESTITCHING_H
14606+/*!
14607+ * \defgroup FrameStitching Frame Stitching (2D and 3D homography estimation)
14608+ */
14609+/*\{*/
14610+
14611+
14612+/*****************************************************************
14613+*    Lean and mean begins here                                   *
14614+*****************************************************************/
14615+/*!
14616+ * \defgroup LMFrameStitching (LM) Frame Stitching (2D and 3D homography estimation)
14617+ */
14618+/*\{*/
14619+
14620+/*!
14621+Find scale, rotation and translation of the similarity that
14622+takes the nr_points inhomogenous 3D points X to Xp
14623+(left to right according to Horn), i.e. for the homogenous equivalents
14624+Xp and X we would have
14625+\code
14626+    Xp~
14627+    [sR t]*X
14628+    [0  1]
14629+\endcode
14630+If orientation_preserving is true, R is restricted such that det(R)>0.
14631+allow_scaling, allow_rotation and allow_translation allow s,R and t
14632+to differ from 1,Identity and 0
14633+
14634+Full similarity takes the following on 550MHz:
14635+\code
14636+4.5 microseconds with       3 points
14637+4.7 microseconds with       4 points
14638+5.0 microseconds with       5 points
14639+5.2 microseconds with       6 points
14640+5.8 microseconds with      10 points
14641+20  microseconds with     100 points
14642+205 microseconds with    1000 points
14643+2.9 milliseconds with   10000 points
14644+50  milliseconds with  100000 points
14645+0.5 seconds      with 1000000 points
14646+\endcode
14647+Without orientation_preserving:
14648+\code
14649+4 points is minimal for (s,R,t) (R,t)
14650+3 points is minimal for (s,R) (R)
14651+2 points is minimal for (s,t)
14652+1 point is minimal for  (s) (t)
14653+\endcode
14654+With orientation_preserving:
14655+\code
14656+3 points is minimal for (s,R,t) (R,t)
14657+2 points is minimal for (s,R) (s,t) (R)
14658+1 point is minimal for  (s) (t)
14659+\endcode
14660+
14661+\param scale                    scale
14662+\param R                        rotation
14663+\param t                        translation
14664+\param Xp                       inhomogenouse 3D points in first coordinate system
14665+\param X                        inhomogenouse 3D points in second coordinate system
14666+\param nr_points                number of points
14667+\param orientation_preserving   if true, R is restricted such that det(R)>0.
14668+\param allow_scaling            estimate scale
14669+\param allow_rotation           estimate rotation
14670+\param allow_translation        estimate translation
14671+*/
14672+DB_API void db_StitchSimilarity3DRaw(double *scale,double R[9],double t[3],
14673+                            double **Xp,double **X,int nr_points,int orientation_preserving=1,
14674+                            int allow_scaling=1,int allow_rotation=1,int allow_translation=1);
14675+
14676+
14677+/*\}*/
14678+
14679+#endif /* DB_FRAMESTITCHING_H */
14680diff --git a/benchmark/feature_stab/db_vlvm/db_image_homography.cpp b/benchmark/feature_stab/db_vlvm/db_image_homography.cpp
14681new file mode 100644
14682index 00000000..aaad7f85
14683--- /dev/null
14684+++ b/benchmark/feature_stab/db_vlvm/db_image_homography.cpp
14685@@ -0,0 +1,332 @@
14686+/*
14687+ * Copyright (C) 2011 The Android Open Source Project
14688+ *
14689+ * Licensed under the Apache License, Version 2.0 (the "License");
14690+ * you may not use this file except in compliance with the License.
14691+ * You may obtain a copy of the License at
14692+ *
14693+ *      http://www.apache.org/licenses/LICENSE-2.0
14694+ *
14695+ * Unless required by applicable law or agreed to in writing, software
14696+ * distributed under the License is distributed on an "AS IS" BASIS,
14697+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14698+ * See the License for the specific language governing permissions and
14699+ * limitations under the License.
14700+ */
14701+
14702+/* $Id: db_image_homography.cpp,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
14703+
14704+#include "db_utilities.h"
14705+#include "db_image_homography.h"
14706+#include "db_framestitching.h"
14707+#include "db_metrics.h"
14708+
14709+
14710+
14711+/*****************************************************************
14712+*    Lean and mean begins here                                   *
14713+*****************************************************************/
14714+
14715+/*Compute the linear constraint on H obtained by requiring that the
14716+ratio between coordinate i_num and i_den of xp is equal to the ratio
14717+between coordinate i_num and i_den of Hx. i_zero should be set to
14718+the coordinate not equal to i_num or i_den. No normalization is used*/
14719+inline void db_SProjImagePointPointConstraint(double c[9],int i_num,int i_den,int i_zero,
14720+                           double xp[3],double x[3])
14721+{
14722+    db_MultiplyScalarCopy3(c+3*i_den,x,  xp[i_num]);
14723+    db_MultiplyScalarCopy3(c+3*i_num,x, -xp[i_den]);
14724+    db_Zero3(c+3*i_zero);
14725+}
14726+
14727+/*Compute two constraints on H generated by the correspondence (Xp,X),
14728+assuming that Xp ~= H*X. No normalization is used*/
14729+inline void db_SProjImagePointPointConstraints(double c1[9],double c2[9],double xp[3],double x[3])
14730+{
14731+    int ma_ind;
14732+
14733+    /*Find index of coordinate of Xp with largest absolute value*/
14734+    ma_ind=db_MaxAbsIndex3(xp);
14735+
14736+    /*Generate 2 constraints,
14737+    each constraint is generated by considering the ratio between a
14738+    coordinate and the largest absolute value coordinate*/
14739+    switch(ma_ind)
14740+    {
14741+    case 0:
14742+        db_SProjImagePointPointConstraint(c1,1,0,2,xp,x);
14743+        db_SProjImagePointPointConstraint(c2,2,0,1,xp,x);
14744+        break;
14745+    case 1:
14746+        db_SProjImagePointPointConstraint(c1,0,1,2,xp,x);
14747+        db_SProjImagePointPointConstraint(c2,2,1,0,xp,x);
14748+        break;
14749+    default:
14750+        db_SProjImagePointPointConstraint(c1,0,2,1,xp,x);
14751+        db_SProjImagePointPointConstraint(c2,1,2,0,xp,x);
14752+    }
14753+}
14754+
14755+inline void db_SAffineImagePointPointConstraints(double c1[7],double c2[7],double xp[3],double x[3])
14756+{
14757+    double ct1[9],ct2[9];
14758+
14759+    db_SProjImagePointPointConstraints(ct1,ct2,xp,x);
14760+    db_Copy6(c1,ct1); c1[6]=ct1[8];
14761+    db_Copy6(c2,ct2); c2[6]=ct2[8];
14762+}
14763+
14764+void db_StitchProjective2D_4Points(double H[9],
14765+                                      double x1[3],double x2[3],double x3[3],double x4[3],
14766+                                      double xp1[3],double xp2[3],double xp3[3],double xp4[3])
14767+{
14768+    double c[72];
14769+
14770+    /*Collect the constraints*/
14771+    db_SProjImagePointPointConstraints(c   ,c+9 ,xp1,x1);
14772+    db_SProjImagePointPointConstraints(c+18,c+27,xp2,x2);
14773+    db_SProjImagePointPointConstraints(c+36,c+45,xp3,x3);
14774+    db_SProjImagePointPointConstraints(c+54,c+63,xp4,x4);
14775+    /*Solve for the nullvector*/
14776+    db_NullVector8x9Destructive(H,c);
14777+}
14778+
14779+void db_StitchAffine2D_3Points(double H[9],
14780+                                      double x1[3],double x2[3],double x3[3],
14781+                                      double xp1[3],double xp2[3],double xp3[3])
14782+{
14783+    double c[42];
14784+
14785+    /*Collect the constraints*/
14786+    db_SAffineImagePointPointConstraints(c   ,c+7 ,xp1,x1);
14787+    db_SAffineImagePointPointConstraints(c+14,c+21,xp2,x2);
14788+    db_SAffineImagePointPointConstraints(c+28,c+35,xp3,x3);
14789+    /*Solve for the nullvector*/
14790+    db_NullVector6x7Destructive(H,c);
14791+    db_MultiplyScalar6(H,db_SafeReciprocal(H[6]));
14792+    H[6]=H[7]=0; H[8]=1.0;
14793+}
14794+
14795+/*Compute up to three solutions for the focal length given two point correspondences
14796+generated by a rotation with a common unknown focal length. No specific normalization
14797+of the input points is required. If signed_disambiguation is true, the points are
14798+required to be in front of the camera*/
14799+inline void db_CommonFocalLengthFromRotation_2Point(double fsol[3],int *nr_sols,double x1[3],double x2[3],double xp1[3],double xp2[3],int signed_disambiguation=1)
14800+{
14801+    double m,ax,ay,apx,apy,bx,by,bpx,bpy;
14802+    double p1[2],p2[2],p3[2],p4[2],p5[2],p6[2];
14803+    double p7[3],p8[4],p9[5],p10[3],p11[4];
14804+    double roots[3];
14805+    int nr_roots,i,j;
14806+
14807+    /*Solve for focal length using the equation
14808+    <a,b>^2*<ap,ap><bp,bp>=<ap,bp>^2*<a,a><b,b>
14809+    where a and ap are the homogenous vectors in the first image
14810+    after focal length scaling and b,bp are the vectors in the
14811+    second image*/
14812+
14813+    /*Normalize homogenous coordinates so that last coordinate is one*/
14814+    m=db_SafeReciprocal(x1[2]);
14815+    ax=x1[0]*m;
14816+    ay=x1[1]*m;
14817+    m=db_SafeReciprocal(xp1[2]);
14818+    apx=xp1[0]*m;
14819+    apy=xp1[1]*m;
14820+    m=db_SafeReciprocal(x2[2]);
14821+    bx=x2[0]*m;
14822+    by=x2[1]*m;
14823+    m=db_SafeReciprocal(xp2[2]);
14824+    bpx=xp2[0]*m;
14825+    bpy=xp2[1]*m;
14826+
14827+    /*Compute cubic in l=1/(f^2)
14828+    by dividing out the root l=0 from the equation
14829+    (l(ax*bx+ay*by)+1)^2*(l(apx^2+apy^2)+1)*(l(bpx^2+bpy^2)+1)=
14830+    (l(apx*bpx+apy*bpy)+1)^2*(l(ax^2+ay^2)+1)*(l(bx^2+by^2)+1)*/
14831+    p1[1]=ax*bx+ay*by;
14832+    p2[1]=db_sqr(apx)+db_sqr(apy);
14833+    p3[1]=db_sqr(bpx)+db_sqr(bpy);
14834+    p4[1]=apx*bpx+apy*bpy;
14835+    p5[1]=db_sqr(ax)+db_sqr(ay);
14836+    p6[1]=db_sqr(bx)+db_sqr(by);
14837+    p1[0]=p2[0]=p3[0]=p4[0]=p5[0]=p6[0]=1;
14838+
14839+    db_MultiplyPoly1_1(p7,p1,p1);
14840+    db_MultiplyPoly1_2(p8,p2,p7);
14841+    db_MultiplyPoly1_3(p9,p3,p8);
14842+
14843+    db_MultiplyPoly1_1(p10,p4,p4);
14844+    db_MultiplyPoly1_2(p11,p5,p10);
14845+    db_SubtractPolyProduct1_3(p9,p6,p11);
14846+    /*Cubic starts at p9[1]*/
14847+    db_SolveCubic(roots,&nr_roots,p9[4],p9[3],p9[2],p9[1]);
14848+
14849+    for(j=0,i=0;i<nr_roots;i++)
14850+    {
14851+        if(roots[i]>0)
14852+        {
14853+            if((!signed_disambiguation) || (db_PolyEval1(p1,roots[i])*db_PolyEval1(p4,roots[i])>0))
14854+            {
14855+                fsol[j++]=db_SafeSqrtReciprocal(roots[i]);
14856+            }
14857+        }
14858+    }
14859+    *nr_sols=j;
14860+}
14861+
14862+int db_StitchRotationCommonFocalLength_3Points(double H[9],double x1[3],double x2[3],double x3[3],double xp1[3],double xp2[3],double xp3[3],double *f,int signed_disambiguation)
14863+{
14864+    double fsol[3];
14865+    int nr_sols,i,best_sol,done;
14866+    double cost,best_cost;
14867+    double m,hyp[27],x1_temp[3],x2_temp[3],xp1_temp[3],xp2_temp[3];
14868+    double *hyp_point,ft;
14869+    double y[2];
14870+
14871+    db_CommonFocalLengthFromRotation_2Point(fsol,&nr_sols,x1,x2,xp1,xp2,signed_disambiguation);
14872+    if(nr_sols)
14873+    {
14874+        db_DeHomogenizeImagePoint(y,xp3);
14875+        done=0;
14876+        for(i=0;i<nr_sols;i++)
14877+        {
14878+            ft=fsol[i];
14879+            m=db_SafeReciprocal(ft);
14880+            x1_temp[0]=x1[0]*m;
14881+            x1_temp[1]=x1[1]*m;
14882+            x1_temp[2]=x1[2];
14883+            x2_temp[0]=x2[0]*m;
14884+            x2_temp[1]=x2[1]*m;
14885+            x2_temp[2]=x2[2];
14886+            xp1_temp[0]=xp1[0]*m;
14887+            xp1_temp[1]=xp1[1]*m;
14888+            xp1_temp[2]=xp1[2];
14889+            xp2_temp[0]=xp2[0]*m;
14890+            xp2_temp[1]=xp2[1]*m;
14891+            xp2_temp[2]=xp2[2];
14892+
14893+            hyp_point=hyp+9*i;
14894+            db_StitchCameraRotation_2Points(hyp_point,x1_temp,x2_temp,xp1_temp,xp2_temp);
14895+            hyp_point[2]*=ft;
14896+            hyp_point[5]*=ft;
14897+            hyp_point[6]*=m;
14898+            hyp_point[7]*=m;
14899+            cost=db_SquaredReprojectionErrorHomography(y,hyp_point,x3);
14900+
14901+            if(!done || cost<best_cost)
14902+            {
14903+                done=1;
14904+                best_cost=cost;
14905+                best_sol=i;
14906+            }
14907+        }
14908+
14909+        if(f) *f=fsol[best_sol];
14910+        db_Copy9(H,hyp+9*best_sol);
14911+        return(1);
14912+    }
14913+    else
14914+    {
14915+        db_Identity3x3(H);
14916+        if(f) *f=1.0;
14917+        return(0);
14918+    }
14919+}
14920+
14921+void db_StitchSimilarity2DRaw(double *scale,double R[4],double t[2],
14922+                            double **Xp,double **X,int nr_points,int orientation_preserving,
14923+                            int allow_scaling,int allow_rotation,int allow_translation)
14924+{
14925+    int i;
14926+    double c[2],cp[2],r[2],rp[2],M[4],s,sp,sc;
14927+    double *temp,*temp_p;
14928+    double Aacc,Bacc,Aacc2,Bacc2,divisor,divisor2,m,Am,Bm;
14929+
14930+    if(allow_translation)
14931+    {
14932+        db_PointCentroid2D(c,X,nr_points);
14933+        db_PointCentroid2D(cp,Xp,nr_points);
14934+    }
14935+    else
14936+    {
14937+        db_Zero2(c);
14938+        db_Zero2(cp);
14939+    }
14940+
14941+    db_Zero4(M);
14942+    s=sp=0;
14943+    for(i=0;i<nr_points;i++)
14944+    {
14945+        temp=   *X++;
14946+        temp_p= *Xp++;
14947+        r[0]=(*temp++)-c[0];
14948+        r[1]=(*temp++)-c[1];
14949+        rp[0]=(*temp_p++)-cp[0];
14950+        rp[1]=(*temp_p++)-cp[1];
14951+
14952+        M[0]+=r[0]*rp[0];
14953+        M[1]+=r[0]*rp[1];
14954+        M[2]+=r[1]*rp[0];
14955+        M[3]+=r[1]*rp[1];
14956+
14957+        s+=db_sqr(r[0])+db_sqr(r[1]);
14958+        sp+=db_sqr(rp[0])+db_sqr(rp[1]);
14959+    }
14960+
14961+    /*Compute scale*/
14962+    if(allow_scaling) sc=sqrt(db_SafeDivision(sp,s));
14963+    else sc=1.0;
14964+    *scale=sc;
14965+
14966+    /*Compute rotation*/
14967+    if(allow_rotation)
14968+    {
14969+        /*orientation preserving*/
14970+        Aacc=M[0]+M[3];
14971+        Bacc=M[2]-M[1];
14972+        /*orientation reversing*/
14973+        Aacc2=M[0]-M[3];
14974+        Bacc2=M[2]+M[1];
14975+        if(Aacc!=0.0 || Bacc!=0.0)
14976+        {
14977+            divisor=sqrt(Aacc*Aacc+Bacc*Bacc);
14978+            m=db_SafeReciprocal(divisor);
14979+            Am=Aacc*m;
14980+            Bm=Bacc*m;
14981+            R[0]=  Am;
14982+            R[1]=  Bm;
14983+            R[2]= -Bm;
14984+            R[3]=  Am;
14985+        }
14986+        else
14987+        {
14988+            db_Identity2x2(R);
14989+            divisor=0.0;
14990+        }
14991+        if(!orientation_preserving && (Aacc2!=0.0 || Bacc2!=0.0))
14992+        {
14993+            divisor2=sqrt(Aacc2*Aacc2+Bacc2*Bacc2);
14994+            if(divisor2>divisor)
14995+            {
14996+                m=db_SafeReciprocal(divisor2);
14997+                Am=Aacc2*m;
14998+                Bm=Bacc2*m;
14999+                R[0]=  Am;
15000+                R[1]=  Bm;
15001+                R[2]=  Bm;
15002+                R[3]= -Am;
15003+            }
15004+        }
15005+    }
15006+    else db_Identity2x2(R);
15007+
15008+    /*Compute translation*/
15009+    if(allow_translation)
15010+    {
15011+        t[0]=cp[0]-sc*(R[0]*c[0]+R[1]*c[1]);
15012+        t[1]=cp[1]-sc*(R[2]*c[0]+R[3]*c[1]);
15013+    }
15014+    else db_Zero2(t);
15015+}
15016+
15017+
15018diff --git a/benchmark/feature_stab/db_vlvm/db_image_homography.h b/benchmark/feature_stab/db_vlvm/db_image_homography.h
15019new file mode 100644
15020index 00000000..165447dd
15021--- /dev/null
15022+++ b/benchmark/feature_stab/db_vlvm/db_image_homography.h
15023@@ -0,0 +1,183 @@
15024+/*
15025+ * Copyright (C) 2011 The Android Open Source Project
15026+ *
15027+ * Licensed under the Apache License, Version 2.0 (the "License");
15028+ * you may not use this file except in compliance with the License.
15029+ * You may obtain a copy of the License at
15030+ *
15031+ *      http://www.apache.org/licenses/LICENSE-2.0
15032+ *
15033+ * Unless required by applicable law or agreed to in writing, software
15034+ * distributed under the License is distributed on an "AS IS" BASIS,
15035+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15036+ * See the License for the specific language governing permissions and
15037+ * limitations under the License.
15038+ */
15039+
15040+/* $Id: db_image_homography.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
15041+
15042+#ifndef DB_IMAGE_HOMOGRAPHY
15043+#define DB_IMAGE_HOMOGRAPHY
15044+
15045+
15046+
15047+/*****************************************************************
15048+*    Lean and mean begins here                                   *
15049+*****************************************************************/
15050+
15051+#include "db_framestitching.h"
15052+/*!
15053+ * \defgroup LMImageHomography (LM) Image Homography Estimation (feature based)
15054+ */
15055+/*\{*/
15056+/*!
15057+Solve for projective H such that xp~Hx. Prior normalization is not necessary,
15058+although desirable for numerical conditioning
15059+\param H    image projective (out)
15060+\param x1   image 1 point 1
15061+\param x2   image 1 point 2
15062+\param x3   image 1 point 3
15063+\param x4   image 1 point 4
15064+\param xp1  image 2 point 1
15065+\param xp2  image 2 point 2
15066+\param xp3  image 2 point 3
15067+\param xp4  image 2 point 4
15068+*/
15069+DB_API void db_StitchProjective2D_4Points(double H[9],
15070+                                      double x1[3],double x2[3],double x3[3],double x4[3],
15071+                                      double xp1[3],double xp2[3],double xp3[3],double xp4[3]);
15072+
15073+/*!
15074+Solve for affine H such that xp~Hx. Prior normalization is not necessary,
15075+although desirable for numerical conditioning
15076+\param H    image projective (out)
15077+\param x1   image 1 point 1
15078+\param x2   image 1 point 2
15079+\param x3   image 1 point 3
15080+\param xp1  image 2 point 1
15081+\param xp2  image 2 point 2
15082+\param xp3  image 2 point 3
15083+*/
15084+DB_API void db_StitchAffine2D_3Points(double H[9],
15085+                                      double x1[3],double x2[3],double x3[3],
15086+                                      double xp1[3],double xp2[3],double xp3[3]);
15087+
15088+/*!
15089+Solve for rotation R such that xp~Rx.
15090+Image points have to be of unit norm for the least squares to be meaningful.
15091+\param R    image rotation (out)
15092+\param x1   image 1 point 1
15093+\param x2   image 1 point 2
15094+\param xp1  image 2 point 1
15095+\param xp2  image 2 point 2
15096+*/
15097+inline void db_StitchCameraRotation_2Points(double R[9],
15098+                                            /*Image points have to be of unit norm
15099+                                            for the least squares to be meaningful*/
15100+                                            double x1[3],double x2[3],
15101+                                            double xp1[3],double xp2[3])
15102+{
15103+    double* x[2];
15104+    double* xp[2];
15105+    double scale,t[3];
15106+
15107+    x[0]=x1;
15108+    x[1]=x2;
15109+    xp[0]=xp1;
15110+    xp[1]=xp2;
15111+    db_StitchSimilarity3DRaw(&scale,R,t,xp,x,2,1,0,1,0);
15112+}
15113+
15114+/*!
15115+Solve for a homography H generated by a rotation R with a common unknown focal length f, i.e.
15116+H=diag(f,f,1)*R*diag(1/f,1/f,1) such that xp~Hx.
15117+If signed_disambiguation is true, the points are
15118+required to be in front of the camera. No specific normalization of the homogenous points
15119+is required, although it could be desirable to keep x1,x2,xp1 and xp2 of reasonable magnitude.
15120+If a solution is obtained the function returns 1, otherwise 0. If the focal length is desired
15121+a valid pointer should be passed in f
15122+*/
15123+DB_API int db_StitchRotationCommonFocalLength_3Points(double H[9],double x1[3],double x2[3],double x3[3],
15124+                                                      double xp1[3],double xp2[3],double xp3[3],double *f=0,int signed_disambiguation=1);
15125+
15126+/*!
15127+Find scale, rotation and translation of the similarity that
15128+takes the nr_points inhomogenous 2D points X to Xp,
15129+i.e. for the homogenous equivalents
15130+Xp and X we would have
15131+\code
15132+Xp~
15133+[sR t]*X
15134+[0  1]
15135+\endcode
15136+If orientation_preserving is true, R is restricted such that det(R)>0.
15137+allow_scaling, allow_rotation and allow_translation allow s,R and t
15138+to differ from 1,Identity and 0
15139+
15140+Full similarity takes the following on 550MHz:
15141+\code
15142+0.9 microseconds with       2 points
15143+1.0 microseconds with       3 points
15144+1.1 microseconds with       4 points
15145+1.3 microseconds with       5 points
15146+1.4 microseconds with       6 points
15147+1.7 microseconds with      10 points
15148+9   microseconds with     100 points
15149+130 microseconds with    1000 points
15150+1.3 milliseconds with   10000 points
15151+35  milliseconds with  100000 points
15152+350 milliseconds with 1000000 points
15153+\endcode
15154+
15155+Without orientation_preserving:
15156+\code
15157+3 points is minimal for (s,R,t) (R,t)
15158+2 points is minimal for (s,t) (s,R) (R)
15159+1 point is minimal for  (s) (t)
15160+\endcode
15161+
15162+With orientation_preserving:
15163+\code
15164+2 points is minimal for (s,R,t) (R,t) (s,t)
15165+1 point is minimal for (s,R) (R) (s) (t)
15166+\endcode
15167+\param scale        (out)
15168+\param R            2D rotation (out)
15169+\param t            2D translation (out)
15170+\param Xp           (nr_points x 2) pointer to array of image points
15171+\param X            (nr_points x 2 ) pointer to array of image points
15172+\param nr_points    number of points
15173+\param orientation_preserving
15174+\param allow_scaling    compute scale (if 0, scale=1)
15175+\param allow_rotation   compute rotation (if 0, R=[I])
15176+\param allow_translation compute translation (if 0 t = [0,0]')
15177+*/
15178+DB_API void db_StitchSimilarity2DRaw(double *scale,double R[4],double t[2],
15179+                            double **Xp,double **X,int nr_points,int orientation_preserving=1,
15180+                            int allow_scaling=1,int allow_rotation=1,int allow_translation=1);
15181+/*!
15182+See db_StitchRotationCommonFocalLength_3Points().
15183+\param H            Image similarity transformation (out)
15184+\param Xp           (nr_points x 2) pointer to array of image points
15185+\param X            (nr_points x 2) pointer to array of image points
15186+\param nr_points    number of points
15187+\param orientation_preserving
15188+\param allow_scaling    compute scale (if 0, scale=1)
15189+\param allow_rotation   compute rotation (if 0, R=[I])
15190+\param allow_translation compute translation (if 0 t = [0,0]')
15191+*/
15192+inline void db_StitchSimilarity2D(double H[9],double **Xp,double **X,int nr_points,int orientation_preserving=1,
15193+                                  int allow_scaling=1,int allow_rotation=1,int allow_translation=1)
15194+{
15195+    double s,R[4],t[2];
15196+
15197+    db_StitchSimilarity2DRaw(&s,R,t,Xp,X,nr_points,orientation_preserving,
15198+        allow_scaling,allow_rotation,allow_translation);
15199+
15200+    H[0]=s*R[0]; H[1]=s*R[1]; H[2]=t[0];
15201+    H[3]=s*R[2]; H[4]=s*R[3]; H[5]=t[1];
15202+    db_Zero2(H+6);
15203+    H[8]=1.0;
15204+}
15205+/*\}*/
15206+#endif /* DB_IMAGE_HOMOGRAPHY */
15207diff --git a/benchmark/feature_stab/db_vlvm/db_metrics.h b/benchmark/feature_stab/db_vlvm/db_metrics.h
15208new file mode 100644
15209index 00000000..6b95458f
15210--- /dev/null
15211+++ b/benchmark/feature_stab/db_vlvm/db_metrics.h
15212@@ -0,0 +1,408 @@
15213+/*
15214+ * Copyright (C) 2011 The Android Open Source Project
15215+ *
15216+ * Licensed under the Apache License, Version 2.0 (the "License");
15217+ * you may not use this file except in compliance with the License.
15218+ * You may obtain a copy of the License at
15219+ *
15220+ *      http://www.apache.org/licenses/LICENSE-2.0
15221+ *
15222+ * Unless required by applicable law or agreed to in writing, software
15223+ * distributed under the License is distributed on an "AS IS" BASIS,
15224+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15225+ * See the License for the specific language governing permissions and
15226+ * limitations under the License.
15227+ */
15228+
15229+/* $Id: db_metrics.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
15230+
15231+#ifndef DB_METRICS
15232+#define DB_METRICS
15233+
15234+
15235+
15236+/*****************************************************************
15237+*    Lean and mean begins here                                   *
15238+*****************************************************************/
15239+
15240+#include "db_utilities.h"
15241+/*!
15242+ * \defgroup LMMetrics (LM) Metrics
15243+ */
15244+/*\{*/
15245+
15246+
15247+
15248+
15249+/*!
15250+Compute function value fp and Jacobian J of robustifier given input value f*/
15251+inline void db_CauchyDerivative(double J[4],double fp[2],const double f[2],double one_over_scale2)
15252+{
15253+    double x2,y2,r,r2,r2s,one_over_r2,fu,r_fu,one_over_r_fu;
15254+    double one_plus_r2s,half_dfu_dx,half_dfu_dy,coeff,coeff2,coeff3;
15255+    int at_zero;
15256+
15257+    /*The robustifier takes the input (x,y) and makes a new
15258+    vector (xp,yp) where
15259+    xp=sqrt(log(1+(x^2+y^2)*one_over_scale2))*x/sqrt(x^2+y^2)
15260+    yp=sqrt(log(1+(x^2+y^2)*one_over_scale2))*y/sqrt(x^2+y^2)
15261+    The new vector has the property
15262+    xp^2+yp^2=log(1+(x^2+y^2)*one_over_scale2)
15263+    i.e. when it is square-summed it gives the robust
15264+    reprojection error
15265+    Define
15266+    r2=(x^2+y^2) and
15267+    r2s=r2*one_over_scale2
15268+    fu=log(1+r2s)/r2
15269+    then
15270+    xp=sqrt(fu)*x
15271+    yp=sqrt(fu)*y
15272+    and
15273+    d(r2)/dx=2x
15274+    d(r2)/dy=2y
15275+    and
15276+    dfu/dx=d(r2)/dx*(r2s/(1+r2s)-log(1+r2s))/(r2*r2)
15277+    dfu/dy=d(r2)/dy*(r2s/(1+r2s)-log(1+r2s))/(r2*r2)
15278+    and
15279+    d(xp)/dx=1/(2sqrt(fu))*(dfu/dx)*x+sqrt(fu)
15280+    d(xp)/dy=1/(2sqrt(fu))*(dfu/dy)*x
15281+    d(yp)/dx=1/(2sqrt(fu))*(dfu/dx)*y
15282+    d(yp)/dy=1/(2sqrt(fu))*(dfu/dy)*y+sqrt(fu)
15283+    */
15284+
15285+    x2=db_sqr(f[0]);
15286+    y2=db_sqr(f[1]);
15287+    r2=x2+y2;
15288+    r=sqrt(r2);
15289+
15290+    if(r2<=0.0) at_zero=1;
15291+    else
15292+    {
15293+        one_over_r2=1.0/r2;
15294+        r2s=r2*one_over_scale2;
15295+        one_plus_r2s=1.0+r2s;
15296+        fu=log(one_plus_r2s)*one_over_r2;
15297+        r_fu=sqrt(fu);
15298+        if(r_fu<=0.0) at_zero=1;
15299+        else
15300+        {
15301+            one_over_r_fu=1.0/r_fu;
15302+            fp[0]=r_fu*f[0];
15303+            fp[1]=r_fu*f[1];
15304+            /*r2s is always >= 0*/
15305+            coeff=(r2s/one_plus_r2s*one_over_r2-fu)*one_over_r2;
15306+            half_dfu_dx=f[0]*coeff;
15307+            half_dfu_dy=f[1]*coeff;
15308+            coeff2=one_over_r_fu*half_dfu_dx;
15309+            coeff3=one_over_r_fu*half_dfu_dy;
15310+
15311+            J[0]=coeff2*f[0]+r_fu;
15312+            J[1]=coeff3*f[0];
15313+            J[2]=coeff2*f[1];
15314+            J[3]=coeff3*f[1]+r_fu;
15315+            at_zero=0;
15316+        }
15317+    }
15318+    if(at_zero)
15319+    {
15320+        /*Close to zero the robustifying mapping
15321+        becomes identity*sqrt(one_over_scale2)*/
15322+        fp[0]=0.0;
15323+        fp[1]=0.0;
15324+        J[0]=sqrt(one_over_scale2);
15325+        J[1]=0.0;
15326+        J[2]=0.0;
15327+        J[3]=J[0];
15328+    }
15329+}
15330+
15331+inline double db_SquaredReprojectionErrorHomography(const double y[2],const double H[9],const double x[3])
15332+{
15333+    double x0,x1,x2,mult;
15334+    double sd;
15335+
15336+    x0=H[0]*x[0]+H[1]*x[1]+H[2]*x[2];
15337+    x1=H[3]*x[0]+H[4]*x[1]+H[5]*x[2];
15338+    x2=H[6]*x[0]+H[7]*x[1]+H[8]*x[2];
15339+    mult=1.0/((x2!=0.0)?x2:1.0);
15340+    sd=db_sqr((y[0]-x0*mult))+db_sqr((y[1]-x1*mult));
15341+
15342+    return(sd);
15343+}
15344+
15345+inline double db_SquaredInhomogenousHomographyError(const double y[2],const double H[9],const double x[2])
15346+{
15347+    double x0,x1,x2,mult;
15348+    double sd;
15349+
15350+    x0=H[0]*x[0]+H[1]*x[1]+H[2];
15351+    x1=H[3]*x[0]+H[4]*x[1]+H[5];
15352+    x2=H[6]*x[0]+H[7]*x[1]+H[8];
15353+    mult=1.0/((x2!=0.0)?x2:1.0);
15354+    sd=db_sqr((y[0]-x0*mult))+db_sqr((y[1]-x1*mult));
15355+
15356+    return(sd);
15357+}
15358+
15359+/*!
15360+Return a constant divided by likelihood of a Cauchy distributed
15361+reprojection error given the image point y, homography H, image point
15362+point x and the squared scale coefficient one_over_scale2=1.0/(scale*scale)
15363+where scale is the half width at half maximum (hWahM) of the
15364+Cauchy distribution*/
15365+inline double db_ExpCauchyInhomogenousHomographyError(const double y[2],const double H[9],const double x[2],
15366+                                                      double one_over_scale2)
15367+{
15368+    double sd;
15369+    sd=db_SquaredInhomogenousHomographyError(y,H,x);
15370+    return(1.0+sd*one_over_scale2);
15371+}
15372+
15373+/*!
15374+Compute residual vector f between image point y and homography Hx of
15375+image point x. Also compute Jacobian of f with respect
15376+to an update dx of H*/
15377+inline void db_DerivativeInhomHomographyError(double Jf_dx[18],double f[2],const double y[2],const double H[9],
15378+                                              const double x[2])
15379+{
15380+    double xh,yh,zh,mult,mult2,xh_mult2,yh_mult2;
15381+    /*The Jacobian of the inhomogenous coordinates with respect to
15382+    the homogenous is
15383+    [1/zh  0  -xh/(zh*zh)]
15384+    [ 0  1/zh -yh/(zh*zh)]
15385+    The Jacobian of the homogenous coordinates with respect to dH is
15386+    [x0 x1 1  0  0 0  0  0 0]
15387+    [ 0  0 0 x0 x1 1  0  0 0]
15388+    [ 0  0 0  0  0 0 x0 x1 1]
15389+    The output Jacobian is minus their product, i.e.
15390+    [-x0/zh -x1/zh -1/zh    0      0     0    x0*xh/(zh*zh) x1*xh/(zh*zh) xh/(zh*zh)]
15391+    [   0      0     0   -x0/zh -x1/zh -1/zh  x0*yh/(zh*zh) x1*yh/(zh*zh) yh/(zh*zh)]*/
15392+
15393+    /*Compute warped point, which is the same as
15394+    homogenous coordinates of reprojection*/
15395+    xh=H[0]*x[0]+H[1]*x[1]+H[2];
15396+    yh=H[3]*x[0]+H[4]*x[1]+H[5];
15397+    zh=H[6]*x[0]+H[7]*x[1]+H[8];
15398+    mult=1.0/((zh!=0.0)?zh:1.0);
15399+    /*Compute inhomogenous residual*/
15400+    f[0]=y[0]-xh*mult;
15401+    f[1]=y[1]-yh*mult;
15402+    /*Compute Jacobian*/
15403+    mult2=mult*mult;
15404+    xh_mult2=xh*mult2;
15405+    yh_mult2=yh*mult2;
15406+    Jf_dx[0]= -x[0]*mult;
15407+    Jf_dx[1]= -x[1]*mult;
15408+    Jf_dx[2]= -mult;
15409+    Jf_dx[3]=0;
15410+    Jf_dx[4]=0;
15411+    Jf_dx[5]=0;
15412+    Jf_dx[6]=x[0]*xh_mult2;
15413+    Jf_dx[7]=x[1]*xh_mult2;
15414+    Jf_dx[8]=xh_mult2;
15415+    Jf_dx[9]=0;
15416+    Jf_dx[10]=0;
15417+    Jf_dx[11]=0;
15418+    Jf_dx[12]=Jf_dx[0];
15419+    Jf_dx[13]=Jf_dx[1];
15420+    Jf_dx[14]=Jf_dx[2];
15421+    Jf_dx[15]=x[0]*yh_mult2;
15422+    Jf_dx[16]=x[1]*yh_mult2;
15423+    Jf_dx[17]=yh_mult2;
15424+}
15425+
15426+/*!
15427+Compute robust residual vector f between image point y and homography Hx of
15428+image point x. Also compute Jacobian of f with respect
15429+to an update dH of H*/
15430+inline void db_DerivativeCauchyInhomHomographyReprojection(double Jf_dx[18],double f[2],const double y[2],const double H[9],
15431+                                                           const double x[2],double one_over_scale2)
15432+{
15433+    double Jf_dx_loc[18],f_loc[2];
15434+    double J[4],J0,J1,J2,J3;
15435+
15436+    /*Compute reprojection Jacobian*/
15437+    db_DerivativeInhomHomographyError(Jf_dx_loc,f_loc,y,H,x);
15438+    /*Compute robustifier Jacobian*/
15439+    db_CauchyDerivative(J,f,f_loc,one_over_scale2);
15440+
15441+    /*Multiply the robustifier Jacobian with
15442+    the reprojection Jacobian*/
15443+    J0=J[0];J1=J[1];J2=J[2];J3=J[3];
15444+    Jf_dx[0]=J0*Jf_dx_loc[0];
15445+    Jf_dx[1]=J0*Jf_dx_loc[1];
15446+    Jf_dx[2]=J0*Jf_dx_loc[2];
15447+    Jf_dx[3]=                J1*Jf_dx_loc[12];
15448+    Jf_dx[4]=                J1*Jf_dx_loc[13];
15449+    Jf_dx[5]=                J1*Jf_dx_loc[14];
15450+    Jf_dx[6]=J0*Jf_dx_loc[6]+J1*Jf_dx_loc[15];
15451+    Jf_dx[7]=J0*Jf_dx_loc[7]+J1*Jf_dx_loc[16];
15452+    Jf_dx[8]=J0*Jf_dx_loc[8]+J1*Jf_dx_loc[17];
15453+    Jf_dx[9]= J2*Jf_dx_loc[0];
15454+    Jf_dx[10]=J2*Jf_dx_loc[1];
15455+    Jf_dx[11]=J2*Jf_dx_loc[2];
15456+    Jf_dx[12]=                J3*Jf_dx_loc[12];
15457+    Jf_dx[13]=                J3*Jf_dx_loc[13];
15458+    Jf_dx[14]=                J3*Jf_dx_loc[14];
15459+    Jf_dx[15]=J2*Jf_dx_loc[6]+J3*Jf_dx_loc[15];
15460+    Jf_dx[16]=J2*Jf_dx_loc[7]+J3*Jf_dx_loc[16];
15461+    Jf_dx[17]=J2*Jf_dx_loc[8]+J3*Jf_dx_loc[17];
15462+}
15463+/*!
15464+Compute residual vector f between image point y and rotation of
15465+image point x by R. Also compute Jacobian of f with respect
15466+to an update dx of R*/
15467+inline void db_DerivativeInhomRotationReprojection(double Jf_dx[6],double f[2],const double y[2],const double R[9],
15468+                                                   const double x[2])
15469+{
15470+    double xh,yh,zh,mult,mult2,xh_mult2,yh_mult2;
15471+    /*The Jacobian of the inhomogenous coordinates with respect to
15472+    the homogenous is
15473+    [1/zh  0  -xh/(zh*zh)]
15474+    [ 0  1/zh -yh/(zh*zh)]
15475+    The Jacobian at zero of the homogenous coordinates with respect to
15476+    [sin(phi) sin(ohm) sin(kap)] is
15477+    [-rx2   0   rx1 ]
15478+    [  0   rx2 -rx0 ]
15479+    [ rx0 -rx1   0  ]
15480+    The output Jacobian is minus their product, i.e.
15481+    [1+xh*xh/(zh*zh) -xh*yh/(zh*zh)   -yh/zh]
15482+    [xh*yh/(zh*zh)   -1-yh*yh/(zh*zh)  xh/zh]*/
15483+
15484+    /*Compute rotated point, which is the same as
15485+    homogenous coordinates of reprojection*/
15486+    xh=R[0]*x[0]+R[1]*x[1]+R[2];
15487+    yh=R[3]*x[0]+R[4]*x[1]+R[5];
15488+    zh=R[6]*x[0]+R[7]*x[1]+R[8];
15489+    mult=1.0/((zh!=0.0)?zh:1.0);
15490+    /*Compute inhomogenous residual*/
15491+    f[0]=y[0]-xh*mult;
15492+    f[1]=y[1]-yh*mult;
15493+    /*Compute Jacobian*/
15494+    mult2=mult*mult;
15495+    xh_mult2=xh*mult2;
15496+    yh_mult2=yh*mult2;
15497+    Jf_dx[0]= 1.0+xh*xh_mult2;
15498+    Jf_dx[1]= -yh*xh_mult2;
15499+    Jf_dx[2]= -yh*mult;
15500+    Jf_dx[3]= -Jf_dx[1];
15501+    Jf_dx[4]= -1-yh*yh_mult2;
15502+    Jf_dx[5]= xh*mult;
15503+}
15504+
15505+/*!
15506+Compute robust residual vector f between image point y and rotation of
15507+image point x by R. Also compute Jacobian of f with respect
15508+to an update dx of R*/
15509+inline void db_DerivativeCauchyInhomRotationReprojection(double Jf_dx[6],double f[2],const double y[2],const double R[9],
15510+                                                         const double x[2],double one_over_scale2)
15511+{
15512+    double Jf_dx_loc[6],f_loc[2];
15513+    double J[4],J0,J1,J2,J3;
15514+
15515+    /*Compute reprojection Jacobian*/
15516+    db_DerivativeInhomRotationReprojection(Jf_dx_loc,f_loc,y,R,x);
15517+    /*Compute robustifier Jacobian*/
15518+    db_CauchyDerivative(J,f,f_loc,one_over_scale2);
15519+
15520+    /*Multiply the robustifier Jacobian with
15521+    the reprojection Jacobian*/
15522+    J0=J[0];J1=J[1];J2=J[2];J3=J[3];
15523+    Jf_dx[0]=J0*Jf_dx_loc[0]+J1*Jf_dx_loc[3];
15524+    Jf_dx[1]=J0*Jf_dx_loc[1]+J1*Jf_dx_loc[4];
15525+    Jf_dx[2]=J0*Jf_dx_loc[2]+J1*Jf_dx_loc[5];
15526+    Jf_dx[3]=J2*Jf_dx_loc[0]+J3*Jf_dx_loc[3];
15527+    Jf_dx[4]=J2*Jf_dx_loc[1]+J3*Jf_dx_loc[4];
15528+    Jf_dx[5]=J2*Jf_dx_loc[2]+J3*Jf_dx_loc[5];
15529+}
15530+
15531+
15532+
15533+/*!
15534+// remove the outliers whose projection error is larger than pre-defined
15535+*/
15536+inline int db_RemoveOutliers_Homography(const double H[9], double *x_i,double *xp_i, double *wp,double *im, double *im_p, double *im_r, double *im_raw,double *im_raw_p,int point_count,double scale, double thresh=DB_OUTLIER_THRESHOLD)
15537+{
15538+    double temp_valueE, t2;
15539+    int c;
15540+    int k1=0;
15541+    int k2=0;
15542+    int k3=0;
15543+    int numinliers=0;
15544+    int ind1;
15545+    int ind2;
15546+    int ind3;
15547+    int isinlier;
15548+
15549+    // experimentally determined
15550+    t2=1.0/(thresh*thresh*thresh*thresh);
15551+
15552+    // count the inliers
15553+    for(c=0;c<point_count;c++)
15554+    {
15555+        ind1=c<<1;
15556+        ind2=c<<2;
15557+        ind3=3*c;
15558+
15559+        temp_valueE=db_SquaredInhomogenousHomographyError(im_p+ind3,H,im+ind3);
15560+
15561+        isinlier=((temp_valueE<=t2)?1:0);
15562+
15563+        // if it is inlier, then copy the 3d and 2d correspondences
15564+        if (isinlier)
15565+        {
15566+            numinliers++;
15567+
15568+            x_i[k1]=x_i[ind1];
15569+            x_i[k1+1]=x_i[ind1+1];
15570+
15571+            xp_i[k1]=xp_i[ind1];
15572+            xp_i[k1+1]=xp_i[ind1+1];
15573+
15574+            k1=k1+2;
15575+
15576+            // original normalized pixel coordinates
15577+            im[k3]=im[ind3];
15578+            im[k3+1]=im[ind3+1];
15579+            im[k3+2]=im[ind3+2];
15580+
15581+            im_r[k3]=im_r[ind3];
15582+            im_r[k3+1]=im_r[ind3+1];
15583+            im_r[k3+2]=im_r[ind3+2];
15584+
15585+            im_p[k3]=im_p[ind3];
15586+            im_p[k3+1]=im_p[ind3+1];
15587+            im_p[k3+2]=im_p[ind3+2];
15588+
15589+            // left and right raw pixel coordinates
15590+            im_raw[k3] = im_raw[ind3];
15591+            im_raw[k3+1] = im_raw[ind3+1];
15592+            im_raw[k3+2] = im_raw[ind3+2]; // the index
15593+
15594+            im_raw_p[k3] = im_raw_p[ind3];
15595+            im_raw_p[k3+1] = im_raw_p[ind3+1];
15596+            im_raw_p[k3+2] = im_raw_p[ind3+2]; // the index
15597+
15598+            k3=k3+3;
15599+
15600+            // 3D coordinates
15601+            wp[k2]=wp[ind2];
15602+            wp[k2+1]=wp[ind2+1];
15603+            wp[k2+2]=wp[ind2+2];
15604+            wp[k2+3]=wp[ind2+3];
15605+
15606+            k2=k2+4;
15607+
15608+        }
15609+    }
15610+
15611+    return numinliers;
15612+}
15613+
15614+
15615+
15616+
15617+
15618+/*\}*/
15619+
15620+#endif /* DB_METRICS */
15621diff --git a/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp
15622new file mode 100644
15623index 00000000..82dec0cb
15624--- /dev/null
15625+++ b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.cpp
15626@@ -0,0 +1,1082 @@
15627+/*
15628+ * Copyright (C) 2011 The Android Open Source Project
15629+ *
15630+ * Licensed under the Apache License, Version 2.0 (the "License");
15631+ * you may not use this file except in compliance with the License.
15632+ * You may obtain a copy of the License at
15633+ *
15634+ *      http://www.apache.org/licenses/LICENSE-2.0
15635+ *
15636+ * Unless required by applicable law or agreed to in writing, software
15637+ * distributed under the License is distributed on an "AS IS" BASIS,
15638+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15639+ * See the License for the specific language governing permissions and
15640+ * limitations under the License.
15641+ */
15642+
15643+/* $Id: db_rob_image_homography.cpp,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
15644+
15645+#include "db_utilities.h"
15646+#include "db_rob_image_homography.h"
15647+#include "db_bundle.h"
15648+
15649+
15650+
15651+/*****************************************************************
15652+*    Lean and mean begins here                                   *
15653+*****************************************************************/
15654+
15655+#include "db_image_homography.h"
15656+
15657+#ifdef _VERBOSE_
15658+#include <iostream>
15659+using namespace std;
15660+#endif /*VERBOSE*/
15661+
15662+inline double db_RobImageHomography_Cost(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2)
15663+{
15664+    int c;
15665+    double back,acc,*x_i_temp,*xp_i_temp;
15666+
15667+    for(back=0.0,c=0;c<point_count;)
15668+    {
15669+        /*Take log of product of ten reprojection
15670+        errors to reduce nr of expensive log operations*/
15671+        if(c+9<point_count)
15672+        {
15673+            x_i_temp=x_i+(c<<1);
15674+            xp_i_temp=xp_i+(c<<1);
15675+
15676+            acc=db_ExpCauchyInhomogenousHomographyError(xp_i_temp,H,x_i_temp,one_over_scale2);
15677+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+2,H,x_i_temp+2,one_over_scale2);
15678+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+4,H,x_i_temp+4,one_over_scale2);
15679+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+6,H,x_i_temp+6,one_over_scale2);
15680+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+8,H,x_i_temp+8,one_over_scale2);
15681+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+10,H,x_i_temp+10,one_over_scale2);
15682+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+12,H,x_i_temp+12,one_over_scale2);
15683+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+14,H,x_i_temp+14,one_over_scale2);
15684+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+16,H,x_i_temp+16,one_over_scale2);
15685+            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+18,H,x_i_temp+18,one_over_scale2);
15686+            c+=10;
15687+        }
15688+        else
15689+        {
15690+            for(acc=1.0;c<point_count;c++)
15691+            {
15692+                acc*=db_ExpCauchyInhomogenousHomographyError(xp_i+(c<<1),H,x_i+(c<<1),one_over_scale2);
15693+            }
15694+        }
15695+        back+=log(acc);
15696+    }
15697+    return(back);
15698+}
15699+
15700+inline double db_RobImageHomography_Statistics(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2,db_Statistics *stat,double thresh=DB_OUTLIER_THRESHOLD)
15701+{
15702+    int c,i;
15703+    double t2,frac;
15704+
15705+    t2=thresh*thresh;
15706+    for(i=0,c=0;c<point_count;c++)
15707+    {
15708+        i+=(db_SquaredInhomogenousHomographyError(xp_i+(c<<1),H,x_i+(c<<1))*one_over_scale2<=t2)?1:0;
15709+    }
15710+    frac=((double)i)/((double)(db_maxi(point_count,1)));
15711+
15712+#ifdef _VERBOSE_
15713+    std::cout << "Inlier Percentage RobImageHomography: " << frac*100.0 << "% out of " << point_count << " constraints" << std::endl;
15714+#endif /*_VERBOSE_*/
15715+
15716+    if(stat)
15717+    {
15718+        stat->nr_points=point_count;
15719+        stat->one_over_scale2=one_over_scale2;
15720+        stat->nr_inliers=i;
15721+        stat->inlier_fraction=frac;
15722+
15723+        stat->cost=db_RobImageHomography_Cost(H,point_count,x_i,xp_i,one_over_scale2);
15724+        stat->model_dimension=0;
15725+        /*stat->nr_parameters=;*/
15726+
15727+        stat->lambda1=log(4.0);
15728+        stat->lambda2=log(4.0*((double)db_maxi(1,stat->nr_points)));
15729+        stat->lambda3=10.0;
15730+        stat->gric=stat->cost+stat->lambda1*stat->model_dimension*((double)stat->nr_points)+stat->lambda2*((double)stat->nr_parameters);
15731+        stat->inlier_evidence=((double)stat->nr_inliers)-stat->lambda3*((double)stat->nr_parameters);
15732+    }
15733+
15734+    return(frac);
15735+}
15736+
15737+/*Compute min_Jtf and upper right of JtJ. Return cost.*/
15738+inline double db_RobImageHomography_Jacobians(double JtJ[81],double min_Jtf[9],double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2)
15739+{
15740+    double back,Jf_dx[18],f[2],temp,temp2;
15741+    int i;
15742+
15743+    db_Zero(JtJ,81);
15744+    db_Zero(min_Jtf,9);
15745+    for(back=0.0,i=0;i<point_count;i++)
15746+    {
15747+        /*Compute reprojection error vector and its Jacobian
15748+        for this point*/
15749+        db_DerivativeCauchyInhomHomographyReprojection(Jf_dx,f,xp_i+(i<<1),H,x_i+(i<<1),one_over_scale2);
15750+        /*Perform
15751+        min_Jtf-=Jf_dx*f[0] and
15752+        min_Jtf-=(Jf_dx+9)*f[1] to accumulate -Jt%f*/
15753+        db_RowOperation9(min_Jtf,Jf_dx,f[0]);
15754+        db_RowOperation9(min_Jtf,Jf_dx+9,f[1]);
15755+        /*Accumulate upper right of JtJ with outer product*/
15756+        temp=Jf_dx[0]; temp2=Jf_dx[9];
15757+        JtJ[0]+=temp*Jf_dx[0]+temp2*Jf_dx[9];
15758+        JtJ[1]+=temp*Jf_dx[1]+temp2*Jf_dx[10];
15759+        JtJ[2]+=temp*Jf_dx[2]+temp2*Jf_dx[11];
15760+        JtJ[3]+=temp*Jf_dx[3]+temp2*Jf_dx[12];
15761+        JtJ[4]+=temp*Jf_dx[4]+temp2*Jf_dx[13];
15762+        JtJ[5]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15763+        JtJ[6]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15764+        JtJ[7]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15765+        JtJ[8]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15766+        temp=Jf_dx[1]; temp2=Jf_dx[10];
15767+        JtJ[10]+=temp*Jf_dx[1]+temp2*Jf_dx[10];
15768+        JtJ[11]+=temp*Jf_dx[2]+temp2*Jf_dx[11];
15769+        JtJ[12]+=temp*Jf_dx[3]+temp2*Jf_dx[12];
15770+        JtJ[13]+=temp*Jf_dx[4]+temp2*Jf_dx[13];
15771+        JtJ[14]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15772+        JtJ[15]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15773+        JtJ[16]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15774+        JtJ[17]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15775+        temp=Jf_dx[2]; temp2=Jf_dx[11];
15776+        JtJ[20]+=temp*Jf_dx[2]+temp2*Jf_dx[11];
15777+        JtJ[21]+=temp*Jf_dx[3]+temp2*Jf_dx[12];
15778+        JtJ[22]+=temp*Jf_dx[4]+temp2*Jf_dx[13];
15779+        JtJ[23]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15780+        JtJ[24]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15781+        JtJ[25]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15782+        JtJ[26]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15783+        temp=Jf_dx[3]; temp2=Jf_dx[12];
15784+        JtJ[30]+=temp*Jf_dx[3]+temp2*Jf_dx[12];
15785+        JtJ[31]+=temp*Jf_dx[4]+temp2*Jf_dx[13];
15786+        JtJ[32]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15787+        JtJ[33]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15788+        JtJ[34]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15789+        JtJ[35]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15790+        temp=Jf_dx[4]; temp2=Jf_dx[13];
15791+        JtJ[40]+=temp*Jf_dx[4]+temp2*Jf_dx[13];
15792+        JtJ[41]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15793+        JtJ[42]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15794+        JtJ[43]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15795+        JtJ[44]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15796+        temp=Jf_dx[5]; temp2=Jf_dx[14];
15797+        JtJ[50]+=temp*Jf_dx[5]+temp2*Jf_dx[14];
15798+        JtJ[51]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15799+        JtJ[52]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15800+        JtJ[53]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15801+        temp=Jf_dx[6]; temp2=Jf_dx[15];
15802+        JtJ[60]+=temp*Jf_dx[6]+temp2*Jf_dx[15];
15803+        JtJ[61]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15804+        JtJ[62]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15805+        temp=Jf_dx[7]; temp2=Jf_dx[16];
15806+        JtJ[70]+=temp*Jf_dx[7]+temp2*Jf_dx[16];
15807+        JtJ[71]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15808+        temp=Jf_dx[8]; temp2=Jf_dx[17];
15809+        JtJ[80]+=temp*Jf_dx[8]+temp2*Jf_dx[17];
15810+
15811+        /*Add square-sum to cost*/
15812+        back+=db_sqr(f[0])+db_sqr(f[1]);
15813+    }
15814+
15815+    return(back);
15816+}
15817+
15818+/*Compute min_Jtf and upper right of JtJ. Return cost*/
15819+inline double db_RobCamRotation_Jacobians(double JtJ[9],double min_Jtf[3],double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2)
15820+{
15821+    double back,Jf_dx[6],f[2];
15822+    int i,j;
15823+
15824+    db_Zero(JtJ,9);
15825+    db_Zero(min_Jtf,3);
15826+    for(back=0.0,i=0;i<point_count;i++)
15827+    {
15828+        /*Compute reprojection error vector and its Jacobian
15829+        for this point*/
15830+        j=(i<<1);
15831+        db_DerivativeCauchyInhomRotationReprojection(Jf_dx,f,xp_i+j,H,x_i+j,one_over_scale2);
15832+        /*Perform
15833+        min_Jtf-=Jf_dx*f[0] and
15834+        min_Jtf-=(Jf_dx+3)*f[1] to accumulate -Jt%f*/
15835+        db_RowOperation3(min_Jtf,Jf_dx,f[0]);
15836+        db_RowOperation3(min_Jtf,Jf_dx+3,f[1]);
15837+        /*Accumulate upper right of JtJ with outer product*/
15838+        JtJ[0]+=Jf_dx[0]*Jf_dx[0]+Jf_dx[3]*Jf_dx[3];
15839+        JtJ[1]+=Jf_dx[0]*Jf_dx[1]+Jf_dx[3]*Jf_dx[4];
15840+        JtJ[2]+=Jf_dx[0]*Jf_dx[2]+Jf_dx[3]*Jf_dx[5];
15841+        JtJ[4]+=Jf_dx[1]*Jf_dx[1]+Jf_dx[4]*Jf_dx[4];
15842+        JtJ[5]+=Jf_dx[1]*Jf_dx[2]+Jf_dx[4]*Jf_dx[5];
15843+        JtJ[8]+=Jf_dx[2]*Jf_dx[2]+Jf_dx[5]*Jf_dx[5];
15844+
15845+        /*Add square-sum to cost*/
15846+        back+=db_sqr(f[0])+db_sqr(f[1]);
15847+    }
15848+
15849+    return(back);
15850+}
15851+
15852+void db_RobCamRotation_Polish(double H[9],int point_count,double *x_i,double *xp_i,double one_over_scale2,
15853+                               int max_iterations,double improvement_requirement)
15854+{
15855+    int i,update,stop;
15856+    double lambda,cost,current_cost;
15857+    double JtJ[9],min_Jtf[3],dx[3],H_p_dx[9];
15858+
15859+    lambda=0.001;
15860+    for(update=1,stop=0,i=0;(stop<2) && (i<max_iterations);i++)
15861+    {
15862+        /*if first time since improvement, compute Jacobian and residual*/
15863+        if(update)
15864+        {
15865+            current_cost=db_RobCamRotation_Jacobians(JtJ,min_Jtf,H,point_count,x_i,xp_i,one_over_scale2);
15866+            update=0;
15867+        }
15868+
15869+#ifdef _VERBOSE_
15870+        /*std::cout << "Cost:" << current_cost << " ";*/
15871+#endif /*_VERBOSE_*/
15872+
15873+        /*Come up with a hypothesis dx
15874+        based on the current lambda*/
15875+        db_Compute_dx_3x3(dx,JtJ,min_Jtf,lambda);
15876+
15877+        /*Compute Cost(x+dx)*/
15878+        db_UpdateRotation(H_p_dx,H,dx);
15879+        cost=db_RobImageHomography_Cost(H_p_dx,point_count,x_i,xp_i,one_over_scale2);
15880+
15881+        /*Is there an improvement?*/
15882+        if(cost<current_cost)
15883+        {
15884+            /*improvement*/
15885+            if(current_cost-cost<current_cost*improvement_requirement) stop++;
15886+            else stop=0;
15887+            lambda*=0.1;
15888+            /*Move to the hypothesised position x+dx*/
15889+            current_cost=cost;
15890+            db_Copy9(H,H_p_dx);
15891+            db_OrthonormalizeRotation(H);
15892+            update=1;
15893+
15894+#ifdef _VERBOSE_
15895+        std::cout << "Step" << i << "Imp,Lambda=" << lambda << "Cost:" << current_cost << std::endl;
15896+#endif /*_VERBOSE_*/
15897+        }
15898+        else
15899+        {
15900+            /*no improvement*/
15901+            lambda*=10.0;
15902+            stop=0;
15903+        }
15904+    }
15905+}
15906+
15907+inline void db_RobImageHomographyFetchJacobian(double **JtJ_ref,double *min_Jtf,double **JtJ_temp_ref,double *min_Jtf_temp,int n,int *fetch_vector)
15908+{
15909+    int i,j,t;
15910+    double *t1,*t2;
15911+
15912+    for(i=0;i<n;i++)
15913+    {
15914+        t=fetch_vector[i];
15915+        min_Jtf[i]=min_Jtf_temp[t];
15916+        t1=JtJ_ref[i];
15917+        t2=JtJ_temp_ref[t];
15918+        for(j=i;j<n;j++)
15919+        {
15920+            t1[j]=t2[fetch_vector[j]];
15921+        }
15922+    }
15923+}
15924+
15925+inline void db_RobImageHomographyMultiplyJacobian(double **JtJ_ref,double *min_Jtf,double **JtJ_temp_ref,double *min_Jtf_temp,double **JE_dx_ref,int n)
15926+{
15927+    double JtJ_JE[72],*JtJ_JE_ref[9];
15928+
15929+    db_SetupMatrixRefs(JtJ_JE_ref,9,8,JtJ_JE);
15930+
15931+    db_SymmetricExtendUpperToLower(JtJ_temp_ref,9,9);
15932+    db_MultiplyMatricesAB(JtJ_JE_ref,JtJ_temp_ref,JE_dx_ref,9,9,n);
15933+    db_UpperMultiplyMatricesAtB(JtJ_ref,JE_dx_ref,JtJ_JE_ref,n,9,n);
15934+    db_MultiplyMatrixVectorAtb(min_Jtf,JE_dx_ref,min_Jtf_temp,n,9);
15935+}
15936+
15937+inline void db_RobImageHomographyJH_Js(double **JE_dx_ref,int j,double H[9])
15938+{
15939+    /*Update of upper 2x2 is multiplication by
15940+    [s 0][ cos(theta) sin(theta)]
15941+    [0 s][-sin(theta) cos(theta)]*/
15942+    JE_dx_ref[0][j]=H[0];
15943+    JE_dx_ref[1][j]=H[1];
15944+    JE_dx_ref[2][j]=0;
15945+    JE_dx_ref[3][j]=H[2];
15946+    JE_dx_ref[4][j]=H[3];
15947+    JE_dx_ref[5][j]=0;
15948+    JE_dx_ref[6][j]=0;
15949+    JE_dx_ref[7][j]=0;
15950+    JE_dx_ref[8][j]=0;
15951+}
15952+
15953+inline void db_RobImageHomographyJH_JR(double **JE_dx_ref,int j,double H[9])
15954+{
15955+    /*Update of upper 2x2 is multiplication by
15956+    [s 0][ cos(theta) sin(theta)]
15957+    [0 s][-sin(theta) cos(theta)]*/
15958+    JE_dx_ref[0][j]=  H[3];
15959+    JE_dx_ref[1][j]=  H[4];
15960+    JE_dx_ref[2][j]=0;
15961+    JE_dx_ref[3][j]= -H[0];
15962+    JE_dx_ref[4][j]= -H[1];
15963+    JE_dx_ref[5][j]=0;
15964+    JE_dx_ref[6][j]=0;
15965+    JE_dx_ref[7][j]=0;
15966+    JE_dx_ref[8][j]=0;
15967+}
15968+
15969+inline void db_RobImageHomographyJH_Jt(double **JE_dx_ref,int j,int k,double H[9])
15970+{
15971+    JE_dx_ref[0][j]=0;
15972+    JE_dx_ref[1][j]=0;
15973+    JE_dx_ref[2][j]=1.0;
15974+    JE_dx_ref[3][j]=0;
15975+    JE_dx_ref[4][j]=0;
15976+    JE_dx_ref[5][j]=0;
15977+    JE_dx_ref[6][j]=0;
15978+    JE_dx_ref[7][j]=0;
15979+    JE_dx_ref[8][j]=0;
15980+
15981+    JE_dx_ref[0][k]=0;
15982+    JE_dx_ref[1][k]=0;
15983+    JE_dx_ref[2][k]=0;
15984+    JE_dx_ref[3][k]=0;
15985+    JE_dx_ref[4][k]=0;
15986+    JE_dx_ref[5][k]=1.0;
15987+    JE_dx_ref[6][k]=0;
15988+    JE_dx_ref[7][k]=0;
15989+    JE_dx_ref[8][k]=0;
15990+}
15991+
15992+inline void db_RobImageHomographyJH_dRotFocal(double **JE_dx_ref,int j,int k,int l,int m,double H[9])
15993+{
15994+    double f,fi,fi2;
15995+    double R[9],J[9];
15996+
15997+    /*Updated matrix is diag(f+df,f+df)*dR*R*diag(1/(f+df),1/(f+df),1)*/
15998+    f=db_FocalAndRotFromCamRotFocalHomography(R,H);
15999+    fi=db_SafeReciprocal(f);
16000+    fi2=db_sqr(fi);
16001+    db_JacobianOfRotatedPointStride(J,R,3);
16002+    JE_dx_ref[0][j]=   J[0];
16003+    JE_dx_ref[1][j]=   J[1];
16004+    JE_dx_ref[2][j]=f* J[2];
16005+    JE_dx_ref[3][j]=   J[3];
16006+    JE_dx_ref[4][j]=   J[4];
16007+    JE_dx_ref[5][j]=f* J[5];
16008+    JE_dx_ref[6][j]=fi*J[6];
16009+    JE_dx_ref[7][j]=fi*J[7];
16010+    JE_dx_ref[8][j]=   J[8];
16011+    db_JacobianOfRotatedPointStride(J,R+1,3);
16012+    JE_dx_ref[0][k]=   J[0];
16013+    JE_dx_ref[1][k]=   J[1];
16014+    JE_dx_ref[2][k]=f* J[2];
16015+    JE_dx_ref[3][k]=   J[3];
16016+    JE_dx_ref[4][k]=   J[4];
16017+    JE_dx_ref[5][k]=f* J[5];
16018+    JE_dx_ref[6][k]=fi*J[6];
16019+    JE_dx_ref[7][k]=fi*J[7];
16020+    JE_dx_ref[8][k]=   J[8];
16021+    db_JacobianOfRotatedPointStride(J,R+2,3);
16022+    JE_dx_ref[0][l]=   J[0];
16023+    JE_dx_ref[1][l]=   J[1];
16024+    JE_dx_ref[2][l]=f* J[2];
16025+    JE_dx_ref[3][l]=   J[3];
16026+    JE_dx_ref[4][l]=   J[4];
16027+    JE_dx_ref[5][l]=f* J[5];
16028+    JE_dx_ref[6][l]=fi*J[6];
16029+    JE_dx_ref[7][l]=fi*J[7];
16030+    JE_dx_ref[8][l]=   J[8];
16031+
16032+    JE_dx_ref[0][m]=0;
16033+    JE_dx_ref[1][m]=0;
16034+    JE_dx_ref[2][m]=H[2];
16035+    JE_dx_ref[3][m]=0;
16036+    JE_dx_ref[4][m]=0;
16037+    JE_dx_ref[5][m]=H[5];
16038+    JE_dx_ref[6][m]= -fi2*H[6];
16039+    JE_dx_ref[7][m]= -fi2*H[7];
16040+    JE_dx_ref[8][m]=0;
16041+}
16042+
16043+inline double db_RobImageHomography_Jacobians_Generic(double *JtJ_ref[8],double min_Jtf[8],int *num_param,int *frozen_coord,double H[9],int point_count,double *x_i,double *xp_i,int homography_type,double one_over_scale2)
16044+{
16045+    double back;
16046+    int i,j,fetch_vector[8],n;
16047+    double JtJ_temp[81],min_Jtf_temp[9],JE_dx[72];
16048+    double *JE_dx_ref[9],*JtJ_temp_ref[9];
16049+
16050+    /*Compute cost and JtJ,min_Jtf with respect to H*/
16051+    back=db_RobImageHomography_Jacobians(JtJ_temp,min_Jtf_temp,H,point_count,x_i,xp_i,one_over_scale2);
16052+
16053+    /*Compute JtJ,min_Jtf with respect to the right parameters
16054+    The formulas are
16055+    JtJ=transpose(JE_dx)*JtJ*JE_dx and
16056+    min_Jtf=transpose(JE_dx)*min_Jtf,
16057+    where the 9xN matrix JE_dx is the Jacobian of H with respect
16058+    to the update*/
16059+    db_SetupMatrixRefs(JtJ_temp_ref,9,9,JtJ_temp);
16060+    db_SetupMatrixRefs(JE_dx_ref,9,8,JE_dx);
16061+    switch(homography_type)
16062+    {
16063+        case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16064+        case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16065+            n=4;
16066+            db_RobImageHomographyJH_Js(JE_dx_ref,0,H);
16067+            db_RobImageHomographyJH_JR(JE_dx_ref,1,H);
16068+            db_RobImageHomographyJH_Jt(JE_dx_ref,2,3,H);
16069+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16070+            break;
16071+        case DB_HOMOGRAPHY_TYPE_ROTATION:
16072+        case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16073+            n=1;
16074+            db_RobImageHomographyJH_JR(JE_dx_ref,0,H);
16075+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16076+            break;
16077+        case DB_HOMOGRAPHY_TYPE_SCALING:
16078+            n=1;
16079+            db_RobImageHomographyJH_Js(JE_dx_ref,0,H);
16080+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16081+            break;
16082+        case DB_HOMOGRAPHY_TYPE_S_T:
16083+            n=3;
16084+            db_RobImageHomographyJH_Js(JE_dx_ref,0,H);
16085+            db_RobImageHomographyJH_Jt(JE_dx_ref,1,2,H);
16086+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16087+            break;
16088+        case DB_HOMOGRAPHY_TYPE_R_T:
16089+            n=3;
16090+            db_RobImageHomographyJH_JR(JE_dx_ref,0,H);
16091+            db_RobImageHomographyJH_Jt(JE_dx_ref,1,2,H);
16092+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16093+            break;
16094+        case DB_HOMOGRAPHY_TYPE_R_S:
16095+            n=2;
16096+            db_RobImageHomographyJH_Js(JE_dx_ref,0,H);
16097+            db_RobImageHomographyJH_JR(JE_dx_ref,1,H);
16098+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16099+            break;
16100+
16101+        case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16102+            n=2;
16103+            fetch_vector[0]=2;
16104+            fetch_vector[1]=5;
16105+            db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector);
16106+            break;
16107+        case DB_HOMOGRAPHY_TYPE_AFFINE:
16108+            n=6;
16109+            fetch_vector[0]=0;
16110+            fetch_vector[1]=1;
16111+            fetch_vector[2]=2;
16112+            fetch_vector[3]=3;
16113+            fetch_vector[4]=4;
16114+            fetch_vector[5]=5;
16115+            db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector);
16116+            break;
16117+        case DB_HOMOGRAPHY_TYPE_PROJECTIVE:
16118+            n=8;
16119+            *frozen_coord=db_MaxAbsIndex9(H);
16120+            for(j=0,i=0;i<9;i++) if(i!=(*frozen_coord))
16121+            {
16122+                fetch_vector[j]=i;
16123+                j++;
16124+            }
16125+            db_RobImageHomographyFetchJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,n,fetch_vector);
16126+            break;
16127+        case DB_HOMOGRAPHY_TYPE_CAMROTATION_F:
16128+        case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD:
16129+            n=4;
16130+            db_RobImageHomographyJH_dRotFocal(JE_dx_ref,0,1,2,3,H);
16131+            db_RobImageHomographyMultiplyJacobian(JtJ_ref,min_Jtf,JtJ_temp_ref,min_Jtf_temp,JE_dx_ref,n);
16132+            break;
16133+    }
16134+    *num_param=n;
16135+
16136+    return(back);
16137+}
16138+
16139+inline void db_ImageHomographyUpdateGeneric(double H_p_dx[9],double H[9],double *dx,int homography_type,int frozen_coord)
16140+{
16141+    switch(homography_type)
16142+    {
16143+        case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16144+        case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16145+            db_Copy9(H_p_dx,H);
16146+            db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]);
16147+            db_MultiplyRotationOntoImageHomography(H,dx[1]);
16148+            H_p_dx[2]+=dx[2];
16149+            H_p_dx[5]+=dx[3];
16150+            break;
16151+        case DB_HOMOGRAPHY_TYPE_ROTATION:
16152+        case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16153+            db_MultiplyRotationOntoImageHomography(H,dx[0]);
16154+            break;
16155+        case DB_HOMOGRAPHY_TYPE_SCALING:
16156+            db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]);
16157+            break;
16158+        case DB_HOMOGRAPHY_TYPE_S_T:
16159+            db_Copy9(H_p_dx,H);
16160+            db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]);
16161+            H_p_dx[2]+=dx[1];
16162+            H_p_dx[5]+=dx[2];
16163+            break;
16164+        case DB_HOMOGRAPHY_TYPE_R_T:
16165+            db_Copy9(H_p_dx,H);
16166+            db_MultiplyRotationOntoImageHomography(H,dx[0]);
16167+            H_p_dx[2]+=dx[1];
16168+            H_p_dx[5]+=dx[2];
16169+            break;
16170+        case DB_HOMOGRAPHY_TYPE_R_S:
16171+            db_Copy9(H_p_dx,H);
16172+            db_MultiplyScaleOntoImageHomography(H,1.0+dx[0]);
16173+            db_MultiplyRotationOntoImageHomography(H,dx[1]);
16174+            break;
16175+        case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16176+            db_Copy9(H_p_dx,H);
16177+            H_p_dx[2]+=dx[0];
16178+            H_p_dx[5]+=dx[1];
16179+            break;
16180+        case DB_HOMOGRAPHY_TYPE_AFFINE:
16181+            db_UpdateImageHomographyAffine(H_p_dx,H,dx);
16182+            break;
16183+        case DB_HOMOGRAPHY_TYPE_PROJECTIVE:
16184+            db_UpdateImageHomographyProjective(H_p_dx,H,dx,frozen_coord);
16185+            break;
16186+        case DB_HOMOGRAPHY_TYPE_CAMROTATION_F:
16187+        case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD:
16188+            db_UpdateRotFocalHomography(H_p_dx,H,dx);
16189+            break;
16190+    }
16191+}
16192+
16193+void db_RobCamRotation_Polish_Generic(double H[9],int point_count,int homography_type,double *x_i,double *xp_i,double one_over_scale2,
16194+                               int max_iterations,double improvement_requirement)
16195+{
16196+    int i,update,stop,n;
16197+    int frozen_coord = 0;
16198+    double lambda,cost,current_cost;
16199+    double JtJ[72],min_Jtf[9],dx[8],H_p_dx[9];
16200+    double *JtJ_ref[9],d[8];
16201+
16202+    lambda=0.001;
16203+    for(update=1,stop=0,i=0;(stop<2) && (i<max_iterations);i++)
16204+    {
16205+        /*if first time since improvement, compute Jacobian and residual*/
16206+        if(update)
16207+        {
16208+            db_SetupMatrixRefs(JtJ_ref,9,8,JtJ);
16209+            current_cost=db_RobImageHomography_Jacobians_Generic(JtJ_ref,min_Jtf,&n,&frozen_coord,H,point_count,x_i,xp_i,homography_type,one_over_scale2);
16210+            update=0;
16211+        }
16212+
16213+#ifdef _VERBOSE_
16214+        /*std::cout << "Cost:" << current_cost << " ";*/
16215+#endif /*_VERBOSE_*/
16216+
16217+        /*Come up with a hypothesis dx
16218+        based on the current lambda*/
16219+        db_Compute_dx(dx,JtJ_ref,min_Jtf,lambda,d,n);
16220+
16221+        /*Compute Cost(x+dx)*/
16222+        db_ImageHomographyUpdateGeneric(H_p_dx,H,dx,homography_type,frozen_coord);
16223+        cost=db_RobImageHomography_Cost(H_p_dx,point_count,x_i,xp_i,one_over_scale2);
16224+
16225+        /*Is there an improvement?*/
16226+        if(cost<current_cost)
16227+        {
16228+            /*improvement*/
16229+            if(current_cost-cost<current_cost*improvement_requirement) stop++;
16230+            else stop=0;
16231+            lambda*=0.1;
16232+            /*Move to the hypothesised position x+dx*/
16233+            current_cost=cost;
16234+            db_Copy9(H,H_p_dx);
16235+            update=1;
16236+
16237+#ifdef _VERBOSE_
16238+        std::cout << "Step" << i << "Imp,Lambda=" << lambda << "Cost:" << current_cost << std::endl;
16239+#endif /*_VERBOSE_*/
16240+        }
16241+        else
16242+        {
16243+            /*no improvement*/
16244+            lambda*=10.0;
16245+            stop=0;
16246+        }
16247+    }
16248+}
16249+void db_RobImageHomography(
16250+                              /*Best homography*/
16251+                              double H[9],
16252+                              /*2DPoint to 2DPoint constraints
16253+                              Points are assumed to be given in
16254+                              homogenous coordinates*/
16255+                              double *im, double *im_p,
16256+                              /*Nr of points in total*/
16257+                              int nr_points,
16258+                              /*Calibration matrices
16259+                              used to normalize the points*/
16260+                              double K[9],
16261+                              double Kp[9],
16262+                              /*Pre-allocated space temp_d
16263+                              should point to at least
16264+                              12*nr_samples+10*nr_points
16265+                              allocated positions*/
16266+                              double *temp_d,
16267+                              /*Pre-allocated space temp_i
16268+                              should point to at least
16269+                              max(nr_samples,nr_points)
16270+                              allocated positions*/
16271+                              int *temp_i,
16272+                              int homography_type,
16273+                              db_Statistics *stat,
16274+                              int max_iterations,
16275+                              int max_points,
16276+                              double scale,
16277+                              int nr_samples,
16278+                              int chunk_size,
16279+                              /////////////////////////////////////////////
16280+                              // regular use: set outlierremoveflagE =0;
16281+                              // flag for the outlier removal
16282+                              int outlierremoveflagE,
16283+                              // if flag is 1, then the following variables
16284+                              // need the input
16285+                              //////////////////////////////////////
16286+                              // 3D coordinates
16287+                              double *wp,
16288+                              // its corresponding stereo pair's points
16289+                              double *im_r,
16290+                              // raw image coordinates
16291+                              double *im_raw, double *im_raw_p,
16292+                              // final matches
16293+                              int *finalNumE)
16294+{
16295+    /*Random seed*/
16296+    int r_seed;
16297+
16298+    int point_count_new;
16299+    /*Counters*/
16300+    int i,j,c,point_count,hyp_count;
16301+    int last_hyp,new_last_hyp,last_corr;
16302+    int pos,point_pos,last_point;
16303+    /*Accumulator*/
16304+    double acc;
16305+    /*Hypothesis pointer*/
16306+    double *hyp_point;
16307+    /*Random sample*/
16308+    int s[4];
16309+    /*Pivot for hypothesis pruning*/
16310+    double pivot;
16311+    /*Best hypothesis position*/
16312+    int best_pos;
16313+    /*Best score*/
16314+    double lowest_cost;
16315+    /*One over the squared scale of
16316+    Cauchy distribution*/
16317+    double one_over_scale2;
16318+    /*temporary pointers*/
16319+    double *x_i_temp,*xp_i_temp;
16320+    /*Temporary space for inverse calibration matrices*/
16321+    double K_inv[9];
16322+    double Kp_inv[9];
16323+    /*Temporary space for homography*/
16324+    double H_temp[9],H_temp2[9];
16325+    /*Pointers to homogenous coordinates*/
16326+    double *x_h_point,*xp_h_point;
16327+    /*Array of pointers to inhomogenous coordinates*/
16328+    double *X[3],*Xp[3];
16329+    /*Similarity parameters*/
16330+    int orientation_preserving,allow_scaling,allow_rotation,allow_translation,sample_size;
16331+
16332+    /*Homogenous coordinates of image points in first image*/
16333+    double *x_h;
16334+    /*Homogenous coordinates of image points in second image*/
16335+    double *xp_h;
16336+    /*Inhomogenous coordinates of image points in first image*/
16337+    double *x_i;
16338+    /*Inhomogenous coordinates of image points in second image*/
16339+    double *xp_i;
16340+    /*Homography hypotheses*/
16341+    double *hyp_H_array;
16342+    /*Cost array*/
16343+    double *hyp_cost_array;
16344+    /*Permutation of the hypotheses*/
16345+    int *hyp_perm;
16346+    /*Sample of the points*/
16347+    int *point_perm;
16348+    /*Temporary space for quick-select
16349+    2*nr_samples*/
16350+    double *temp_select;
16351+
16352+    /*Get inverse calibration matrices*/
16353+    db_InvertCalibrationMatrix(K_inv,K);
16354+    db_InvertCalibrationMatrix(Kp_inv,Kp);
16355+    /*Compute scale coefficient*/
16356+    one_over_scale2=1.0/(scale*scale);
16357+    /*Initialize random seed*/
16358+    r_seed=12345;
16359+    /*Set pointers to pre-allocated space*/
16360+    hyp_cost_array=temp_d;
16361+    hyp_H_array=temp_d+nr_samples;
16362+    temp_select=temp_d+10*nr_samples;
16363+    x_h=temp_d+12*nr_samples;
16364+    xp_h=temp_d+12*nr_samples+3*nr_points;
16365+    x_i=temp_d+12*nr_samples+6*nr_points;
16366+    xp_i=temp_d+12*nr_samples+8*nr_points;
16367+    hyp_perm=temp_i;
16368+    point_perm=temp_i;
16369+
16370+    /*Prepare a randomly permuted subset of size
16371+    point_count from the input points*/
16372+
16373+    point_count=db_mini(nr_points,(int)(chunk_size*log((double)nr_samples)/DB_LN2));
16374+
16375+    point_count_new = point_count;
16376+
16377+    for(i=0;i<nr_points;i++) point_perm[i]=i;
16378+
16379+    for(last_point=nr_points-1,i=0;i<point_count;i++,last_point--)
16380+    {
16381+        pos=db_RandomInt(r_seed,last_point);
16382+        point_pos=point_perm[pos];
16383+        point_perm[pos]=point_perm[last_point];
16384+
16385+        /*Normalize image points with calibration
16386+        matrices and move them to x_h and xp_h*/
16387+        c=3*point_pos;
16388+        j=3*i;
16389+        x_h_point=x_h+j;
16390+        xp_h_point=xp_h+j;
16391+        db_Multiply3x3_3x1(x_h_point,K_inv,im+c);
16392+        db_Multiply3x3_3x1(xp_h_point,Kp_inv,im_p+c);
16393+
16394+        db_HomogenousNormalize3(x_h_point);
16395+        db_HomogenousNormalize3(xp_h_point);
16396+
16397+        /*Dehomogenize image points and move them
16398+        to x_i and xp_i*/
16399+        c=(i<<1);
16400+        db_DeHomogenizeImagePoint(x_i+c,x_h_point); // 2-dimension
16401+        db_DeHomogenizeImagePoint(xp_i+c,xp_h_point); //2-dimension
16402+    }
16403+
16404+
16405+    /*Generate Hypotheses*/
16406+    hyp_count=0;
16407+    switch(homography_type)
16408+    {
16409+    case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16410+    case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16411+    case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16412+    case DB_HOMOGRAPHY_TYPE_ROTATION:
16413+    case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16414+    case DB_HOMOGRAPHY_TYPE_SCALING:
16415+    case DB_HOMOGRAPHY_TYPE_S_T:
16416+    case DB_HOMOGRAPHY_TYPE_R_T:
16417+    case DB_HOMOGRAPHY_TYPE_R_S:
16418+
16419+        switch(homography_type)
16420+        {
16421+        case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16422+            orientation_preserving=1;
16423+            allow_scaling=1;
16424+            allow_rotation=1;
16425+            allow_translation=1;
16426+            sample_size=2;
16427+            break;
16428+        case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16429+            orientation_preserving=0;
16430+            allow_scaling=1;
16431+            allow_rotation=1;
16432+            allow_translation=1;
16433+            sample_size=3;
16434+            break;
16435+        case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16436+            orientation_preserving=1;
16437+            allow_scaling=0;
16438+            allow_rotation=0;
16439+            allow_translation=1;
16440+            sample_size=1;
16441+            break;
16442+        case DB_HOMOGRAPHY_TYPE_ROTATION:
16443+            orientation_preserving=1;
16444+            allow_scaling=0;
16445+            allow_rotation=1;
16446+            allow_translation=0;
16447+            sample_size=1;
16448+            break;
16449+        case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16450+            orientation_preserving=0;
16451+            allow_scaling=0;
16452+            allow_rotation=1;
16453+            allow_translation=0;
16454+            sample_size=2;
16455+            break;
16456+        case DB_HOMOGRAPHY_TYPE_SCALING:
16457+            orientation_preserving=1;
16458+            allow_scaling=1;
16459+            allow_rotation=0;
16460+            allow_translation=0;
16461+            sample_size=1;
16462+            break;
16463+        case DB_HOMOGRAPHY_TYPE_S_T:
16464+            orientation_preserving=1;
16465+            allow_scaling=1;
16466+            allow_rotation=0;
16467+            allow_translation=1;
16468+            sample_size=2;
16469+            break;
16470+        case DB_HOMOGRAPHY_TYPE_R_T:
16471+            orientation_preserving=1;
16472+            allow_scaling=0;
16473+            allow_rotation=1;
16474+            allow_translation=1;
16475+            sample_size=2;
16476+            break;
16477+        case DB_HOMOGRAPHY_TYPE_R_S:
16478+            orientation_preserving=1;
16479+            allow_scaling=1;
16480+            allow_rotation=0;
16481+            allow_translation=0;
16482+            sample_size=1;
16483+            break;
16484+        }
16485+
16486+        if(point_count>=sample_size) for(i=0;i<nr_samples;i++)
16487+        {
16488+            db_RandomSample(s,3,point_count,r_seed);
16489+            X[0]= &x_i[s[0]<<1];
16490+            X[1]= &x_i[s[1]<<1];
16491+            X[2]= &x_i[s[2]<<1];
16492+            Xp[0]= &xp_i[s[0]<<1];
16493+            Xp[1]= &xp_i[s[1]<<1];
16494+            Xp[2]= &xp_i[s[2]<<1];
16495+            db_StitchSimilarity2D(&hyp_H_array[9*hyp_count],Xp,X,sample_size,orientation_preserving,
16496+                                  allow_scaling,allow_rotation,allow_translation);
16497+            hyp_count++;
16498+        }
16499+        break;
16500+
16501+    case DB_HOMOGRAPHY_TYPE_CAMROTATION:
16502+        if(point_count>=2) for(i=0;i<nr_samples;i++)
16503+        {
16504+            db_RandomSample(s,2,point_count,r_seed);
16505+            db_StitchCameraRotation_2Points(&hyp_H_array[9*hyp_count],
16506+                                      &x_h[3*s[0]],&x_h[3*s[1]],
16507+                                      &xp_h[3*s[0]],&xp_h[3*s[1]]);
16508+            hyp_count++;
16509+        }
16510+        break;
16511+
16512+    case DB_HOMOGRAPHY_TYPE_CAMROTATION_F:
16513+        if(point_count>=3) for(i=0;i<nr_samples;i++)
16514+        {
16515+            db_RandomSample(s,3,point_count,r_seed);
16516+            hyp_count+=db_StitchRotationCommonFocalLength_3Points(&hyp_H_array[9*hyp_count],
16517+                                      &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]],
16518+                                      &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]]);
16519+        }
16520+        break;
16521+
16522+    case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD:
16523+        if(point_count>=3) for(i=0;i<nr_samples;i++)
16524+        {
16525+            db_RandomSample(s,3,point_count,r_seed);
16526+            hyp_count+=db_StitchRotationCommonFocalLength_3Points(&hyp_H_array[9*hyp_count],
16527+                                      &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]],
16528+                                      &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]],NULL,0);
16529+        }
16530+        break;
16531+
16532+    case DB_HOMOGRAPHY_TYPE_AFFINE:
16533+        if(point_count>=3) for(i=0;i<nr_samples;i++)
16534+        {
16535+            db_RandomSample(s,3,point_count,r_seed);
16536+            db_StitchAffine2D_3Points(&hyp_H_array[9*hyp_count],
16537+                                      &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]],
16538+                                      &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]]);
16539+            hyp_count++;
16540+        }
16541+        break;
16542+
16543+    case DB_HOMOGRAPHY_TYPE_PROJECTIVE:
16544+    default:
16545+        if(point_count>=4) for(i=0;i<nr_samples;i++)
16546+        {
16547+            db_RandomSample(s,4,point_count,r_seed);
16548+            db_StitchProjective2D_4Points(&hyp_H_array[9*hyp_count],
16549+                                      &x_h[3*s[0]],&x_h[3*s[1]],&x_h[3*s[2]],&x_h[3*s[3]],
16550+                                      &xp_h[3*s[0]],&xp_h[3*s[1]],&xp_h[3*s[2]],&xp_h[3*s[3]]);
16551+            hyp_count++;
16552+        }
16553+    }
16554+
16555+    if(hyp_count)
16556+    {
16557+        /*Count cost in chunks and decimate hypotheses
16558+        until only one remains or the correspondences are
16559+        exhausted*/
16560+        for(i=0;i<hyp_count;i++)
16561+        {
16562+            hyp_perm[i]=i;
16563+            hyp_cost_array[i]=0.0;
16564+        }
16565+        for(i=0,last_hyp=hyp_count-1;(last_hyp>0) && (i<point_count);i+=chunk_size)
16566+        {
16567+            /*Update cost with the next chunk*/
16568+            last_corr=db_mini(i+chunk_size-1,point_count-1);
16569+            for(j=0;j<=last_hyp;j++)
16570+            {
16571+                hyp_point=hyp_H_array+9*hyp_perm[j];
16572+                for(c=i;c<=last_corr;)
16573+                {
16574+                    /*Take log of product of ten reprojection
16575+                    errors to reduce nr of expensive log operations*/
16576+                    if(c+9<=last_corr)
16577+                    {
16578+                        x_i_temp=x_i+(c<<1);
16579+                        xp_i_temp=xp_i+(c<<1);
16580+
16581+                        acc=db_ExpCauchyInhomogenousHomographyError(xp_i_temp,hyp_point,x_i_temp,one_over_scale2);
16582+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+2,hyp_point,x_i_temp+2,one_over_scale2);
16583+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+4,hyp_point,x_i_temp+4,one_over_scale2);
16584+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+6,hyp_point,x_i_temp+6,one_over_scale2);
16585+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+8,hyp_point,x_i_temp+8,one_over_scale2);
16586+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+10,hyp_point,x_i_temp+10,one_over_scale2);
16587+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+12,hyp_point,x_i_temp+12,one_over_scale2);
16588+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+14,hyp_point,x_i_temp+14,one_over_scale2);
16589+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+16,hyp_point,x_i_temp+16,one_over_scale2);
16590+                        acc*=db_ExpCauchyInhomogenousHomographyError(xp_i_temp+18,hyp_point,x_i_temp+18,one_over_scale2);
16591+                        c+=10;
16592+                    }
16593+                    else
16594+                    {
16595+                        for(acc=1.0;c<=last_corr;c++)
16596+                        {
16597+                            acc*=db_ExpCauchyInhomogenousHomographyError(xp_i+(c<<1),hyp_point,x_i+(c<<1),one_over_scale2);
16598+                        }
16599+                    }
16600+                    hyp_cost_array[j]+=log(acc);
16601+                }
16602+            }
16603+            if (chunk_size<point_count){
16604+                /*Prune out half of the hypotheses*/
16605+                new_last_hyp=(last_hyp+1)/2-1;
16606+                pivot=db_LeanQuickSelect(hyp_cost_array,last_hyp+1,new_last_hyp,temp_select);
16607+                for(j=0,c=0;(j<=last_hyp) && (c<=new_last_hyp);j++)
16608+                {
16609+                    if(hyp_cost_array[j]<=pivot)
16610+                    {
16611+                        hyp_cost_array[c]=hyp_cost_array[j];
16612+                        hyp_perm[c]=hyp_perm[j];
16613+                        c++;
16614+                    }
16615+                }
16616+                last_hyp=new_last_hyp;
16617+            }
16618+        }
16619+        /*Find the best hypothesis*/
16620+        lowest_cost=hyp_cost_array[0];
16621+        best_pos=0;
16622+        for(j=1;j<=last_hyp;j++)
16623+        {
16624+            if(hyp_cost_array[j]<lowest_cost)
16625+            {
16626+                lowest_cost=hyp_cost_array[j];
16627+                best_pos=j;
16628+            }
16629+        }
16630+
16631+        /*Move the best hypothesis*/
16632+        db_Copy9(H_temp,hyp_H_array+9*hyp_perm[best_pos]);
16633+
16634+        // outlier removal
16635+        if (outlierremoveflagE) // no polishment needed
16636+        {
16637+            point_count_new = db_RemoveOutliers_Homography(H_temp,x_i,xp_i,wp,im,im_p,im_r,im_raw,im_raw_p,point_count,one_over_scale2);
16638+        }
16639+        else
16640+        {
16641+            /*Polish*/
16642+            switch(homography_type)
16643+            {
16644+            case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16645+            case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16646+            case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16647+            case DB_HOMOGRAPHY_TYPE_ROTATION:
16648+            case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16649+            case DB_HOMOGRAPHY_TYPE_SCALING:
16650+            case DB_HOMOGRAPHY_TYPE_S_T:
16651+            case DB_HOMOGRAPHY_TYPE_R_T:
16652+            case DB_HOMOGRAPHY_TYPE_R_S:
16653+            case DB_HOMOGRAPHY_TYPE_AFFINE:
16654+            case DB_HOMOGRAPHY_TYPE_PROJECTIVE:
16655+            case DB_HOMOGRAPHY_TYPE_CAMROTATION_F:
16656+            case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD:
16657+                db_RobCamRotation_Polish_Generic(H_temp,db_mini(point_count,max_points),homography_type,x_i,xp_i,one_over_scale2,max_iterations);
16658+                break;
16659+            case DB_HOMOGRAPHY_TYPE_CAMROTATION:
16660+                db_RobCamRotation_Polish(H_temp,db_mini(point_count,max_points),x_i,xp_i,one_over_scale2,max_iterations);
16661+                break;
16662+            }
16663+
16664+        }
16665+
16666+    }
16667+    else db_Identity3x3(H_temp);
16668+
16669+    switch(homography_type)
16670+    {
16671+    case DB_HOMOGRAPHY_TYPE_PROJECTIVE:
16672+        if(stat) stat->nr_parameters=8;
16673+        break;
16674+    case DB_HOMOGRAPHY_TYPE_AFFINE:
16675+        if(stat) stat->nr_parameters=6;
16676+        break;
16677+    case DB_HOMOGRAPHY_TYPE_SIMILARITY:
16678+    case DB_HOMOGRAPHY_TYPE_SIMILARITY_U:
16679+    case DB_HOMOGRAPHY_TYPE_CAMROTATION_F:
16680+    case DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD:
16681+        if(stat) stat->nr_parameters=4;
16682+        break;
16683+    case DB_HOMOGRAPHY_TYPE_CAMROTATION:
16684+        if(stat) stat->nr_parameters=3;
16685+        break;
16686+    case DB_HOMOGRAPHY_TYPE_TRANSLATION:
16687+    case DB_HOMOGRAPHY_TYPE_S_T:
16688+    case DB_HOMOGRAPHY_TYPE_R_T:
16689+    case DB_HOMOGRAPHY_TYPE_R_S:
16690+        if(stat) stat->nr_parameters=2;
16691+        break;
16692+    case DB_HOMOGRAPHY_TYPE_ROTATION:
16693+    case DB_HOMOGRAPHY_TYPE_ROTATION_U:
16694+    case DB_HOMOGRAPHY_TYPE_SCALING:
16695+        if(stat) stat->nr_parameters=1;
16696+        break;
16697+    }
16698+
16699+    db_RobImageHomography_Statistics(H_temp,db_mini(point_count,max_points),x_i,xp_i,one_over_scale2,stat);
16700+
16701+    /*Put on the calibration matrices*/
16702+    db_Multiply3x3_3x3(H_temp2,H_temp,K_inv);
16703+    db_Multiply3x3_3x3(H,Kp,H_temp2);
16704+
16705+    if (finalNumE)
16706+        *finalNumE = point_count_new;
16707+
16708+}
16709diff --git a/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h
16710new file mode 100644
16711index 00000000..59cde7da
16712--- /dev/null
16713+++ b/benchmark/feature_stab/db_vlvm/db_rob_image_homography.h
16714@@ -0,0 +1,148 @@
16715+/*
16716+ * Copyright (C) 2011 The Android Open Source Project
16717+ *
16718+ * Licensed under the Apache License, Version 2.0 (the "License");
16719+ * you may not use this file except in compliance with the License.
16720+ * You may obtain a copy of the License at
16721+ *
16722+ *      http://www.apache.org/licenses/LICENSE-2.0
16723+ *
16724+ * Unless required by applicable law or agreed to in writing, software
16725+ * distributed under the License is distributed on an "AS IS" BASIS,
16726+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16727+ * See the License for the specific language governing permissions and
16728+ * limitations under the License.
16729+ */
16730+
16731+/* $Id: db_rob_image_homography.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
16732+
16733+#ifndef DB_ROB_IMAGE_HOMOGRAPHY
16734+#define DB_ROB_IMAGE_HOMOGRAPHY
16735+
16736+#include "db_utilities.h"
16737+#include "db_robust.h"
16738+#include "db_metrics.h"
16739+
16740+#include <stdlib.h> // for NULL
16741+
16742+
16743+/*****************************************************************
16744+*    Lean and mean begins here                                   *
16745+*****************************************************************/
16746+/*!
16747+ * \defgroup LMRobImageHomography (LM) Robust Image Homography
16748+ */
16749+/*\{*/
16750+
16751+#define DB_HOMOGRAPHY_TYPE_DEFAULT           0
16752+#define DB_HOMOGRAPHY_TYPE_PROJECTIVE        0
16753+#define DB_HOMOGRAPHY_TYPE_AFFINE            1
16754+#define DB_HOMOGRAPHY_TYPE_SIMILARITY        2
16755+#define DB_HOMOGRAPHY_TYPE_SIMILARITY_U      3
16756+#define DB_HOMOGRAPHY_TYPE_TRANSLATION       4
16757+#define DB_HOMOGRAPHY_TYPE_ROTATION          5
16758+#define DB_HOMOGRAPHY_TYPE_ROTATION_U        6
16759+#define DB_HOMOGRAPHY_TYPE_SCALING           7
16760+#define DB_HOMOGRAPHY_TYPE_S_T               8
16761+#define DB_HOMOGRAPHY_TYPE_R_T               9
16762+#define DB_HOMOGRAPHY_TYPE_R_S              10
16763+#define DB_HOMOGRAPHY_TYPE_CAMROTATION      11
16764+#define DB_HOMOGRAPHY_TYPE_CAMROTATION_F    12
16765+#define DB_HOMOGRAPHY_TYPE_CAMROTATION_F_UD 13
16766+
16767+/*!
16768+Solve for homography H such that xp~Hx
16769+\param H    best homography
16770+
16771+2D point to 2D point constraints:
16772+
16773+\param im           first image points
16774+\param im_p         second image points
16775+\param nr_points    number of points
16776+
16777+Calibration matrices:
16778+
16779+\param K    first camera
16780+\param Kp   second camera
16781+
16782+ Temporary space:
16783+
16784+ \param temp_d      pre-allocated space of size 12*nr_samples+10*nr_points doubles
16785+ \param temp_i      pre-allocated space of size max(nr_samples,nr_points) ints
16786+
16787+ Statistics for this estimation
16788+
16789+ \param stat        NULL - do not compute
16790+
16791+ \param homography_type see DB_HOMOGRAPHY_TYPE_* definitions above
16792+
16793+ Estimation parameters:
16794+
16795+ \param max_iterations  max number of polishing steps
16796+ \param max_points      only use this many points
16797+ \param scale           Cauchy scale coefficient (see db_ExpCauchyReprojectionError() )
16798+ \param nr_samples      number of times to compute a hypothesis
16799+ \param chunk_size      size of cost chunks
16800+*/
16801+DB_API void db_RobImageHomography(
16802+                              /*Best homography*/
16803+                              double H[9],
16804+                              /*2DPoint to 2DPoint constraints
16805+                              Points are assumed to be given in
16806+                              homogenous coordinates*/
16807+                              double *im,double *im_p,
16808+                              /*Nr of points in total*/
16809+                              int nr_points,
16810+                              /*Calibration matrices
16811+                              used to normalize the points*/
16812+                              double K[9],
16813+                              double Kp[9],
16814+                              /*Pre-allocated space temp_d
16815+                              should point to at least
16816+                              12*nr_samples+10*nr_points
16817+                              allocated positions*/
16818+                              double *temp_d,
16819+                              /*Pre-allocated space temp_i
16820+                              should point to at least
16821+                              max(nr_samples,nr_points)
16822+                              allocated positions*/
16823+                              int *temp_i,
16824+                              int homography_type=DB_HOMOGRAPHY_TYPE_DEFAULT,
16825+                              db_Statistics *stat=NULL,
16826+                              int max_iterations=DB_DEFAULT_MAX_ITERATIONS,
16827+                              int max_points=DB_DEFAULT_MAX_POINTS,
16828+                              double scale=DB_POINT_STANDARDDEV,
16829+                              int nr_samples=DB_DEFAULT_NR_SAMPLES,
16830+                              int chunk_size=DB_DEFAULT_CHUNK_SIZE,
16831+                              ///////////////////////////////////////////////////
16832+                              // flag for the outlier removal
16833+                              int outlierremoveflagE = 0,
16834+                              // if flag is 1, then the following variables
16835+                              // need to input
16836+                              ///////////////////////////////////////////////////
16837+                              // 3D coordinates
16838+                              double *wp=NULL,
16839+                              // its corresponding stereo pair's points
16840+                              double *im_r=NULL,
16841+                              // raw image coordinates
16842+                              double *im_raw=NULL, double *im_raw_p=NULL,
16843+                              // final matches
16844+                              int *final_NumE=0);
16845+
16846+DB_API double db_RobImageHomography_Cost(double H[9],int point_count,double *x_i,
16847+                                                double *xp_i,double one_over_scale2);
16848+
16849+
16850+DB_API void db_RobCamRotation_Polish(double H[9],int point_count,double *x_i,
16851+                                     double *xp_i, double one_over_scale2,
16852+                                     int max_iterations=DB_DEFAULT_MAX_ITERATIONS,
16853+                                     double improvement_requirement=DB_DEFAULT_IMP_REQ);
16854+
16855+
16856+DB_API void db_RobCamRotation_Polish_Generic(double H[9],int point_count,int homography_type,
16857+                                             double *x_i,double *xp_i,double one_over_scale2,
16858+                                             int max_iterations=DB_DEFAULT_MAX_ITERATIONS,
16859+                                             double improvement_requirement=DB_DEFAULT_IMP_REQ);
16860+
16861+
16862+#endif /* DB_ROB_IMAGE_HOMOGRAPHY */
16863diff --git a/benchmark/feature_stab/db_vlvm/db_robust.h b/benchmark/feature_stab/db_vlvm/db_robust.h
16864new file mode 100644
16865index 00000000..be0794c6
16866--- /dev/null
16867+++ b/benchmark/feature_stab/db_vlvm/db_robust.h
16868@@ -0,0 +1,61 @@
16869+/*
16870+ * Copyright (C) 2011 The Android Open Source Project
16871+ *
16872+ * Licensed under the Apache License, Version 2.0 (the "License");
16873+ * you may not use this file except in compliance with the License.
16874+ * You may obtain a copy of the License at
16875+ *
16876+ *      http://www.apache.org/licenses/LICENSE-2.0
16877+ *
16878+ * Unless required by applicable law or agreed to in writing, software
16879+ * distributed under the License is distributed on an "AS IS" BASIS,
16880+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16881+ * See the License for the specific language governing permissions and
16882+ * limitations under the License.
16883+ */
16884+
16885+/* $Id: db_robust.h,v 1.4 2011/06/17 14:03:31 mbansal Exp $ */
16886+
16887+#ifndef DB_ROBUST
16888+#define DB_ROBUST
16889+
16890+
16891+
16892+/*****************************************************************
16893+*    Lean and mean begins here                                   *
16894+*****************************************************************/
16895+/*!
16896+ * \defgroup LMRobust (LM) Robust Estimation
16897+ */
16898+
16899+/*!
16900+    \struct     db_Statistics
16901+    \ingroup    LMRobust
16902+    \brief      (LnM) Sampling problem statistics
16903+    \date       Mon Sep 10 10:28:08 EDT 2007
16904+    \par        Copyright: 2007 Sarnoff Corporation.  All Rights Reserved
16905+ */
16906+ struct db_stat_struct
16907+ {
16908+     int nr_points;
16909+     int nr_inliers;
16910+     double inlier_fraction;
16911+     double cost;
16912+     double one_over_scale2;
16913+     double lambda1;
16914+     double lambda2;
16915+     double lambda3;
16916+     int nr_parameters;
16917+     int model_dimension;
16918+     double gric;
16919+     double inlier_evidence;
16920+     double posestd[6];
16921+     double rotationvecCov[9];
16922+     double translationvecCov[9];
16923+     int posecov_inliercount;
16924+     int posecovready;
16925+     double median_reprojection_error;
16926+ };
16927+ typedef db_stat_struct db_Statistics;
16928+
16929+#endif /* DB_ROBUST */
16930diff --git a/benchmark/feature_stab/db_vlvm/db_utilities.cpp b/benchmark/feature_stab/db_vlvm/db_utilities.cpp
16931new file mode 100644
16932index 00000000..ce2093b0
16933--- /dev/null
16934+++ b/benchmark/feature_stab/db_vlvm/db_utilities.cpp
16935@@ -0,0 +1,176 @@
16936+/*
16937+ * Copyright (C) 2011 The Android Open Source Project
16938+ *
16939+ * Licensed under the Apache License, Version 2.0 (the "License");
16940+ * you may not use this file except in compliance with the License.
16941+ * You may obtain a copy of the License at
16942+ *
16943+ *      http://www.apache.org/licenses/LICENSE-2.0
16944+ *
16945+ * Unless required by applicable law or agreed to in writing, software
16946+ * distributed under the License is distributed on an "AS IS" BASIS,
16947+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16948+ * See the License for the specific language governing permissions and
16949+ * limitations under the License.
16950+ */
16951+
16952+/* $Id: db_utilities.cpp,v 1.4 2011/06/17 14:03:31 mbansal Exp $ */
16953+
16954+#include "db_utilities.h"
16955+#include <string.h>
16956+#include <stdio.h>
16957+
16958+float** db_SetupImageReferences_f(float *im,int w,int h)
16959+{
16960+    int i;
16961+    float **img;
16962+    assert(im);
16963+    img=new float* [h];
16964+    for(i=0;i<h;i++)
16965+    {
16966+        img[i]=im+w*i;
16967+    }
16968+    return(img);
16969+}
16970+
16971+unsigned char** db_SetupImageReferences_u(unsigned char *im,int w,int h)
16972+{
16973+    int i;
16974+    unsigned char **img;
16975+
16976+    assert(im);
16977+
16978+    img=new unsigned char* [h];
16979+    for(i=0;i<h;i++)
16980+    {
16981+        img[i]=im+w*i;
16982+    }
16983+    return(img);
16984+}
16985+float** db_AllocImage_f(int w,int h,int over_allocation)
16986+{
16987+    float **img,*im;
16988+
16989+    im=new float [w*h+over_allocation];
16990+    img=db_SetupImageReferences_f(im,w,h);
16991+
16992+    return(img);
16993+}
16994+
16995+unsigned char** db_AllocImage_u(int w,int h,int over_allocation)
16996+{
16997+    unsigned char **img,*im;
16998+
16999+    im=new unsigned char [w*h+over_allocation];
17000+    img=db_SetupImageReferences_u(im,w,h);
17001+
17002+    return(img);
17003+}
17004+
17005+void db_FreeImage_f(float **img,int h)
17006+{
17007+    delete [] (img[0]);
17008+    delete [] img;
17009+}
17010+
17011+void db_FreeImage_u(unsigned char **img,int h)
17012+{
17013+    delete [] (img[0]);
17014+    delete [] img;
17015+}
17016+
17017+// ----------------------------------------------------------------------------------------------------------- ;
17018+//
17019+// copy image (source to destination)
17020+// ---> must be a 2D image array with the same image size
17021+// ---> the size of the input and output images must be same
17022+//
17023+// ------------------------------------------------------------------------------------------------------------ ;
17024+void db_CopyImage_u(unsigned char **d,const unsigned char * const *s, int w, int h, int over_allocation)
17025+{
17026+    int i;
17027+
17028+    for (i=0;i<h;i++)
17029+    {
17030+        memcpy(d[i],s[i],w*sizeof(unsigned char));
17031+    }
17032+
17033+    memcpy(&d[h],&d[h],over_allocation);
17034+
17035+}
17036+
17037+inline void db_WarpImageLutFast_u(const unsigned char * const * src, unsigned char ** dst, int w, int h,
17038+                                  const float * const * lut_x, const float * const * lut_y)
17039+{
17040+    assert(src && dst);
17041+    int xd=0, yd=0;
17042+
17043+    for ( int i = 0; i < w; ++i )
17044+        for ( int j = 0; j < h; ++j )
17045+        {
17046+            //xd = static_cast<unsigned int>(lut_x[j][i]);
17047+            //yd = static_cast<unsigned int>(lut_y[j][i]);
17048+            xd = (unsigned int)(lut_x[j][i]);
17049+            yd = (unsigned int)(lut_y[j][i]);
17050+            if ( xd >= w || yd >= h ||
17051+                 xd < 0 || yd < 0)
17052+                dst[j][i] = 0;
17053+            else
17054+                dst[j][i] = src[yd][xd];
17055+        }
17056+}
17057+
17058+inline void db_WarpImageLutBilinear_u(const unsigned char * const * src, unsigned char ** dst, int w, int h,
17059+                                      const float * const * lut_x,const float * const* lut_y)
17060+{
17061+    assert(src && dst);
17062+    double xd=0.0, yd=0.0;
17063+
17064+    for ( int i = 0; i < w; ++i )
17065+        for ( int j = 0; j < h; ++j )
17066+        {
17067+            xd = static_cast<double>(lut_x[j][i]);
17068+            yd = static_cast<double>(lut_y[j][i]);
17069+            if ( xd > w   || yd > h ||
17070+                 xd < 0.0 || yd < 0.0)
17071+                dst[j][i] = 0;
17072+            else
17073+                dst[j][i] = db_BilinearInterpolation(yd, xd, src);
17074+        }
17075+}
17076+
17077+
17078+void db_WarpImageLut_u(const unsigned char * const * src, unsigned char ** dst, int w, int h,
17079+                       const float * const * lut_x,const float * const * lut_y, int type)
17080+{
17081+    switch (type)
17082+    {
17083+    case DB_WARP_FAST:
17084+        db_WarpImageLutFast_u(src,dst,w,h,lut_x,lut_y);
17085+        break;
17086+    case DB_WARP_BILINEAR:
17087+        db_WarpImageLutBilinear_u(src,dst,w,h,lut_x,lut_y);
17088+        break;
17089+    default:
17090+        break;
17091+    }
17092+}
17093+
17094+
17095+void db_PrintDoubleVector(double *a,long size)
17096+{
17097+    printf("[ ");
17098+    for(long i=0;i<size;i++) printf("%lf ",a[i]);
17099+    printf("]");
17100+}
17101+
17102+void db_PrintDoubleMatrix(double *a,long rows,long cols)
17103+{
17104+    printf("[\n");
17105+    for(long i=0;i<rows;i++)
17106+    {
17107+        for(long j=0;j<cols;j++) printf("%lf ",a[i*cols+j]);
17108+        printf("\n");
17109+    }
17110+    printf("]");
17111+}
17112diff --git a/benchmark/feature_stab/db_vlvm/db_utilities.h b/benchmark/feature_stab/db_vlvm/db_utilities.h
17113new file mode 100644
17114index 00000000..fa9c8774
17115--- /dev/null
17116+++ b/benchmark/feature_stab/db_vlvm/db_utilities.h
17117@@ -0,0 +1,571 @@
17118+/*
17119+ * Copyright (C) 2011 The Android Open Source Project
17120+ *
17121+ * Licensed under the Apache License, Version 2.0 (the "License");
17122+ * you may not use this file except in compliance with the License.
17123+ * You may obtain a copy of the License at
17124+ *
17125+ *      http://www.apache.org/licenses/LICENSE-2.0
17126+ *
17127+ * Unless required by applicable law or agreed to in writing, software
17128+ * distributed under the License is distributed on an "AS IS" BASIS,
17129+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17130+ * See the License for the specific language governing permissions and
17131+ * limitations under the License.
17132+ */
17133+
17134+/* $Id: db_utilities.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
17135+
17136+#ifndef DB_UTILITIES_H
17137+#define DB_UTILITIES_H
17138+
17139+
17140+#ifdef _WIN32
17141+#pragma warning(disable: 4275)
17142+#pragma warning(disable: 4251)
17143+#pragma warning(disable: 4786)
17144+#pragma warning(disable: 4800)
17145+#pragma warning(disable: 4018) /* signed-unsigned mismatch */
17146+#endif /* _WIN32 */
17147+
17148+#ifdef _WIN32
17149+    #ifdef DBDYNAMIC_EXPORTS
17150+        #define DB_API __declspec(dllexport)
17151+    #else
17152+        #ifdef DBDYNAMIC_IMPORTS
17153+            #define DB_API __declspec(dllimport)
17154+        #else
17155+            #define DB_API
17156+        #endif
17157+    #endif
17158+#else
17159+    #define DB_API
17160+#endif /* _WIN32 */
17161+
17162+#ifdef _VERBOSE_
17163+#include <iostream>
17164+#endif
17165+
17166+#include <math.h>
17167+
17168+#include <assert.h>
17169+#include "db_utilities_constants.h"
17170+/*!
17171+ * \defgroup LMBasicUtilities (LM) Utility Functions (basic math, linear algebra and array manipulations)
17172+ */
17173+/*\{*/
17174+
17175+/*!
17176+ * Round double into int using fld and fistp instructions.
17177+ */
17178+inline int db_roundi (double x) {
17179+#ifdef WIN32_ASM
17180+    int n;
17181+    __asm
17182+    {
17183+        fld x;
17184+        fistp n;
17185+    }
17186+    return n;
17187+#else
17188+    return static_cast<int>(floor(x+0.5));
17189+#endif
17190+}
17191+
17192+/*!
17193+ * Square a double.
17194+ */
17195+inline double db_sqr(double a)
17196+{
17197+    return(a*a);
17198+}
17199+
17200+/*!
17201+ * Square a long.
17202+ */
17203+inline long db_sqr(long a)
17204+{
17205+    return(a*a);
17206+}
17207+
17208+/*!
17209+ * Square an int.
17210+ */
17211+inline long db_sqr(int a)
17212+{
17213+    return(a*a);
17214+}
17215+
17216+/*!
17217+ * Maximum of two doubles.
17218+ */
17219+inline double db_maxd(double a,double b)
17220+{
17221+    if(b>a) return(b);
17222+    else return(a);
17223+}
17224+/*!
17225+ * Minumum of two doubles.
17226+ */
17227+inline double db_mind(double a,double b)
17228+{
17229+    if(b<a) return(b);
17230+    else return(a);
17231+}
17232+
17233+
17234+/*!
17235+ * Maximum of two ints.
17236+ */
17237+inline int db_maxi(int a,int b)
17238+{
17239+    if(b>a) return(b);
17240+    else return(a);
17241+}
17242+
17243+/*!
17244+ * Minimum of two numbers.
17245+ */
17246+inline int db_mini(int a,int b)
17247+{
17248+    if(b<a) return(b);
17249+    else return(a);
17250+}
17251+/*!
17252+ * Maximum of two numbers.
17253+ */
17254+inline long db_maxl(long a,long b)
17255+{
17256+    if(b>a) return(b);
17257+    else return(a);
17258+}
17259+
17260+/*!
17261+ * Minimum of two numbers.
17262+ */
17263+inline long db_minl(long a,long b)
17264+{
17265+    if(b<a) return(b);
17266+    else return(a);
17267+}
17268+
17269+/*!
17270+ * Sign of a number.
17271+ * \return -1.0 if negative, 1.0 if positive.
17272+ */
17273+inline double db_sign(double x)
17274+{
17275+    if(x>=0.0) return(1.0);
17276+    else return(-1.0);
17277+}
17278+/*!
17279+ * Absolute value.
17280+ */
17281+inline int db_absi(int a)
17282+{
17283+    if(a<0) return(-a);
17284+    else return(a);
17285+}
17286+/*!
17287+ * Absolute value.
17288+ */
17289+inline float db_absf(float a)
17290+{
17291+    if(a<0) return(-a);
17292+    else return(a);
17293+}
17294+
17295+/*!
17296+ * Absolute value.
17297+ */
17298+inline double db_absd(double a)
17299+{
17300+    if(a<0) return(-a);
17301+    else return(a);
17302+}
17303+
17304+/*!
17305+ * Reciprocal (1/a). Prevents divide by 0.
17306+ * \return 1/a if a != 0. 1.0 otherwise.
17307+ */
17308+inline double db_SafeReciprocal(double a)
17309+{
17310+    return((a!=0.0)?(1.0/a):1.0);
17311+}
17312+
17313+/*!
17314+ * Division. Prevents divide by 0.
17315+ * \return a/b if b!=0. a otherwise.
17316+ */
17317+inline double db_SafeDivision(double a,double b)
17318+{
17319+    return((b!=0.0)?(a/b):a);
17320+}
17321+
17322+/*!
17323+ * Square root. Prevents imaginary output.
17324+ * \return sqrt(a) if a > 0.0. 0.0 otherewise.
17325+ */
17326+inline double db_SafeSqrt(double a)
17327+{
17328+    return((a>=0.0)?(sqrt(a)):0.0);
17329+}
17330+
17331+/*!
17332+ * Square root of a reciprocal. Prevents divide by 0 and imaginary output.
17333+ * \return sqrt(1/a) if a > 0.0. 1.0 otherewise.
17334+ */
17335+inline double db_SafeSqrtReciprocal(double a)
17336+{
17337+    return((a>0.0)?(sqrt(1.0/a)):1.0);
17338+}
17339+/*!
17340+ * Cube root.
17341+ */
17342+inline double db_CubRoot(double x)
17343+{
17344+    if(x>=0.0) return(pow(x,1.0/3.0));
17345+    else return(-pow(-x,1.0/3.0));
17346+}
17347+/*!
17348+ * Sum of squares of elements of x.
17349+ */
17350+inline double db_SquareSum3(const double x[3])
17351+{
17352+    return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2]));
17353+}
17354+/*!
17355+ * Sum of squares of elements of x.
17356+ */
17357+inline double db_SquareSum7(double x[7])
17358+{
17359+    return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2])+
17360+        db_sqr(x[3])+db_sqr(x[4])+db_sqr(x[5])+
17361+        db_sqr(x[6]));
17362+}
17363+/*!
17364+ * Sum of squares of elements of x.
17365+ */
17366+inline double db_SquareSum9(double x[9])
17367+{
17368+    return(db_sqr(x[0])+db_sqr(x[1])+db_sqr(x[2])+
17369+        db_sqr(x[3])+db_sqr(x[4])+db_sqr(x[5])+
17370+        db_sqr(x[6])+db_sqr(x[7])+db_sqr(x[8]));
17371+}
17372+/*!
17373+ * Copy a vector.
17374+ * \param xd destination
17375+ * \param xs source
17376+ */
17377+void inline db_Copy3(double xd[3],const double xs[3])
17378+{
17379+    xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2];
17380+}
17381+/*!
17382+ * Copy a vector.
17383+ * \param xd destination
17384+ * \param xs source
17385+ */
17386+void inline db_Copy6(double xd[6],const double xs[6])
17387+{
17388+    xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2];
17389+    xd[3]=xs[3];xd[4]=xs[4];xd[5]=xs[5];
17390+}
17391+/*!
17392+ * Copy a vector.
17393+ * \param xd destination
17394+ * \param xs source
17395+ */
17396+void inline db_Copy9(double xd[9],const double xs[9])
17397+{
17398+    xd[0]=xs[0];xd[1]=xs[1];xd[2]=xs[2];
17399+    xd[3]=xs[3];xd[4]=xs[4];xd[5]=xs[5];
17400+    xd[6]=xs[6];xd[7]=xs[7];xd[8]=xs[8];
17401+}
17402+
17403+/*!
17404+ * Scalar product: Transpose(A)*B.
17405+ */
17406+inline double db_ScalarProduct4(const double A[4],const double B[4])
17407+{
17408+    return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+A[3]*B[3]);
17409+}
17410+/*!
17411+ * Scalar product: Transpose(A)*B.
17412+ */
17413+inline double db_ScalarProduct7(const double A[7],const double B[7])
17414+{
17415+    return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+
17416+        A[3]*B[3]+A[4]*B[4]+A[5]*B[5]+
17417+        A[6]*B[6]);
17418+}
17419+/*!
17420+ * Scalar product: Transpose(A)*B.
17421+ */
17422+inline double db_ScalarProduct9(const double A[9],const double B[9])
17423+{
17424+    return(A[0]*B[0]+A[1]*B[1]+A[2]*B[2]+
17425+        A[3]*B[3]+A[4]*B[4]+A[5]*B[5]+
17426+        A[6]*B[6]+A[7]*B[7]+A[8]*B[8]);
17427+}
17428+/*!
17429+ * Vector addition: S=A+B.
17430+ */
17431+inline void db_AddVectors6(double S[6],const double A[6],const double B[6])
17432+{
17433+    S[0]=A[0]+B[0]; S[1]=A[1]+B[1]; S[2]=A[2]+B[2]; S[3]=A[3]+B[3]; S[4]=A[4]+B[4];
17434+    S[5]=A[5]+B[5];
17435+}
17436+/*!
17437+ * Multiplication: C(3x1)=A(3x3)*B(3x1).
17438+ */
17439+inline void db_Multiply3x3_3x1(double y[3],const double A[9],const double x[3])
17440+{
17441+    y[0]=A[0]*x[0]+A[1]*x[1]+A[2]*x[2];
17442+    y[1]=A[3]*x[0]+A[4]*x[1]+A[5]*x[2];
17443+    y[2]=A[6]*x[0]+A[7]*x[1]+A[8]*x[2];
17444+}
17445+inline void db_Multiply3x3_3x3(double C[9], const double A[9],const double B[9])
17446+{
17447+    C[0]=A[0]*B[0]+A[1]*B[3]+A[2]*B[6];
17448+    C[1]=A[0]*B[1]+A[1]*B[4]+A[2]*B[7];
17449+    C[2]=A[0]*B[2]+A[1]*B[5]+A[2]*B[8];
17450+
17451+    C[3]=A[3]*B[0]+A[4]*B[3]+A[5]*B[6];
17452+    C[4]=A[3]*B[1]+A[4]*B[4]+A[5]*B[7];
17453+    C[5]=A[3]*B[2]+A[4]*B[5]+A[5]*B[8];
17454+
17455+    C[6]=A[6]*B[0]+A[7]*B[3]+A[8]*B[6];
17456+    C[7]=A[6]*B[1]+A[7]*B[4]+A[8]*B[7];
17457+    C[8]=A[6]*B[2]+A[7]*B[5]+A[8]*B[8];
17458+}
17459+/*!
17460+ * Multiplication: C(4x1)=A(4x4)*B(4x1).
17461+ */
17462+inline void db_Multiply4x4_4x1(double y[4],const double A[16],const double x[4])
17463+{
17464+    y[0]=A[0]*x[0]+A[1]*x[1]+A[2]*x[2]+A[3]*x[3];
17465+    y[1]=A[4]*x[0]+A[5]*x[1]+A[6]*x[2]+A[7]*x[3];
17466+    y[2]=A[8]*x[0]+A[9]*x[1]+A[10]*x[2]+A[11]*x[3];
17467+    y[3]=A[12]*x[0]+A[13]*x[1]+A[14]*x[2]+A[15]*x[3];
17468+}
17469+/*!
17470+ * Scalar multiplication in place: A(3)=mult*A(3).
17471+ */
17472+inline void db_MultiplyScalar3(double *A,double mult)
17473+{
17474+    (*A++) *= mult; (*A++) *= mult; (*A++) *= mult;
17475+}
17476+
17477+/*!
17478+ * Scalar multiplication: A(3)=mult*B(3).
17479+ */
17480+inline void db_MultiplyScalarCopy3(double *A,const double *B,double mult)
17481+{
17482+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17483+}
17484+
17485+/*!
17486+ * Scalar multiplication: A(4)=mult*B(4).
17487+ */
17488+inline void db_MultiplyScalarCopy4(double *A,const double *B,double mult)
17489+{
17490+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17491+}
17492+/*!
17493+ * Scalar multiplication: A(7)=mult*B(7).
17494+ */
17495+inline void db_MultiplyScalarCopy7(double *A,const double *B,double mult)
17496+{
17497+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17498+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17499+}
17500+/*!
17501+ * Scalar multiplication: A(9)=mult*B(9).
17502+ */
17503+inline void db_MultiplyScalarCopy9(double *A,const double *B,double mult)
17504+{
17505+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17506+    (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult; (*A++)=(*B++)*mult;
17507+}
17508+
17509+/*!
17510+ * \defgroup LMImageBasicUtilities (LM) Basic Image Utility Functions
17511+
17512+ Images in db are simply 2D arrays of unsigned char or float types.
17513+ Only the very basic operations are supported: allocation/deallocation,
17514+copying, simple pyramid construction and LUT warping. These images are used
17515+by db_CornerDetector_u and db_Matcher_u. The db_Image class is an attempt
17516+to wrap these images. It has not been tested well.
17517+
17518+ */
17519+/*\{*/
17520+/*!
17521+ * Given a float image array, allocates and returns the set of row poiners.
17522+ * \param im    image pointer
17523+ * \param w     image width
17524+ * \param h     image height
17525+ */
17526+DB_API float** db_SetupImageReferences_f(float *im,int w,int h);
17527+/*!
17528+ * Allocate a float image.
17529+ * Note: for feature detection images must be overallocated by 256 bytes.
17530+ * \param w                 width
17531+ * \param h                 height
17532+ * \param over_allocation   allocate this many extra bytes at the end
17533+ * \return row array pointer
17534+ */
17535+DB_API float** db_AllocImage_f(int w,int h,int over_allocation=256);
17536+/*!
17537+ * Free a float image
17538+ * \param img   row array pointer
17539+ * \param h     image height (number of rows)
17540+ */
17541+DB_API void db_FreeImage_f(float **img,int h);
17542+/*!
17543+ * Given an unsigned char image array, allocates and returns the set of row poiners.
17544+ * \param im    image pointer
17545+ * \param w     image width
17546+ * \param h     image height
17547+ */
17548+DB_API unsigned char** db_SetupImageReferences_u(unsigned char *im,int w,int h);
17549+/*!
17550+ * Allocate an unsigned char image.
17551+ * Note: for feature detection images must be overallocated by 256 bytes.
17552+ * \param w                 width
17553+ * \param h                 height
17554+ * \param over_allocation   allocate this many extra bytes at the end
17555+ * \return row array pointer
17556+ */
17557+DB_API unsigned char** db_AllocImage_u(int w,int h,int over_allocation=256);
17558+/*!
17559+ * Free an unsigned char image
17560+ * \param img   row array pointer
17561+ * \param h     image height (number of rows)
17562+ */
17563+DB_API void db_FreeImage_u(unsigned char **img,int h);
17564+
17565+/*!
17566+ Copy an image from s to d. Both s and d must be pre-allocated at of the same size.
17567+ Copy is done row by row.
17568+ \param s   source
17569+ \param d   destination
17570+ \param w   width
17571+ \param h   height
17572+ \param over_allocation copy this many bytes after the end of the last line
17573+ */
17574+DB_API void db_CopyImage_u(unsigned char **d,const unsigned char * const *s,int w,int h,int over_allocation=0);
17575+
17576+DB_API inline unsigned char db_BilinearInterpolation(double y, double x, const unsigned char * const * v)
17577+{
17578+    int floor_x=(int) x;
17579+    int floor_y=(int) y;
17580+
17581+    int ceil_x=floor_x+1;
17582+    int ceil_y=floor_y+1;
17583+
17584+    unsigned char f00 = v[floor_y][floor_x];
17585+    unsigned char f01 = v[floor_y][ceil_x];
17586+    unsigned char f10 = v[ceil_y][floor_x];
17587+    unsigned char f11 = v[ceil_y][ceil_x];
17588+
17589+    double xl = x-floor_x;
17590+    double yl = y-floor_y;
17591+
17592+    return (unsigned char)(f00*(1-yl)*(1-xl) + f10*yl*(1-xl) + f01*(1-yl)*xl + f11*yl*xl);
17593+}
17594+/*\}*/
17595+/*!
17596+ * \ingroup LMRotation
17597+ * Compute an incremental rotation matrix using the update dx=[sin(phi) sin(ohm) sin(kap)]
17598+ */
17599+inline void db_IncrementalRotationMatrix(double R[9],const double dx[3])
17600+{
17601+    double sp,so,sk,om_sp2,om_so2,om_sk2,cp,co,ck,sp_so,cp_so;
17602+
17603+    /*Store sines*/
17604+    sp=dx[0]; so=dx[1]; sk=dx[2];
17605+    om_sp2=1.0-sp*sp;
17606+    om_so2=1.0-so*so;
17607+    om_sk2=1.0-sk*sk;
17608+    /*Compute cosines*/
17609+    cp=(om_sp2>=0.0)?sqrt(om_sp2):1.0;
17610+    co=(om_so2>=0.0)?sqrt(om_so2):1.0;
17611+    ck=(om_sk2>=0.0)?sqrt(om_sk2):1.0;
17612+    /*Compute matrix*/
17613+    sp_so=sp*so;
17614+    cp_so=cp*so;
17615+    R[0]=sp_so*sk+cp*ck; R[1]=co*sk; R[2]=cp_so*sk-sp*ck;
17616+    R[3]=sp_so*ck-cp*sk; R[4]=co*ck; R[5]=cp_so*ck+sp*sk;
17617+    R[6]=sp*co;          R[7]= -so;  R[8]=cp*co;
17618+}
17619+/*!
17620+ * Zero out 2 vector in place.
17621+ */
17622+void inline db_Zero2(double x[2])
17623+{
17624+    x[0]=x[1]=0;
17625+}
17626+/*!
17627+ * Zero out 3 vector in place.
17628+ */
17629+void inline db_Zero3(double x[3])
17630+{
17631+    x[0]=x[1]=x[2]=0;
17632+}
17633+/*!
17634+ * Zero out 4 vector in place.
17635+ */
17636+void inline db_Zero4(double x[4])
17637+{
17638+    x[0]=x[1]=x[2]=x[3]=0;
17639+}
17640+/*!
17641+ * Zero out 9 vector in place.
17642+ */
17643+void inline db_Zero9(double x[9])
17644+{
17645+    x[0]=x[1]=x[2]=x[3]=x[4]=x[5]=x[6]=x[7]=x[8]=0;
17646+}
17647+
17648+#define DB_WARP_FAST        0
17649+#define DB_WARP_BILINEAR    1
17650+
17651+/*!
17652+ * Perform a look-up table warp.
17653+ * The LUTs must be float images of the same size as source image.
17654+ * The source value x_s is determined from destination (x_d,y_d) through lut_x
17655+ * and y_s is determined from lut_y:
17656+   \code
17657+   x_s = lut_x[y_d][x_d];
17658+   y_s = lut_y[y_d][x_d];
17659+   \endcode
17660+
17661+ * \param src   source image
17662+ * \param dst   destination image
17663+ * \param w     width
17664+ * \param h     height
17665+ * \param lut_x LUT for x
17666+ * \param lut_y LUT for y
17667+ * \param type  warp type (DB_WARP_FAST or DB_WARP_BILINEAR)
17668+ */
17669+DB_API void db_WarpImageLut_u(const unsigned char * const * src,unsigned char ** dst, int w, int h,
17670+                               const float * const * lut_x, const float * const * lut_y, int type=DB_WARP_BILINEAR);
17671+
17672+DB_API void db_PrintDoubleVector(double *a,long size);
17673+DB_API void db_PrintDoubleMatrix(double *a,long rows,long cols);
17674+
17675+#include "db_utilities_constants.h"
17676+#include "db_utilities_algebra.h"
17677+#include "db_utilities_indexing.h"
17678+#include "db_utilities_linalg.h"
17679+#include "db_utilities_poly.h"
17680+#include "db_utilities_geometry.h"
17681+#include "db_utilities_random.h"
17682+#include "db_utilities_rotation.h"
17683+#include "db_utilities_camera.h"
17684+
17685+#define DB_INVALID (-1)
17686+
17687+
17688+#endif /* DB_UTILITIES_H */
17689diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h b/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h
17690new file mode 100644
17691index 00000000..2aedd74d
17692--- /dev/null
17693+++ b/benchmark/feature_stab/db_vlvm/db_utilities_algebra.h
17694@@ -0,0 +1,41 @@
17695+/*
17696+ * Copyright (C) 2011 The Android Open Source Project
17697+ *
17698+ * Licensed under the Apache License, Version 2.0 (the "License");
17699+ * you may not use this file except in compliance with the License.
17700+ * You may obtain a copy of the License at
17701+ *
17702+ *      http://www.apache.org/licenses/LICENSE-2.0
17703+ *
17704+ * Unless required by applicable law or agreed to in writing, software
17705+ * distributed under the License is distributed on an "AS IS" BASIS,
17706+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17707+ * See the License for the specific language governing permissions and
17708+ * limitations under the License.
17709+ */
17710+
17711+/* $Id: db_utilities_algebra.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
17712+
17713+#ifndef DB_UTILITIES_ALGEBRA
17714+#define DB_UTILITIES_ALGEBRA
17715+
17716+#include "db_utilities.h"
17717+
17718+
17719+
17720+/*****************************************************************
17721+*    Lean and mean begins here                                   *
17722+*****************************************************************/
17723+/*!
17724+ * \defgroup LMAlgebra (LM) Algebra utilities
17725+ */
17726+/*\{*/
17727+
17728+inline void db_HomogenousNormalize3(double *x)
17729+{
17730+    db_MultiplyScalar3(x,db_SafeSqrtReciprocal(db_SquareSum3(x)));
17731+}
17732+
17733+/*\}*/
17734+
17735+#endif /* DB_UTILITIES_ALGEBRA */
17736diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp
17737new file mode 100644
17738index 00000000..dceba9b6
17739--- /dev/null
17740+++ b/benchmark/feature_stab/db_vlvm/db_utilities_camera.cpp
17741@@ -0,0 +1,50 @@
17742+/*
17743+ * Copyright (C) 2011 The Android Open Source Project
17744+ *
17745+ * Licensed under the Apache License, Version 2.0 (the "License");
17746+ * you may not use this file except in compliance with the License.
17747+ * You may obtain a copy of the License at
17748+ *
17749+ *      http://www.apache.org/licenses/LICENSE-2.0
17750+ *
17751+ * Unless required by applicable law or agreed to in writing, software
17752+ * distributed under the License is distributed on an "AS IS" BASIS,
17753+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17754+ * See the License for the specific language governing permissions and
17755+ * limitations under the License.
17756+ */
17757+
17758+/* $Id: db_utilities_camera.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
17759+
17760+#include "db_utilities_camera.h"
17761+#include "db_utilities.h"
17762+#include <assert.h>
17763+
17764+
17765+
17766+/*****************************************************************
17767+*    Lean and mean begins here                                   *
17768+*****************************************************************/
17769+
17770+void db_Approx3DCalMat(double K[9],double Kinv[9],int im_width,int im_height,double f_correction,int field)
17771+{
17772+    double iw,ih,av_size,field_fact;
17773+
17774+    if(field) field_fact=2.0;
17775+    else field_fact=1.0;
17776+
17777+    iw=(double)im_width;
17778+    ih=(double)(im_height*field_fact);
17779+    av_size=(iw+ih)/2.0;
17780+    K[0]=f_correction*av_size;
17781+    K[1]=0;
17782+    K[2]=iw/2.0;
17783+    K[3]=0;
17784+    K[4]=f_correction*av_size/field_fact;
17785+    K[5]=ih/2.0/field_fact;
17786+    K[6]=0;
17787+    K[7]=0;
17788+    K[8]=1;
17789+
17790+    db_InvertCalibrationMatrix(Kinv,K);
17791+}
17792diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_camera.h b/benchmark/feature_stab/db_vlvm/db_utilities_camera.h
17793new file mode 100644
17794index 00000000..26ba4420
17795--- /dev/null
17796+++ b/benchmark/feature_stab/db_vlvm/db_utilities_camera.h
17797@@ -0,0 +1,332 @@
17798+/*
17799+ * Copyright (C) 2011 The Android Open Source Project
17800+ *
17801+ * Licensed under the Apache License, Version 2.0 (the "License");
17802+ * you may not use this file except in compliance with the License.
17803+ * You may obtain a copy of the License at
17804+ *
17805+ *      http://www.apache.org/licenses/LICENSE-2.0
17806+ *
17807+ * Unless required by applicable law or agreed to in writing, software
17808+ * distributed under the License is distributed on an "AS IS" BASIS,
17809+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17810+ * See the License for the specific language governing permissions and
17811+ * limitations under the License.
17812+ */
17813+
17814+/* $Id: db_utilities_camera.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
17815+
17816+#ifndef DB_UTILITIES_CAMERA
17817+#define DB_UTILITIES_CAMERA
17818+
17819+#include "db_utilities.h"
17820+
17821+
17822+
17823+/*****************************************************************
17824+*    Lean and mean begins here                                   *
17825+*****************************************************************/
17826+/*!
17827+ * \defgroup LMCamera (LM) Camera Utilities
17828+ */
17829+/*\{*/
17830+
17831+#include "db_utilities.h"
17832+
17833+#define DB_RADDISTMODE_BOUGEUT  4
17834+#define DB_RADDISTMODE_2NDORDER 5
17835+#define DB_RADDISTMODE_IDENTITY 6
17836+
17837+/*!
17838+Give reasonable guess of the calibration matrix for normalization purposes.
17839+Use real K matrix when doing real geometry.
17840+focal length = (w+h)/2.0*f_correction.
17841+\param K            calibration matrix (out)
17842+\param Kinv         inverse of K (out)
17843+\param im_width     image width
17844+\param im_height    image height
17845+\param f_correction focal length correction factor
17846+\param field        set to 1 if this is a field image (fy = fx/2)
17847+\return K(3x3) intrinsic calibration matrix
17848+*/
17849+DB_API void db_Approx3DCalMat(double K[9],double Kinv[9],int im_width,int im_height,double f_correction=1.0,int field=0);
17850+
17851+/*!
17852+ Make a 2x2 identity matrix
17853+ */
17854+void inline db_Identity2x2(double A[4])
17855+{
17856+    A[0]=1;A[1]=0;
17857+    A[2]=0;A[3]=1;
17858+}
17859+/*!
17860+ Make a 3x3 identity matrix
17861+ */
17862+void inline db_Identity3x3(double A[9])
17863+{
17864+    A[0]=1;A[1]=0;A[2]=0;
17865+    A[3]=0;A[4]=1;A[5]=0;
17866+    A[6]=0;A[7]=0;A[8]=1;
17867+}
17868+/*!
17869+ Invert intrinsic calibration matrix K(3x3)
17870+ If fx or fy is 0, I is returned.
17871+ */
17872+void inline db_InvertCalibrationMatrix(double Kinv[9],const double K[9])
17873+{
17874+    double a,b,c,d,e,f,ainv,dinv,adinv;
17875+
17876+    a=K[0];b=K[1];c=K[2];d=K[4];e=K[5];f=K[8];
17877+    if((a==0.0)||(d==0.0)) db_Identity3x3(Kinv);
17878+    else
17879+    {
17880+        Kinv[3]=0.0;
17881+        Kinv[6]=0.0;
17882+        Kinv[7]=0.0;
17883+        Kinv[8]=1.0;
17884+
17885+        ainv=1.0/a;
17886+        dinv=1.0/d;
17887+        adinv=ainv*dinv;
17888+        Kinv[0]=f*ainv;
17889+        Kinv[1]= -b*f*adinv;
17890+        Kinv[2]=(b*e-c*d)*adinv;
17891+        Kinv[4]=f*dinv;
17892+        Kinv[5]= -e*dinv;
17893+    }
17894+}
17895+/*!
17896+ De-homogenize image point: xd(1:2) = xs(1:2)/xs(3).
17897+ If xs(3) is 0, xd will become 0
17898+ \param xd  destination point
17899+ \param xs  source point
17900+ */
17901+void inline db_DeHomogenizeImagePoint(double xd[2],const double xs[3])
17902+{
17903+    double temp,div;
17904+
17905+    temp=xs[2];
17906+    if(temp!=0)
17907+    {
17908+        div=1.0/temp;
17909+        xd[0]=xs[0]*div;xd[1]=xs[1]*div;
17910+    }
17911+    else
17912+    {
17913+        xd[0]=0.0;xd[1]=0.0;
17914+    }
17915+}
17916+
17917+
17918+/*!
17919+ Orthonormalize 3D rotation R
17920+ */
17921+inline void db_OrthonormalizeRotation(double R[9])
17922+{
17923+    double s,mult;
17924+    /*Normalize first vector*/
17925+    s=db_sqr(R[0])+db_sqr(R[1])+db_sqr(R[2]);
17926+    mult=sqrt(1.0/(s?s:1));
17927+    R[0]*=mult; R[1]*=mult; R[2]*=mult;
17928+    /*Subtract scalar product from second vector*/
17929+    s=R[0]*R[3]+R[1]*R[4]+R[2]*R[5];
17930+    R[3]-=s*R[0]; R[4]-=s*R[1]; R[5]-=s*R[2];
17931+    /*Normalize second vector*/
17932+    s=db_sqr(R[3])+db_sqr(R[4])+db_sqr(R[5]);
17933+    mult=sqrt(1.0/(s?s:1));
17934+    R[3]*=mult; R[4]*=mult; R[5]*=mult;
17935+    /*Get third vector by vector product*/
17936+    R[6]=R[1]*R[5]-R[4]*R[2];
17937+    R[7]=R[2]*R[3]-R[5]*R[0];
17938+    R[8]=R[0]*R[4]-R[3]*R[1];
17939+}
17940+/*!
17941+Update a rotation with the update dx=[sin(phi) sin(ohm) sin(kap)]
17942+*/
17943+inline void db_UpdateRotation(double R_p_dx[9],double R[9],const double dx[3])
17944+{
17945+    double R_temp[9];
17946+    /*Update rotation*/
17947+    db_IncrementalRotationMatrix(R_temp,dx);
17948+    db_Multiply3x3_3x3(R_p_dx,R_temp,R);
17949+}
17950+/*!
17951+ Compute xp = Hx for inhomogenous image points.
17952+ */
17953+inline void db_ImageHomographyInhomogenous(double xp[2],const double H[9],const double x[2])
17954+{
17955+    double x3,m;
17956+
17957+    x3=H[6]*x[0]+H[7]*x[1]+H[8];
17958+    if(x3!=0.0)
17959+    {
17960+        m=1.0/x3;
17961+        xp[0]=m*(H[0]*x[0]+H[1]*x[1]+H[2]);
17962+        xp[1]=m*(H[3]*x[0]+H[4]*x[1]+H[5]);
17963+    }
17964+    else
17965+    {
17966+        xp[0]=xp[1]=0.0;
17967+    }
17968+}
17969+inline double db_FocalFromCamRotFocalHomography(const double H[9])
17970+{
17971+    double k1,k2;
17972+
17973+    k1=db_sqr(H[2])+db_sqr(H[5]);
17974+    k2=db_sqr(H[6])+db_sqr(H[7]);
17975+    if(k1>=k2)
17976+    {
17977+        return(db_SafeSqrt(db_SafeDivision(k1,1.0-db_sqr(H[8]))));
17978+    }
17979+    else
17980+    {
17981+        return(db_SafeSqrt(db_SafeDivision(1.0-db_sqr(H[8]),k2)));
17982+    }
17983+}
17984+
17985+inline double db_FocalAndRotFromCamRotFocalHomography(double R[9],const double H[9])
17986+{
17987+    double back,fi;
17988+
17989+    back=db_FocalFromCamRotFocalHomography(H);
17990+    fi=db_SafeReciprocal(back);
17991+    R[0]=H[0];      R[1]=H[1];      R[2]=fi*H[2];
17992+    R[3]=H[3];      R[4]=H[4];      R[5]=fi*H[5];
17993+    R[6]=back*H[6]; R[7]=back*H[7]; R[8]=H[8];
17994+    return(back);
17995+}
17996+/*!
17997+Compute Jacobian at zero of three coordinates dR*x with
17998+respect to the update dR([sin(phi) sin(ohm) sin(kap)]) given x.
17999+
18000+The Jacobian at zero of the homogenous coordinates with respect to
18001+    [sin(phi) sin(ohm) sin(kap)] is
18002+\code
18003+    [-rx2   0   rx1 ]
18004+    [  0   rx2 -rx0 ]
18005+    [ rx0 -rx1   0  ].
18006+\endcode
18007+
18008+*/
18009+inline void db_JacobianOfRotatedPointStride(double J[9],const double x[3],int stride)
18010+{
18011+    /*The Jacobian at zero of the homogenous coordinates with respect to
18012+    [sin(phi) sin(ohm) sin(kap)] is
18013+    [-rx2   0   rx1 ]
18014+    [  0   rx2 -rx0 ]
18015+    [ rx0 -rx1   0  ]*/
18016+
18017+    J[0]= -x[stride<<1];
18018+    J[1]=0;
18019+    J[2]=  x[stride];
18020+    J[3]=0;
18021+    J[4]=  x[stride<<1];
18022+    J[5]= -x[0];
18023+    J[6]=  x[0];
18024+    J[7]= -x[stride];
18025+    J[8]=0;
18026+}
18027+/*!
18028+ Invert an affine (if possible)
18029+ \param Hinv    inverted matrix
18030+ \param H       input matrix
18031+ \return true if success and false if matrix is ill-conditioned (det < 1e-7)
18032+ */
18033+inline bool db_InvertAffineTransform(double Hinv[9],const double H[9])
18034+{
18035+    double det=H[0]*H[4]-H[3]*H[1];
18036+    if (det<1e-7)
18037+    {
18038+        db_Copy9(Hinv,H);
18039+        return false;
18040+    }
18041+    else
18042+    {
18043+        Hinv[0]=H[4]/det;
18044+        Hinv[1]=-H[1]/det;
18045+        Hinv[3]=-H[3]/det;
18046+        Hinv[4]=H[0]/det;
18047+        Hinv[2]= -Hinv[0]*H[2]-Hinv[1]*H[5];
18048+        Hinv[5]= -Hinv[3]*H[2]-Hinv[4]*H[5];
18049+    }
18050+    return true;
18051+}
18052+
18053+/*!
18054+Update of upper 2x2 is multiplication by
18055+\code
18056+[s 0][ cos(theta) sin(theta)]
18057+[0 s][-sin(theta) cos(theta)]
18058+\endcode
18059+*/
18060+inline void db_MultiplyScaleOntoImageHomography(double H[9],double s)
18061+{
18062+
18063+    H[0]*=s;
18064+    H[1]*=s;
18065+    H[3]*=s;
18066+    H[4]*=s;
18067+}
18068+/*!
18069+Update of upper 2x2 is multiplication by
18070+\code
18071+[s 0][ cos(theta) sin(theta)]
18072+[0 s][-sin(theta) cos(theta)]
18073+\endcode
18074+*/
18075+inline void db_MultiplyRotationOntoImageHomography(double H[9],double theta)
18076+{
18077+    double c,s,H0,H1;
18078+
18079+
18080+    c=cos(theta);
18081+    s=db_SafeSqrt(1.0-db_sqr(c));
18082+    H0=  c*H[0]+s*H[3];
18083+    H[3]= -s*H[0]+c*H[3];
18084+    H[0]=H0;
18085+    H1=c*H[1]+s*H[4];
18086+    H[4]= -s*H[1]+c*H[4];
18087+    H[1]=H1;
18088+}
18089+
18090+inline void db_UpdateImageHomographyAffine(double H_p_dx[9],const double H[9],const double dx[6])
18091+{
18092+    db_AddVectors6(H_p_dx,H,dx);
18093+    db_Copy3(H_p_dx+6,H+6);
18094+}
18095+
18096+inline void db_UpdateImageHomographyProjective(double H_p_dx[9],const double H[9],const double dx[8],int frozen_coord)
18097+{
18098+    int i,j;
18099+
18100+    for(j=0,i=0;i<9;i++)
18101+    {
18102+        if(i!=frozen_coord)
18103+        {
18104+            H_p_dx[i]=H[i]+dx[j];
18105+            j++;
18106+        }
18107+        else H_p_dx[i]=H[i];
18108+    }
18109+}
18110+
18111+inline void db_UpdateRotFocalHomography(double H_p_dx[9],const double H[9],const double dx[4])
18112+{
18113+    double f,fp,fpi;
18114+    double R[9],dR[9];
18115+
18116+    /*Updated matrix is diag(f+df,f+df)*dR*R*diag(1/(f+df),1/(f+df),1)*/
18117+    f=db_FocalAndRotFromCamRotFocalHomography(R,H);
18118+    db_IncrementalRotationMatrix(dR,dx);
18119+    db_Multiply3x3_3x3(H_p_dx,dR,R);
18120+    fp=f+dx[3];
18121+    fpi=db_SafeReciprocal(fp);
18122+    H_p_dx[2]*=fp;
18123+    H_p_dx[5]*=fp;
18124+    H_p_dx[6]*=fpi;
18125+    H_p_dx[7]*=fpi;
18126+}
18127+
18128+/*\}*/
18129+#endif /* DB_UTILITIES_CAMERA */
18130diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_constants.h b/benchmark/feature_stab/db_vlvm/db_utilities_constants.h
18131new file mode 100644
18132index 00000000..07565efd
18133--- /dev/null
18134+++ b/benchmark/feature_stab/db_vlvm/db_utilities_constants.h
18135@@ -0,0 +1,208 @@
18136+/*
18137+ * Copyright (C) 2011 The Android Open Source Project
18138+ *
18139+ * Licensed under the Apache License, Version 2.0 (the "License");
18140+ * you may not use this file except in compliance with the License.
18141+ * You may obtain a copy of the License at
18142+ *
18143+ *      http://www.apache.org/licenses/LICENSE-2.0
18144+ *
18145+ * Unless required by applicable law or agreed to in writing, software
18146+ * distributed under the License is distributed on an "AS IS" BASIS,
18147+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18148+ * See the License for the specific language governing permissions and
18149+ * limitations under the License.
18150+ */
18151+
18152+/* $Id: db_utilities_constants.h,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
18153+
18154+#ifndef DB_UTILITIES_CONSTANTS
18155+#define DB_UTILITIES_CONSTANTS
18156+
18157+/*****************************************************************
18158+*    Lean and mean begins here                                   *
18159+*****************************************************************/
18160+
18161+/****************Constants********************/
18162+#define DB_E             2.7182818284590452354
18163+#define DB_LOG2E         1.4426950408889634074
18164+#define DB_LOG10E        0.43429448190325182765
18165+#define DB_LN2           0.69314718055994530942
18166+#define DB_LN10          2.30258509299404568402
18167+#define DB_PI            3.1415926535897932384626433832795
18168+#define DB_PI_2          1.57079632679489661923
18169+#define DB_PI_4          0.78539816339744830962
18170+#define DB_1_PI          0.31830988618379067154
18171+#define DB_2_PI          0.63661977236758134308
18172+#define DB_SQRTPI        1.7724538509055160272981674833411
18173+#define DB_SQRT_2PI      2.506628274631000502415765284811
18174+#define DB_2_SQRTPI      1.12837916709551257390
18175+#define DB_SQRT2         1.41421356237309504880
18176+#define DB_SQRT3         1.7320508075688772935274463415059
18177+#define DB_SQRT1_2       0.70710678118654752440
18178+#define DB_EPS           2.220446049250313e-016 /* for 32 bit double */
18179+
18180+/****************Default Parameters********************/
18181+/*Preemptive ransac parameters*/
18182+#define DB_DEFAULT_NR_SAMPLES 500
18183+#define DB_DEFAULT_CHUNK_SIZE 100
18184+#define DB_DEFAULT_GROUP_SIZE 10
18185+
18186+/*Optimisation parameters*/
18187+#define DB_DEFAULT_MAX_POINTS 1000
18188+#define DB_DEFAULT_MAX_ITERATIONS 25
18189+#define DB_DEFAULT_IMP_REQ 0.001
18190+
18191+/*Feature standard deviation parameters*/
18192+#define DB_POINT_STANDARDDEV (1.0/(826.0)) /*1 pixel for CIF (fraction of (image width+image height)/2)*/
18193+#define DB_OUTLIER_THRESHOLD 3.0 /*In number of DB_POINT_STANDARDDEV's*/
18194+#define DB_WORST_CASE 50.0 /*In number of DB_POINT_STANDARDDEV's*/
18195+
18196+/*Front-end parameters*/
18197+#define DB_DEFAULT_TARGET_NR_CORNERS 5000
18198+#define DB_DEFAULT_NR_FEATURE_BLOCKS 10
18199+#define DB_DEFAULT_ABS_CORNER_THRESHOLD 50000000.0
18200+#define DB_DEFAULT_REL_CORNER_THRESHOLD 0.00005
18201+#define DB_DEFAULT_MAX_DISPARITY 0.1
18202+#define DB_DEFAULT_NO_DISPARITY -1.0
18203+#define DB_DEFAULT_MAX_TRACK_LENGTH 300
18204+
18205+#define DB_DEFAULT_MAX_NR_CAMERAS 1000
18206+
18207+#define DB_DEFAULT_TRIPLE_STEP 2
18208+#define DB_DEFAULT_DOUBLE_STEP 2
18209+#define DB_DEFAULT_SINGLE_STEP 1
18210+#define DB_DEFAULT_NR_SINGLES 10
18211+#define DB_DEFAULT_NR_DOUBLES 1
18212+#define DB_DEFAULT_NR_TRIPLES 1
18213+
18214+#define DB_DEFAULT_TRIFOCAL_FOUR_STEPS 40
18215+
18216+#define DB_DEFAULT_EPIPOLAR_ERROR 1 /*in pixels*/
18217+
18218+////////////////////////// DOXYGEN /////////////////////
18219+
18220+/*!
18221+ * \def DB_DEFAULT_GROUP_SIZE
18222+ * \ingroup LMRobust
18223+ * \brief Default group size for db_PreemptiveRansac class.
18224+ * Group size is the number of observation costs multiplied together
18225+ * before a log of the product is added to the total cost.
18226+*/
18227+
18228+/*!
18229+ * \def DB_DEFAULT_TARGET_NR_CORNERS
18230+ * \ingroup FeatureDetection
18231+ * \brief Default target number of corners
18232+*/
18233+/*!
18234+ * \def DB_DEFAULT_NR_FEATURE_BLOCKS
18235+ * \ingroup FeatureDetection
18236+ * \brief Default number of regions (horizontal or vertical) that are considered separately
18237+ * for feature detection. The greater the number, the more uniform the distribution of
18238+ * detected features.
18239+*/
18240+/*!
18241+ * \def DB_DEFAULT_ABS_CORNER_THRESHOLD
18242+ * \ingroup FeatureDetection
18243+ * \brief Absolute feature strength threshold.
18244+*/
18245+/*!
18246+ * \def DB_DEFAULT_REL_CORNER_THRESHOLD
18247+ * \ingroup FeatureDetection
18248+ * \brief Relative feature strength threshold.
18249+*/
18250+/*!
18251+ * \def DB_DEFAULT_MAX_DISPARITY
18252+ * \ingroup FeatureMatching
18253+ * \brief Maximum disparity (as fraction of image size) allowed in feature matching
18254+*/
18255+ /*!
18256+ * \def DB_DEFAULT_NO_DISPARITY
18257+ * \ingroup FeatureMatching
18258+ * \brief Indicates that vertical disparity is the same as horizontal disparity.
18259+*/
18260+///////////////////////////////////////////////////////////////////////////////////
18261+ /*!
18262+ * \def DB_E
18263+ * \ingroup LMBasicUtilities
18264+ * \brief e
18265+*/
18266+ /*!
18267+ * \def DB_LOG2E
18268+ * \ingroup LMBasicUtilities
18269+ * \brief log2(e)
18270+*/
18271+ /*!
18272+ * \def DB_LOG10E
18273+ * \ingroup LMBasicUtilities
18274+ * \brief log10(e)
18275+*/
18276+ /*!
18277+ * \def DB_LOG10E
18278+ * \ingroup LMBasicUtilities
18279+ * \brief log10(e)
18280+*/
18281+/*!
18282+ * \def DB_LN2
18283+ * \ingroup LMBasicUtilities
18284+ * \brief ln(2)
18285+*/
18286+/*!
18287+ * \def DB_LN10
18288+ * \ingroup LMBasicUtilities
18289+ * \brief ln(10)
18290+*/
18291+/*!
18292+ * \def DB_PI
18293+ * \ingroup LMBasicUtilities
18294+ * \brief Pi
18295+*/
18296+/*!
18297+ * \def DB_PI_2
18298+ * \ingroup LMBasicUtilities
18299+ * \brief Pi/2
18300+*/
18301+/*!
18302+ * \def DB_PI_4
18303+ * \ingroup LMBasicUtilities
18304+ * \brief Pi/4
18305+*/
18306+/*!
18307+ * \def DB_1_PI
18308+ * \ingroup LMBasicUtilities
18309+ * \brief 1/Pi
18310+*/
18311+/*!
18312+ * \def DB_2_PI
18313+ * \ingroup LMBasicUtilities
18314+ * \brief 2/Pi
18315+*/
18316+/*!
18317+ * \def DB_SQRTPI
18318+ * \ingroup LMBasicUtilities
18319+ * \brief sqrt(Pi)
18320+*/
18321+/*!
18322+ * \def DB_SQRT_2PI
18323+ * \ingroup LMBasicUtilities
18324+ * \brief sqrt(2*Pi)
18325+*/
18326+/*!
18327+ * \def DB_SQRT2
18328+ * \ingroup LMBasicUtilities
18329+ * \brief sqrt(2)
18330+*/
18331+/*!
18332+ * \def DB_SQRT3
18333+ * \ingroup LMBasicUtilities
18334+ * \brief sqrt(3)
18335+*/
18336+/*!
18337+ * \def DB_SQRT1_2
18338+ * \ingroup LMBasicUtilities
18339+ * \brief sqrt(1/2)
18340+*/
18341+#endif /* DB_UTILITIES_CONSTANTS */
18342+
18343+
18344diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h b/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h
18345new file mode 100644
18346index 00000000..f2155846
18347--- /dev/null
18348+++ b/benchmark/feature_stab/db_vlvm/db_utilities_geometry.h
18349@@ -0,0 +1,121 @@
18350+/*
18351+ * Copyright (C) 2011 The Android Open Source Project
18352+ *
18353+ * Licensed under the Apache License, Version 2.0 (the "License");
18354+ * you may not use this file except in compliance with the License.
18355+ * You may obtain a copy of the License at
18356+ *
18357+ *      http://www.apache.org/licenses/LICENSE-2.0
18358+ *
18359+ * Unless required by applicable law or agreed to in writing, software
18360+ * distributed under the License is distributed on an "AS IS" BASIS,
18361+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18362+ * See the License for the specific language governing permissions and
18363+ * limitations under the License.
18364+ */
18365+
18366+/* $Id: db_utilities_geometry.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
18367+
18368+#ifndef DB_UTILITIES_GEOMETRY_H
18369+#define DB_UTILITIES_GEOMETRY_H
18370+
18371+#include "db_utilities.h"
18372+
18373+
18374+
18375+/*****************************************************************
18376+*    Lean and mean begins here                                   *
18377+*****************************************************************/
18378+/*! Get the inhomogenous 2D-point centroid of nr_point inhomogenous
18379+points in X*/
18380+inline void db_PointCentroid2D(double c[2],const double *X,int nr_points)
18381+{
18382+    int i;
18383+    double cx,cy,m;
18384+
18385+    cx=0;cy=0;
18386+    for(i=0;i<nr_points;i++)
18387+    {
18388+        cx+= *X++;
18389+        cy+= *X++;
18390+    }
18391+    if(nr_points)
18392+    {
18393+        m=1.0/((double)nr_points);
18394+        c[0]=cx*m;
18395+        c[1]=cy*m;
18396+    }
18397+    else c[0]=c[1]=0;
18398+}
18399+
18400+inline void db_PointCentroid2D(double c[2],const double * const *X,int nr_points)
18401+{
18402+    int i;
18403+    double cx,cy,m;
18404+    const double *temp;
18405+
18406+    cx=0;cy=0;
18407+    for(i=0;i<nr_points;i++)
18408+    {
18409+        temp= *X++;
18410+        cx+=temp[0];
18411+        cy+=temp[1];
18412+    }
18413+    if(nr_points)
18414+    {
18415+        m=1.0/((double)nr_points);
18416+        c[0]=cx*m;
18417+        c[1]=cy*m;
18418+    }
18419+    else c[0]=c[1]=0;
18420+}
18421+
18422+/*! Get the inhomogenous 3D-point centroid of nr_point inhomogenous
18423+points in X*/
18424+inline void db_PointCentroid3D(double c[3],const double *X,int nr_points)
18425+{
18426+    int i;
18427+    double cx,cy,cz,m;
18428+
18429+    cx=0;cy=0;cz=0;
18430+    for(i=0;i<nr_points;i++)
18431+    {
18432+        cx+= *X++;
18433+        cy+= *X++;
18434+        cz+= *X++;
18435+    }
18436+    if(nr_points)
18437+    {
18438+        m=1.0/((double)nr_points);
18439+        c[0]=cx*m;
18440+        c[1]=cy*m;
18441+        c[2]=cz*m;
18442+    }
18443+    else c[0]=c[1]=c[2]=0;
18444+}
18445+
18446+inline void db_PointCentroid3D(double c[3],const double * const *X,int nr_points)
18447+{
18448+    int i;
18449+    double cx,cy,cz,m;
18450+    const double *temp;
18451+
18452+    cx=0;cy=0;cz=0;
18453+    for(i=0;i<nr_points;i++)
18454+    {
18455+        temp= *X++;
18456+        cx+=temp[0];
18457+        cy+=temp[1];
18458+        cz+=temp[2];
18459+    }
18460+    if(nr_points)
18461+    {
18462+        m=1.0/((double)nr_points);
18463+        c[0]=cx*m;
18464+        c[1]=cy*m;
18465+        c[2]=cz*m;
18466+    }
18467+    else c[0]=c[1]=c[2]=0;
18468+}
18469+
18470+#endif /* DB_UTILITIES_GEOMETRY_H */
18471diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp
18472new file mode 100644
18473index 00000000..30ce03aa
18474--- /dev/null
18475+++ b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.cpp
18476@@ -0,0 +1,120 @@
18477+/*
18478+ * Copyright (C) 2011 The Android Open Source Project
18479+ *
18480+ * Licensed under the Apache License, Version 2.0 (the "License");
18481+ * you may not use this file except in compliance with the License.
18482+ * You may obtain a copy of the License at
18483+ *
18484+ *      http://www.apache.org/licenses/LICENSE-2.0
18485+ *
18486+ * Unless required by applicable law or agreed to in writing, software
18487+ * distributed under the License is distributed on an "AS IS" BASIS,
18488+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18489+ * See the License for the specific language governing permissions and
18490+ * limitations under the License.
18491+ */
18492+
18493+/* $Id: db_utilities_indexing.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
18494+
18495+#include "db_utilities_indexing.h"
18496+#include "db_utilities.h"
18497+
18498+
18499+
18500+/*****************************************************************
18501+*    Lean and mean begins here                                   *
18502+*****************************************************************/
18503+
18504+void db_Zero(double *d,long nr)
18505+{
18506+    long i;
18507+    for(i=0;i<nr;i++) d[i]=0.0;
18508+}
18509+
18510+/*This routine breaks number in source into values smaller and larger than
18511+a pivot element. Values equal to the pivot are ignored*/
18512+void db_LeanPartitionOnPivot(double pivot,double *dest,const double *source,long first,long last,long *first_equal,long *last_equal)
18513+{
18514+    double temp;
18515+    const double *s_point;
18516+    const double *s_top;
18517+    double *d_bottom;
18518+    double *d_top;
18519+
18520+    s_point=source+first;
18521+    s_top=source+last;
18522+    d_bottom=dest+first;
18523+    d_top=dest+last;
18524+
18525+    for(;s_point<=s_top;)
18526+    {
18527+        temp= *(s_point++);
18528+        if(temp<pivot) *(d_bottom++)=temp;
18529+        else if(temp>pivot) *(d_top--)=temp;
18530+    }
18531+    *first_equal=d_bottom-dest;
18532+    *last_equal=d_top-dest;
18533+}
18534+
18535+double db_LeanQuickSelect(const double *s,long nr_elements,long pos,double *temp)
18536+{
18537+  long first=0;
18538+  long last=nr_elements-1;
18539+  double pivot;
18540+  long first_equal,last_equal;
18541+  double *tempA;
18542+  double *tempB;
18543+  double *tempC;
18544+  const double *source;
18545+  double *dest;
18546+
18547+  tempA=temp;
18548+  tempB=temp+nr_elements;
18549+  source=s;
18550+  dest=tempA;
18551+
18552+  for(;last-first>2;)
18553+  {
18554+      pivot=db_TripleMedian(source[first],source[last],source[(first+last)/2]);
18555+      db_LeanPartitionOnPivot(pivot,dest,source,first,last,&first_equal,&last_equal);
18556+
18557+      if(first_equal>pos) last=first_equal-1;
18558+      else if(last_equal<pos) first=last_equal+1;
18559+      else
18560+      {
18561+        return(pivot);
18562+      }
18563+
18564+      /*Swap pointers*/
18565+      tempC=tempA;
18566+      tempA=tempB;
18567+      tempB=tempC;
18568+      source=tempB;
18569+      dest=tempA;
18570+  }
18571+  pivot=db_TripleMedian(source[first],source[last],source[(first+last)/2]);
18572+
18573+  return(pivot);
18574+}
18575+
18576+float* db_AlignPointer_f(float *p,unsigned long nr_bytes)
18577+{
18578+    float *ap;
18579+    unsigned long m;
18580+
18581+    m=((unsigned long)p)%nr_bytes;
18582+    if(m) ap=(float*) (((unsigned long)p)-m+nr_bytes);
18583+    else ap=p;
18584+    return(ap);
18585+}
18586+
18587+short* db_AlignPointer_s(short *p,unsigned long nr_bytes)
18588+{
18589+    short *ap;
18590+    unsigned long m;
18591+
18592+    m=((unsigned long)p)%nr_bytes;
18593+    if(m) ap=(short*) (((unsigned long)p)-m+nr_bytes);
18594+    else ap=p;
18595+    return(ap);
18596+}
18597diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h
18598new file mode 100644
18599index 00000000..01eeb9ea
18600--- /dev/null
18601+++ b/benchmark/feature_stab/db_vlvm/db_utilities_indexing.h
18602@@ -0,0 +1,270 @@
18603+/*
18604+ * Copyright (C) 2011 The Android Open Source Project
18605+ *
18606+ * Licensed under the Apache License, Version 2.0 (the "License");
18607+ * you may not use this file except in compliance with the License.
18608+ * You may obtain a copy of the License at
18609+ *
18610+ *      http://www.apache.org/licenses/LICENSE-2.0
18611+ *
18612+ * Unless required by applicable law or agreed to in writing, software
18613+ * distributed under the License is distributed on an "AS IS" BASIS,
18614+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18615+ * See the License for the specific language governing permissions and
18616+ * limitations under the License.
18617+ */
18618+
18619+/* $Id: db_utilities_indexing.h,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
18620+
18621+#ifndef DB_UTILITIES_INDEXING
18622+#define DB_UTILITIES_INDEXING
18623+
18624+
18625+
18626+/*****************************************************************
18627+*    Lean and mean begins here                                   *
18628+*****************************************************************/
18629+
18630+#include "db_utilities.h"
18631+
18632+/*!
18633+ * \defgroup LMIndexing (LM) Indexing Utilities (Order Statistics, Matrix Operations)
18634+ */
18635+/*\{*/
18636+
18637+inline void db_SetupMatrixRefs(double **ar,long rows,long cols,double *a)
18638+{
18639+    long i;
18640+    for(i=0;i<rows;i++) ar[i]=&a[i*cols];
18641+}
18642+
18643+inline void db_SymmetricExtendUpperToLower(double **A,int rows,int cols)
18644+{
18645+    int i,j;
18646+    for(i=1;i<rows;i++) for(j=0;j<i;j++) A[i][j]=A[j][i];
18647+}
18648+
18649+void inline db_MultiplyMatrixVectorAtb(double *c,const double * const *At,const double *b,int arows,int acols)
18650+{
18651+    int i,j;
18652+    double acc;
18653+
18654+    for(i=0;i<arows;i++)
18655+    {
18656+        acc=0;
18657+        for(j=0;j<acols;j++) acc+=At[j][i]*b[j];
18658+        c[i]=acc;
18659+    }
18660+}
18661+
18662+inline void db_MultiplyMatricesAB(double **C,const double * const *A,const double * const *B,int arows,int acols,int bcols)
18663+{
18664+    int i,j,k;
18665+    double acc;
18666+
18667+    for(i=0;i<arows;i++) for(j=0;j<bcols;j++)
18668+    {
18669+        acc=0;
18670+        for(k=0;k<acols;k++) acc+=A[i][k]*B[k][j];
18671+        C[i][j]=acc;
18672+    }
18673+}
18674+
18675+inline void db_UpperMultiplyMatricesAtB(double **Cu,const double * const *At,const double * const *B,int arows,int acols,int bcols)
18676+{
18677+    int i,j,k;
18678+    double acc;
18679+
18680+    for(i=0;i<arows;i++) for(j=i;j<bcols;j++)
18681+    {
18682+        acc=0;
18683+        for(k=0;k<acols;k++) acc+=At[k][i]*B[k][j];
18684+        Cu[i][j]=acc;
18685+    }
18686+}
18687+
18688+DB_API void db_Zero(double *d,long nr);
18689+
18690+inline int db_MaxIndex2(double s[2])
18691+{
18692+    if(s[0]>=s[1]) return(0);
18693+    return(1);
18694+}
18695+
18696+inline int db_MaxIndex3(const double s[3])
18697+{
18698+    double best;
18699+    int pos;
18700+
18701+    best=s[0];pos=0;
18702+    if(s[1]>best){best=s[1];pos=1;}
18703+    if(s[2]>best){best=s[2];pos=2;}
18704+    return(pos);
18705+}
18706+
18707+inline int db_MaxIndex4(const double s[4])
18708+{
18709+    double best;
18710+    int pos;
18711+
18712+    best=s[0];pos=0;
18713+    if(s[1]>best){best=s[1];pos=1;}
18714+    if(s[2]>best){best=s[2];pos=2;}
18715+    if(s[3]>best){best=s[3];pos=3;}
18716+    return(pos);
18717+}
18718+
18719+inline int db_MaxIndex5(const double s[5])
18720+{
18721+    double best;
18722+    int pos;
18723+
18724+    best=s[0];pos=0;
18725+    if(s[1]>best){best=s[1];pos=1;}
18726+    if(s[2]>best){best=s[2];pos=2;}
18727+    if(s[3]>best){best=s[3];pos=3;}
18728+    if(s[4]>best){best=s[4];pos=4;}
18729+    return(pos);
18730+}
18731+
18732+inline int db_MaxIndex6(const double s[6])
18733+{
18734+    double best;
18735+    int pos;
18736+
18737+    best=s[0];pos=0;
18738+    if(s[1]>best){best=s[1];pos=1;}
18739+    if(s[2]>best){best=s[2];pos=2;}
18740+    if(s[3]>best){best=s[3];pos=3;}
18741+    if(s[4]>best){best=s[4];pos=4;}
18742+    if(s[5]>best){best=s[5];pos=5;}
18743+    return(pos);
18744+}
18745+
18746+inline int db_MaxIndex7(const double s[7])
18747+{
18748+    double best;
18749+    int pos;
18750+
18751+    best=s[0];pos=0;
18752+    if(s[1]>best){best=s[1];pos=1;}
18753+    if(s[2]>best){best=s[2];pos=2;}
18754+    if(s[3]>best){best=s[3];pos=3;}
18755+    if(s[4]>best){best=s[4];pos=4;}
18756+    if(s[5]>best){best=s[5];pos=5;}
18757+    if(s[6]>best){best=s[6];pos=6;}
18758+    return(pos);
18759+}
18760+
18761+inline int db_MinIndex7(const double s[7])
18762+{
18763+    double best;
18764+    int pos;
18765+
18766+    best=s[0];pos=0;
18767+    if(s[1]<best){best=s[1];pos=1;}
18768+    if(s[2]<best){best=s[2];pos=2;}
18769+    if(s[3]<best){best=s[3];pos=3;}
18770+    if(s[4]<best){best=s[4];pos=4;}
18771+    if(s[5]<best){best=s[5];pos=5;}
18772+    if(s[6]<best){best=s[6];pos=6;}
18773+    return(pos);
18774+}
18775+
18776+inline int db_MinIndex9(const double s[9])
18777+{
18778+    double best;
18779+    int pos;
18780+
18781+    best=s[0];pos=0;
18782+    if(s[1]<best){best=s[1];pos=1;}
18783+    if(s[2]<best){best=s[2];pos=2;}
18784+    if(s[3]<best){best=s[3];pos=3;}
18785+    if(s[4]<best){best=s[4];pos=4;}
18786+    if(s[5]<best){best=s[5];pos=5;}
18787+    if(s[6]<best){best=s[6];pos=6;}
18788+    if(s[7]<best){best=s[7];pos=7;}
18789+    if(s[8]<best){best=s[8];pos=8;}
18790+    return(pos);
18791+}
18792+
18793+inline int db_MaxAbsIndex3(const double *s)
18794+{
18795+    double t,best;
18796+    int pos;
18797+
18798+    best=fabs(s[0]);pos=0;
18799+    t=fabs(s[1]);if(t>best){best=t;pos=1;}
18800+    t=fabs(s[2]);if(t>best){pos=2;}
18801+    return(pos);
18802+}
18803+
18804+inline int db_MaxAbsIndex9(const double *s)
18805+{
18806+    double t,best;
18807+    int pos;
18808+
18809+    best=fabs(s[0]);pos=0;
18810+    t=fabs(s[1]);if(t>best){best=t;pos=1;}
18811+    t=fabs(s[2]);if(t>best){best=t;pos=2;}
18812+    t=fabs(s[3]);if(t>best){best=t;pos=3;}
18813+    t=fabs(s[4]);if(t>best){best=t;pos=4;}
18814+    t=fabs(s[5]);if(t>best){best=t;pos=5;}
18815+    t=fabs(s[6]);if(t>best){best=t;pos=6;}
18816+    t=fabs(s[7]);if(t>best){best=t;pos=7;}
18817+    t=fabs(s[8]);if(t>best){best=t;pos=8;}
18818+    return(pos);
18819+}
18820+
18821+
18822+/*!
18823+Select ordinal pos (zero based) out of nr_elements in s.
18824+temp should point to alloced memory of at least nr_elements*2
18825+Optimized runtimes on 450MHz:
18826+\code
18827+  30 with   3 microsecs
18828+ 100 with  11 microsecs
18829+ 300 with  30 microsecs
18830+ 500 with  40 microsecs
18831+1000 with 100 microsecs
18832+5000 with 540 microsecs
18833+\endcode
18834+so the expected runtime is around
18835+(nr_elements/10) microseconds
18836+The total quickselect cost of splitting 500 hypotheses recursively
18837+is thus around 100 microseconds
18838+
18839+Does the same operation as std::nth_element().
18840+*/
18841+DB_API double db_LeanQuickSelect(const double *s,long nr_elements,long pos,double *temp);
18842+
18843+/*!
18844+ Median of 3 doubles
18845+ */
18846+inline double db_TripleMedian(double a,double b,double c)
18847+{
18848+    if(a>b)
18849+    {
18850+        if(c>a) return(a);
18851+        else if(c>b) return(c);
18852+        else return(b);
18853+    }
18854+    else
18855+    {
18856+        if(c>b) return(b);
18857+        else if(c>a) return(c);
18858+        else return(a);
18859+    }
18860+}
18861+
18862+/*!
18863+Align float pointer to nr_bytes by moving forward
18864+*/
18865+DB_API float* db_AlignPointer_f(float *p,unsigned long nr_bytes);
18866+
18867+/*!
18868+Align short pointer to nr_bytes by moving forward
18869+*/
18870+DB_API short* db_AlignPointer_s(short *p,unsigned long nr_bytes);
18871+
18872+#endif /* DB_UTILITIES_INDEXING */
18873diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp
18874new file mode 100644
18875index 00000000..8f68b303
18876--- /dev/null
18877+++ b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.cpp
18878@@ -0,0 +1,376 @@
18879+/*
18880+ * Copyright (C) 2011 The Android Open Source Project
18881+ *
18882+ * Licensed under the Apache License, Version 2.0 (the "License");
18883+ * you may not use this file except in compliance with the License.
18884+ * You may obtain a copy of the License at
18885+ *
18886+ *      http://www.apache.org/licenses/LICENSE-2.0
18887+ *
18888+ * Unless required by applicable law or agreed to in writing, software
18889+ * distributed under the License is distributed on an "AS IS" BASIS,
18890+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18891+ * See the License for the specific language governing permissions and
18892+ * limitations under the License.
18893+ */
18894+
18895+/* $Id: db_utilities_linalg.cpp,v 1.3 2011/06/17 14:03:31 mbansal Exp $ */
18896+
18897+#include "db_utilities_linalg.h"
18898+#include "db_utilities.h"
18899+
18900+
18901+
18902+/*****************************************************************
18903+*    Lean and mean begins here                                   *
18904+*****************************************************************/
18905+
18906+/*Cholesky-factorize symmetric positive definite 6 x 6 matrix A. Upper
18907+part of A is used from the input. The Cholesky factor is output as
18908+subdiagonal part in A and diagonal in d, which is 6-dimensional*/
18909+void db_CholeskyDecomp6x6(double A[36],double d[6])
18910+{
18911+    double s,temp;
18912+
18913+    /*[50 mult 35 add 6sqrt=85flops 6func]*/
18914+    /*i=0*/
18915+    s=A[0];
18916+    d[0]=((s>0.0)?sqrt(s):1.0);
18917+    temp=db_SafeReciprocal(d[0]);
18918+    A[6]=A[1]*temp;
18919+    A[12]=A[2]*temp;
18920+    A[18]=A[3]*temp;
18921+    A[24]=A[4]*temp;
18922+    A[30]=A[5]*temp;
18923+    /*i=1*/
18924+    s=A[7]-A[6]*A[6];
18925+    d[1]=((s>0.0)?sqrt(s):1.0);
18926+    temp=db_SafeReciprocal(d[1]);
18927+    A[13]=(A[8]-A[6]*A[12])*temp;
18928+    A[19]=(A[9]-A[6]*A[18])*temp;
18929+    A[25]=(A[10]-A[6]*A[24])*temp;
18930+    A[31]=(A[11]-A[6]*A[30])*temp;
18931+    /*i=2*/
18932+    s=A[14]-A[12]*A[12]-A[13]*A[13];
18933+    d[2]=((s>0.0)?sqrt(s):1.0);
18934+    temp=db_SafeReciprocal(d[2]);
18935+    A[20]=(A[15]-A[12]*A[18]-A[13]*A[19])*temp;
18936+    A[26]=(A[16]-A[12]*A[24]-A[13]*A[25])*temp;
18937+    A[32]=(A[17]-A[12]*A[30]-A[13]*A[31])*temp;
18938+    /*i=3*/
18939+    s=A[21]-A[18]*A[18]-A[19]*A[19]-A[20]*A[20];
18940+    d[3]=((s>0.0)?sqrt(s):1.0);
18941+    temp=db_SafeReciprocal(d[3]);
18942+    A[27]=(A[22]-A[18]*A[24]-A[19]*A[25]-A[20]*A[26])*temp;
18943+    A[33]=(A[23]-A[18]*A[30]-A[19]*A[31]-A[20]*A[32])*temp;
18944+    /*i=4*/
18945+    s=A[28]-A[24]*A[24]-A[25]*A[25]-A[26]*A[26]-A[27]*A[27];
18946+    d[4]=((s>0.0)?sqrt(s):1.0);
18947+    temp=db_SafeReciprocal(d[4]);
18948+    A[34]=(A[29]-A[24]*A[30]-A[25]*A[31]-A[26]*A[32]-A[27]*A[33])*temp;
18949+    /*i=5*/
18950+    s=A[35]-A[30]*A[30]-A[31]*A[31]-A[32]*A[32]-A[33]*A[33]-A[34]*A[34];
18951+    d[5]=((s>0.0)?sqrt(s):1.0);
18952+}
18953+
18954+/*Cholesky-factorize symmetric positive definite n x n matrix A.Part
18955+above diagonal of A is used from the input, diagonal of A is assumed to
18956+be stored in d. The Cholesky factor is output as
18957+subdiagonal part in A and diagonal in d, which is n-dimensional*/
18958+void db_CholeskyDecompSeparateDiagonal(double **A,double *d,int n)
18959+{
18960+    int i,j,k;
18961+    double s;
18962+    double temp = 0.0;
18963+
18964+    for(i=0;i<n;i++) for(j=i;j<n;j++)
18965+    {
18966+        if(i==j) s=d[i];
18967+        else s=A[i][j];
18968+        for(k=i-1;k>=0;k--) s-=A[i][k]*A[j][k];
18969+        if(i==j)
18970+        {
18971+            d[i]=((s>0.0)?sqrt(s):1.0);
18972+            temp=db_SafeReciprocal(d[i]);
18973+        }
18974+        else A[j][i]=s*temp;
18975+    }
18976+}
18977+
18978+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
18979+of an n x n matrix and the right hand side b. The vector b is unchanged*/
18980+void db_CholeskyBacksub(double *x,const double * const *A,const double *d,int n,const double *b)
18981+{
18982+    int i,k;
18983+    double s;
18984+
18985+    for(i=0;i<n;i++)
18986+    {
18987+        for(s=b[i],k=i-1;k>=0;k--) s-=A[i][k]*x[k];
18988+        x[i]=db_SafeDivision(s,d[i]);
18989+    }
18990+    for(i=n-1;i>=0;i--)
18991+    {
18992+        for(s=x[i],k=i+1;k<n;k++) s-=A[k][i]*x[k];
18993+        x[i]=db_SafeDivision(s,d[i]);
18994+    }
18995+}
18996+
18997+/*Cholesky-factorize symmetric positive definite 3 x 3 matrix A. Part
18998+above diagonal of A is used from the input, diagonal of A is assumed to
18999+be stored in d. The Cholesky factor is output as subdiagonal part in A
19000+and diagonal in d, which is 3-dimensional*/
19001+void db_CholeskyDecomp3x3SeparateDiagonal(double A[9],double d[3])
19002+{
19003+    double s,temp;
19004+
19005+    /*i=0*/
19006+    s=d[0];
19007+    d[0]=((s>0.0)?sqrt(s):1.0);
19008+    temp=db_SafeReciprocal(d[0]);
19009+    A[3]=A[1]*temp;
19010+    A[6]=A[2]*temp;
19011+    /*i=1*/
19012+    s=d[1]-A[3]*A[3];
19013+    d[1]=((s>0.0)?sqrt(s):1.0);
19014+    temp=db_SafeReciprocal(d[1]);
19015+    A[7]=(A[5]-A[3]*A[6])*temp;
19016+    /*i=2*/
19017+    s=d[2]-A[6]*A[6]-A[7]*A[7];
19018+    d[2]=((s>0.0)?sqrt(s):1.0);
19019+}
19020+
19021+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
19022+of a 3 x 3 matrix and the right hand side b. The vector b is unchanged*/
19023+void db_CholeskyBacksub3x3(double x[3],const double A[9],const double d[3],const double b[3])
19024+{
19025+    /*[42 mult 30 add=72flops]*/
19026+    x[0]=db_SafeDivision(b[0],d[0]);
19027+    x[1]=db_SafeDivision((b[1]-A[3]*x[0]),d[1]);
19028+    x[2]=db_SafeDivision((b[2]-A[6]*x[0]-A[7]*x[1]),d[2]);
19029+    x[2]=db_SafeDivision(x[2],d[2]);
19030+    x[1]=db_SafeDivision((x[1]-A[7]*x[2]),d[1]);
19031+    x[0]=db_SafeDivision((x[0]-A[6]*x[2]-A[3]*x[1]),d[0]);
19032+}
19033+
19034+/*Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
19035+of a 6 x 6 matrix and the right hand side b. The vector b is unchanged*/
19036+void db_CholeskyBacksub6x6(double x[6],const double A[36],const double d[6],const double b[6])
19037+{
19038+    /*[42 mult 30 add=72flops]*/
19039+    x[0]=db_SafeDivision(b[0],d[0]);
19040+    x[1]=db_SafeDivision((b[1]-A[6]*x[0]),d[1]);
19041+    x[2]=db_SafeDivision((b[2]-A[12]*x[0]-A[13]*x[1]),d[2]);
19042+    x[3]=db_SafeDivision((b[3]-A[18]*x[0]-A[19]*x[1]-A[20]*x[2]),d[3]);
19043+    x[4]=db_SafeDivision((b[4]-A[24]*x[0]-A[25]*x[1]-A[26]*x[2]-A[27]*x[3]),d[4]);
19044+    x[5]=db_SafeDivision((b[5]-A[30]*x[0]-A[31]*x[1]-A[32]*x[2]-A[33]*x[3]-A[34]*x[4]),d[5]);
19045+    x[5]=db_SafeDivision(x[5],d[5]);
19046+    x[4]=db_SafeDivision((x[4]-A[34]*x[5]),d[4]);
19047+    x[3]=db_SafeDivision((x[3]-A[33]*x[5]-A[27]*x[4]),d[3]);
19048+    x[2]=db_SafeDivision((x[2]-A[32]*x[5]-A[26]*x[4]-A[20]*x[3]),d[2]);
19049+    x[1]=db_SafeDivision((x[1]-A[31]*x[5]-A[25]*x[4]-A[19]*x[3]-A[13]*x[2]),d[1]);
19050+    x[0]=db_SafeDivision((x[0]-A[30]*x[5]-A[24]*x[4]-A[18]*x[3]-A[12]*x[2]-A[6]*x[1]),d[0]);
19051+}
19052+
19053+
19054+void db_Orthogonalize6x7(double A[42],int orthonormalize)
19055+{
19056+    int i;
19057+    double ss[6];
19058+
19059+    /*Compute square sums of rows*/
19060+    ss[0]=db_SquareSum7(A);
19061+    ss[1]=db_SquareSum7(A+7);
19062+    ss[2]=db_SquareSum7(A+14);
19063+    ss[3]=db_SquareSum7(A+21);
19064+    ss[4]=db_SquareSum7(A+28);
19065+    ss[5]=db_SquareSum7(A+35);
19066+
19067+    ss[1]-=db_OrthogonalizePair7(A+7 ,A,ss[0]);
19068+    ss[2]-=db_OrthogonalizePair7(A+14,A,ss[0]);
19069+    ss[3]-=db_OrthogonalizePair7(A+21,A,ss[0]);
19070+    ss[4]-=db_OrthogonalizePair7(A+28,A,ss[0]);
19071+    ss[5]-=db_OrthogonalizePair7(A+35,A,ss[0]);
19072+
19073+    /*Pivot on largest ss (could also be done on ss/(original_ss))*/
19074+    i=db_MaxIndex5(ss+1);
19075+    db_OrthogonalizationSwap7(A+7,i,ss+1);
19076+
19077+    ss[2]-=db_OrthogonalizePair7(A+14,A+7,ss[1]);
19078+    ss[3]-=db_OrthogonalizePair7(A+21,A+7,ss[1]);
19079+    ss[4]-=db_OrthogonalizePair7(A+28,A+7,ss[1]);
19080+    ss[5]-=db_OrthogonalizePair7(A+35,A+7,ss[1]);
19081+
19082+    i=db_MaxIndex4(ss+2);
19083+    db_OrthogonalizationSwap7(A+14,i,ss+2);
19084+
19085+    ss[3]-=db_OrthogonalizePair7(A+21,A+14,ss[2]);
19086+    ss[4]-=db_OrthogonalizePair7(A+28,A+14,ss[2]);
19087+    ss[5]-=db_OrthogonalizePair7(A+35,A+14,ss[2]);
19088+
19089+    i=db_MaxIndex3(ss+3);
19090+    db_OrthogonalizationSwap7(A+21,i,ss+3);
19091+
19092+    ss[4]-=db_OrthogonalizePair7(A+28,A+21,ss[3]);
19093+    ss[5]-=db_OrthogonalizePair7(A+35,A+21,ss[3]);
19094+
19095+    i=db_MaxIndex2(ss+4);
19096+    db_OrthogonalizationSwap7(A+28,i,ss+4);
19097+
19098+    ss[5]-=db_OrthogonalizePair7(A+35,A+28,ss[4]);
19099+
19100+    if(orthonormalize)
19101+    {
19102+        db_MultiplyScalar7(A   ,db_SafeSqrtReciprocal(ss[0]));
19103+        db_MultiplyScalar7(A+7 ,db_SafeSqrtReciprocal(ss[1]));
19104+        db_MultiplyScalar7(A+14,db_SafeSqrtReciprocal(ss[2]));
19105+        db_MultiplyScalar7(A+21,db_SafeSqrtReciprocal(ss[3]));
19106+        db_MultiplyScalar7(A+28,db_SafeSqrtReciprocal(ss[4]));
19107+        db_MultiplyScalar7(A+35,db_SafeSqrtReciprocal(ss[5]));
19108+    }
19109+}
19110+
19111+void db_Orthogonalize8x9(double A[72],int orthonormalize)
19112+{
19113+    int i;
19114+    double ss[8];
19115+
19116+    /*Compute square sums of rows*/
19117+    ss[0]=db_SquareSum9(A);
19118+    ss[1]=db_SquareSum9(A+9);
19119+    ss[2]=db_SquareSum9(A+18);
19120+    ss[3]=db_SquareSum9(A+27);
19121+    ss[4]=db_SquareSum9(A+36);
19122+    ss[5]=db_SquareSum9(A+45);
19123+    ss[6]=db_SquareSum9(A+54);
19124+    ss[7]=db_SquareSum9(A+63);
19125+
19126+    ss[1]-=db_OrthogonalizePair9(A+9 ,A,ss[0]);
19127+    ss[2]-=db_OrthogonalizePair9(A+18,A,ss[0]);
19128+    ss[3]-=db_OrthogonalizePair9(A+27,A,ss[0]);
19129+    ss[4]-=db_OrthogonalizePair9(A+36,A,ss[0]);
19130+    ss[5]-=db_OrthogonalizePair9(A+45,A,ss[0]);
19131+    ss[6]-=db_OrthogonalizePair9(A+54,A,ss[0]);
19132+    ss[7]-=db_OrthogonalizePair9(A+63,A,ss[0]);
19133+
19134+    /*Pivot on largest ss (could also be done on ss/(original_ss))*/
19135+    i=db_MaxIndex7(ss+1);
19136+    db_OrthogonalizationSwap9(A+9,i,ss+1);
19137+
19138+    ss[2]-=db_OrthogonalizePair9(A+18,A+9,ss[1]);
19139+    ss[3]-=db_OrthogonalizePair9(A+27,A+9,ss[1]);
19140+    ss[4]-=db_OrthogonalizePair9(A+36,A+9,ss[1]);
19141+    ss[5]-=db_OrthogonalizePair9(A+45,A+9,ss[1]);
19142+    ss[6]-=db_OrthogonalizePair9(A+54,A+9,ss[1]);
19143+    ss[7]-=db_OrthogonalizePair9(A+63,A+9,ss[1]);
19144+
19145+    i=db_MaxIndex6(ss+2);
19146+    db_OrthogonalizationSwap9(A+18,i,ss+2);
19147+
19148+    ss[3]-=db_OrthogonalizePair9(A+27,A+18,ss[2]);
19149+    ss[4]-=db_OrthogonalizePair9(A+36,A+18,ss[2]);
19150+    ss[5]-=db_OrthogonalizePair9(A+45,A+18,ss[2]);
19151+    ss[6]-=db_OrthogonalizePair9(A+54,A+18,ss[2]);
19152+    ss[7]-=db_OrthogonalizePair9(A+63,A+18,ss[2]);
19153+
19154+    i=db_MaxIndex5(ss+3);
19155+    db_OrthogonalizationSwap9(A+27,i,ss+3);
19156+
19157+    ss[4]-=db_OrthogonalizePair9(A+36,A+27,ss[3]);
19158+    ss[5]-=db_OrthogonalizePair9(A+45,A+27,ss[3]);
19159+    ss[6]-=db_OrthogonalizePair9(A+54,A+27,ss[3]);
19160+    ss[7]-=db_OrthogonalizePair9(A+63,A+27,ss[3]);
19161+
19162+    i=db_MaxIndex4(ss+4);
19163+    db_OrthogonalizationSwap9(A+36,i,ss+4);
19164+
19165+    ss[5]-=db_OrthogonalizePair9(A+45,A+36,ss[4]);
19166+    ss[6]-=db_OrthogonalizePair9(A+54,A+36,ss[4]);
19167+    ss[7]-=db_OrthogonalizePair9(A+63,A+36,ss[4]);
19168+
19169+    i=db_MaxIndex3(ss+5);
19170+    db_OrthogonalizationSwap9(A+45,i,ss+5);
19171+
19172+    ss[6]-=db_OrthogonalizePair9(A+54,A+45,ss[5]);
19173+    ss[7]-=db_OrthogonalizePair9(A+63,A+45,ss[5]);
19174+
19175+    i=db_MaxIndex2(ss+6);
19176+    db_OrthogonalizationSwap9(A+54,i,ss+6);
19177+
19178+    ss[7]-=db_OrthogonalizePair9(A+63,A+54,ss[6]);
19179+
19180+    if(orthonormalize)
19181+    {
19182+        db_MultiplyScalar9(A   ,db_SafeSqrtReciprocal(ss[0]));
19183+        db_MultiplyScalar9(A+9 ,db_SafeSqrtReciprocal(ss[1]));
19184+        db_MultiplyScalar9(A+18,db_SafeSqrtReciprocal(ss[2]));
19185+        db_MultiplyScalar9(A+27,db_SafeSqrtReciprocal(ss[3]));
19186+        db_MultiplyScalar9(A+36,db_SafeSqrtReciprocal(ss[4]));
19187+        db_MultiplyScalar9(A+45,db_SafeSqrtReciprocal(ss[5]));
19188+        db_MultiplyScalar9(A+54,db_SafeSqrtReciprocal(ss[6]));
19189+        db_MultiplyScalar9(A+63,db_SafeSqrtReciprocal(ss[7]));
19190+    }
19191+}
19192+
19193+void db_NullVectorOrthonormal6x7(double x[7],const double A[42])
19194+{
19195+    int i;
19196+    double omss[7];
19197+    const double *B;
19198+
19199+    /*Pivot by choosing row of the identity matrix
19200+    (the one corresponding to column of A with smallest square sum)*/
19201+    omss[0]=db_SquareSum6Stride7(A);
19202+    omss[1]=db_SquareSum6Stride7(A+1);
19203+    omss[2]=db_SquareSum6Stride7(A+2);
19204+    omss[3]=db_SquareSum6Stride7(A+3);
19205+    omss[4]=db_SquareSum6Stride7(A+4);
19206+    omss[5]=db_SquareSum6Stride7(A+5);
19207+    omss[6]=db_SquareSum6Stride7(A+6);
19208+    i=db_MinIndex7(omss);
19209+    /*orthogonalize that row against all previous rows
19210+    and normalize it*/
19211+    B=A+i;
19212+    db_MultiplyScalarCopy7(x,A,-B[0]);
19213+    db_RowOperation7(x,A+7 ,B[7]);
19214+    db_RowOperation7(x,A+14,B[14]);
19215+    db_RowOperation7(x,A+21,B[21]);
19216+    db_RowOperation7(x,A+28,B[28]);
19217+    db_RowOperation7(x,A+35,B[35]);
19218+    x[i]+=1.0;
19219+    db_MultiplyScalar7(x,db_SafeSqrtReciprocal(1.0-omss[i]));
19220+}
19221+
19222+void db_NullVectorOrthonormal8x9(double x[9],const double A[72])
19223+{
19224+    int i;
19225+    double omss[9];
19226+    const double *B;
19227+
19228+    /*Pivot by choosing row of the identity matrix
19229+    (the one corresponding to column of A with smallest square sum)*/
19230+    omss[0]=db_SquareSum8Stride9(A);
19231+    omss[1]=db_SquareSum8Stride9(A+1);
19232+    omss[2]=db_SquareSum8Stride9(A+2);
19233+    omss[3]=db_SquareSum8Stride9(A+3);
19234+    omss[4]=db_SquareSum8Stride9(A+4);
19235+    omss[5]=db_SquareSum8Stride9(A+5);
19236+    omss[6]=db_SquareSum8Stride9(A+6);
19237+    omss[7]=db_SquareSum8Stride9(A+7);
19238+    omss[8]=db_SquareSum8Stride9(A+8);
19239+    i=db_MinIndex9(omss);
19240+    /*orthogonalize that row against all previous rows
19241+    and normalize it*/
19242+    B=A+i;
19243+    db_MultiplyScalarCopy9(x,A,-B[0]);
19244+    db_RowOperation9(x,A+9 ,B[9]);
19245+    db_RowOperation9(x,A+18,B[18]);
19246+    db_RowOperation9(x,A+27,B[27]);
19247+    db_RowOperation9(x,A+36,B[36]);
19248+    db_RowOperation9(x,A+45,B[45]);
19249+    db_RowOperation9(x,A+54,B[54]);
19250+    db_RowOperation9(x,A+63,B[63]);
19251+    x[i]+=1.0;
19252+    db_MultiplyScalar9(x,db_SafeSqrtReciprocal(1.0-omss[i]));
19253+}
19254+
19255diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h
19256new file mode 100644
19257index 00000000..1f63d4e5
19258--- /dev/null
19259+++ b/benchmark/feature_stab/db_vlvm/db_utilities_linalg.h
19260@@ -0,0 +1,802 @@
19261+/*
19262+ * Copyright (C) 2011 The Android Open Source Project
19263+ *
19264+ * Licensed under the Apache License, Version 2.0 (the "License");
19265+ * you may not use this file except in compliance with the License.
19266+ * You may obtain a copy of the License at
19267+ *
19268+ *      http://www.apache.org/licenses/LICENSE-2.0
19269+ *
19270+ * Unless required by applicable law or agreed to in writing, software
19271+ * distributed under the License is distributed on an "AS IS" BASIS,
19272+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19273+ * See the License for the specific language governing permissions and
19274+ * limitations under the License.
19275+ */
19276+
19277+/* $Id: db_utilities_linalg.h,v 1.5 2011/06/17 14:03:31 mbansal Exp $ */
19278+
19279+#ifndef DB_UTILITIES_LINALG
19280+#define DB_UTILITIES_LINALG
19281+
19282+#include "db_utilities.h"
19283+
19284+
19285+
19286+/*****************************************************************
19287+*    Lean and mean begins here                                   *
19288+*****************************************************************/
19289+/*!
19290+ * \defgroup LMLinAlg (LM) Linear Algebra Utilities (QR factorization, orthogonal basis, etc.)
19291+ */
19292+
19293+/*!
19294+ \ingroup LMBasicUtilities
19295+ */
19296+inline void db_MultiplyScalar6(double A[6],double mult)
19297+{
19298+    (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult;
19299+    (*A++) *= mult;
19300+}
19301+/*!
19302+ \ingroup LMBasicUtilities
19303+ */
19304+inline void db_MultiplyScalar7(double A[7],double mult)
19305+{
19306+    (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult;
19307+    (*A++) *= mult; (*A++) *= mult;
19308+}
19309+/*!
19310+ \ingroup LMBasicUtilities
19311+ */
19312+inline void db_MultiplyScalar9(double A[9],double mult)
19313+{
19314+    (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult;
19315+    (*A++) *= mult; (*A++) *= mult; (*A++) *= mult; (*A++) *= mult;
19316+}
19317+
19318+/*!
19319+ \ingroup LMBasicUtilities
19320+ */
19321+inline double db_SquareSum6Stride7(const double *x)
19322+{
19323+    return(db_sqr(x[0])+db_sqr(x[7])+db_sqr(x[14])+
19324+        db_sqr(x[21])+db_sqr(x[28])+db_sqr(x[35]));
19325+}
19326+
19327+/*!
19328+ \ingroup LMBasicUtilities
19329+ */
19330+inline double db_SquareSum8Stride9(const double *x)
19331+{
19332+    return(db_sqr(x[0])+db_sqr(x[9])+db_sqr(x[18])+
19333+        db_sqr(x[27])+db_sqr(x[36])+db_sqr(x[45])+
19334+        db_sqr(x[54])+db_sqr(x[63]));
19335+}
19336+
19337+/*!
19338+ \ingroup LMLinAlg
19339+ Cholesky-factorize symmetric positive definite 6 x 6 matrix A. Upper
19340+part of A is used from the input. The Cholesky factor is output as
19341+subdiagonal part in A and diagonal in d, which is 6-dimensional
19342+1.9 microseconds on 450MHz*/
19343+DB_API void db_CholeskyDecomp6x6(double A[36],double d[6]);
19344+
19345+/*!
19346+ \ingroup LMLinAlg
19347+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
19348+of a 6 x 6 matrix and the right hand side b. The vector b is unchanged
19349+1.3 microseconds on 450MHz*/
19350+DB_API void db_CholeskyBacksub6x6(double x[6],const double A[36],const double d[6],const double b[6]);
19351+
19352+/*!
19353+ \ingroup LMLinAlg
19354+ Cholesky-factorize symmetric positive definite n x n matrix A.Part
19355+above diagonal of A is used from the input, diagonal of A is assumed to
19356+be stored in d. The Cholesky factor is output as
19357+subdiagonal part in A and diagonal in d, which is n-dimensional*/
19358+DB_API void db_CholeskyDecompSeparateDiagonal(double **A,double *d,int n);
19359+
19360+/*!
19361+ \ingroup LMLinAlg
19362+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
19363+of an n x n matrix and the right hand side b. The vector b is unchanged*/
19364+DB_API void db_CholeskyBacksub(double *x,const double * const *A,const double *d,int n,const double *b);
19365+
19366+/*!
19367+ \ingroup LMLinAlg
19368+ Cholesky-factorize symmetric positive definite 3 x 3 matrix A. Part
19369+above diagonal of A is used from the input, diagonal of A is assumed to
19370+be stored in d. The Cholesky factor is output as subdiagonal part in A
19371+and diagonal in d, which is 3-dimensional*/
19372+DB_API void db_CholeskyDecomp3x3SeparateDiagonal(double A[9],double d[3]);
19373+
19374+/*!
19375+ \ingroup LMLinAlg
19376+ Backsubstitute L%transpose(L)*x=b for x given the Cholesky decomposition
19377+of a 3 x 3 matrix and the right hand side b. The vector b is unchanged*/
19378+DB_API void db_CholeskyBacksub3x3(double x[3],const double A[9],const double d[3],const double b[3]);
19379+
19380+/*!
19381+ \ingroup LMLinAlg
19382+ perform A-=B*mult*/
19383+inline void db_RowOperation3(double A[3],const double B[3],double mult)
19384+{
19385+    *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++);
19386+}
19387+
19388+/*!
19389+ \ingroup LMLinAlg
19390+ */
19391+inline void db_RowOperation7(double A[7],const double B[7],double mult)
19392+{
19393+    *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++);
19394+    *A++ -= mult*(*B++); *A++ -= mult*(*B++);
19395+}
19396+
19397+/*!
19398+ \ingroup LMLinAlg
19399+ */
19400+inline void db_RowOperation9(double A[9],const double B[9],double mult)
19401+{
19402+    *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++);
19403+    *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++); *A++ -= mult*(*B++);
19404+}
19405+
19406+/*!
19407+ \ingroup LMBasicUtilities
19408+ Swap values of A[7] and B[7]
19409+ */
19410+inline void db_Swap7(double A[7],double B[7])
19411+{
19412+    double temp;
19413+    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;
19414+    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;
19415+    temp= *A; *A++ = *B; *B++ =temp;
19416+}
19417+
19418+/*!
19419+ \ingroup LMBasicUtilities
19420+ Swap values of A[9] and B[9]
19421+ */
19422+inline void db_Swap9(double A[9],double B[9])
19423+{
19424+    double temp;
19425+    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;
19426+    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;
19427+    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;    temp= *A; *A++ = *B; *B++ =temp;
19428+}
19429+
19430+
19431+/*!
19432+ \ingroup LMLinAlg
19433+ */
19434+DB_API void db_Orthogonalize6x7(double A[42],int orthonormalize=0);
19435+
19436+/*!
19437+ \ingroup LMLinAlg
19438+ */
19439+DB_API void db_Orthogonalize8x9(double A[72],int orthonormalize=0);
19440+
19441+/*!
19442+ \ingroup LMLinAlg
19443+ */
19444+inline double db_OrthogonalizePair7(double *x,const double *v,double ssv)
19445+{
19446+    double m,sp,sp_m;
19447+
19448+    m=db_SafeReciprocal(ssv);
19449+    sp=db_ScalarProduct7(x,v);
19450+    sp_m=sp*m;
19451+    db_RowOperation7(x,v,sp_m);
19452+    return(sp*sp_m);
19453+}
19454+
19455+/*!
19456+ \ingroup LMLinAlg
19457+ */
19458+inline double db_OrthogonalizePair9(double *x,const double *v,double ssv)
19459+{
19460+    double m,sp,sp_m;
19461+
19462+    m=db_SafeReciprocal(ssv);
19463+    sp=db_ScalarProduct9(x,v);
19464+    sp_m=sp*m;
19465+    db_RowOperation9(x,v,sp_m);
19466+    return(sp*sp_m);
19467+}
19468+
19469+/*!
19470+ \ingroup LMLinAlg
19471+ */
19472+inline void db_OrthogonalizationSwap7(double *A,int i,double *ss)
19473+{
19474+    double temp;
19475+
19476+    db_Swap7(A,A+7*i);
19477+    temp=ss[0]; ss[0]=ss[i]; ss[i]=temp;
19478+}
19479+/*!
19480+ \ingroup LMLinAlg
19481+ */
19482+inline void db_OrthogonalizationSwap9(double *A,int i,double *ss)
19483+{
19484+    double temp;
19485+
19486+    db_Swap9(A,A+9*i);
19487+    temp=ss[0]; ss[0]=ss[i]; ss[i]=temp;
19488+}
19489+
19490+/*!
19491+ \ingroup LMLinAlg
19492+ */
19493+DB_API void db_NullVectorOrthonormal6x7(double x[7],const double A[42]);
19494+/*!
19495+ \ingroup LMLinAlg
19496+ */
19497+DB_API void db_NullVectorOrthonormal8x9(double x[9],const double A[72]);
19498+
19499+/*!
19500+ \ingroup LMLinAlg
19501+ */
19502+inline void db_NullVector6x7Destructive(double x[7],double A[42])
19503+{
19504+    db_Orthogonalize6x7(A,1);
19505+    db_NullVectorOrthonormal6x7(x,A);
19506+}
19507+
19508+/*!
19509+ \ingroup LMLinAlg
19510+ */
19511+inline void db_NullVector8x9Destructive(double x[9],double A[72])
19512+{
19513+    db_Orthogonalize8x9(A,1);
19514+    db_NullVectorOrthonormal8x9(x,A);
19515+}
19516+
19517+inline int db_ScalarProduct512_s(const short *f,const short *g)
19518+{
19519+#ifndef DB_USE_MMX
19520+    int back;
19521+    back=0;
19522+    for(int i=1; i<=512; i++)
19523+        back+=(*f++)*(*g++);
19524+
19525+    return(back);
19526+#endif
19527+}
19528+
19529+
19530+inline int db_ScalarProduct32_s(const short *f,const short *g)
19531+{
19532+#ifndef DB_USE_MMX
19533+    int back;
19534+    back=0;
19535+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19536+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19537+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19538+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19539+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19540+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19541+    back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19542+
19543+    return(back);
19544+#endif
19545+}
19546+
19547+/*!
19548+ \ingroup LMLinAlg
19549+ Scalar product of 128-vectors (short)
19550+  Compile-time control: MMX, SSE2 or standard C
19551+ */
19552+inline int db_ScalarProduct128_s(const short *f,const short *g)
19553+{
19554+#ifndef DB_USE_MMX
19555+    int back;
19556+    back=0;
19557+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19558+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19559+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19560+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19561+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19562+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19563+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19564+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19565+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19566+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19567+
19568+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19569+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19570+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19571+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19572+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19573+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19574+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19575+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19576+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19577+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19578+
19579+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19580+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19581+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19582+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19583+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19584+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19585+
19586+    return(back);
19587+#else
19588+#ifdef DB_USE_SSE2
19589+    int back;
19590+
19591+    _asm
19592+    {
19593+        mov eax,f
19594+        mov ecx,g
19595+        /*First iteration************************************/
19596+        movdqa     xmm0,[eax]
19597+         pxor    xmm7,xmm7      /*Set xmm7 to zero*/
19598+        pmaddwd  xmm0,[ecx]
19599+         /*Stall*/
19600+        /*Standard iteration************************************/
19601+        movdqa     xmm2,[eax+16]
19602+         paddd   xmm7,xmm0
19603+        pmaddwd  xmm2,[ecx+16]
19604+         /*Stall*/
19605+        movdqa     xmm1,[eax+32]
19606+         paddd   xmm7,xmm2
19607+        pmaddwd  xmm1,[ecx+32]
19608+         /*Stall*/
19609+        /*Standard iteration************************************/
19610+        movdqa     xmm0,[eax+48]
19611+         paddd   xmm7,xmm1
19612+        pmaddwd  xmm0,[ecx+48]
19613+         /*Stall*/
19614+        /*Standard iteration************************************/
19615+        movdqa     xmm2,[eax+64]
19616+         paddd   xmm7,xmm0
19617+        pmaddwd  xmm2,[ecx+64]
19618+         /*Stall*/
19619+        movdqa     xmm1,[eax+80]
19620+         paddd   xmm7,xmm2
19621+        pmaddwd  xmm1,[ecx+80]
19622+         /*Stall*/
19623+        /*Standard iteration************************************/
19624+        movdqa     xmm0,[eax+96]
19625+         paddd   xmm7,xmm1
19626+        pmaddwd  xmm0,[ecx+96]
19627+         /*Stall*/
19628+        /*Standard iteration************************************/
19629+        movdqa     xmm2,[eax+112]
19630+         paddd   xmm7,xmm0
19631+        pmaddwd  xmm2,[ecx+112]
19632+         /*Stall*/
19633+        movdqa     xmm1,[eax+128]
19634+         paddd   xmm7,xmm2
19635+        pmaddwd  xmm1,[ecx+128]
19636+         /*Stall*/
19637+        /*Standard iteration************************************/
19638+        movdqa     xmm0,[eax+144]
19639+         paddd   xmm7,xmm1
19640+        pmaddwd  xmm0,[ecx+144]
19641+         /*Stall*/
19642+        /*Standard iteration************************************/
19643+        movdqa     xmm2,[eax+160]
19644+         paddd   xmm7,xmm0
19645+        pmaddwd  xmm2,[ecx+160]
19646+         /*Stall*/
19647+        movdqa     xmm1,[eax+176]
19648+         paddd   xmm7,xmm2
19649+        pmaddwd  xmm1,[ecx+176]
19650+         /*Stall*/
19651+        /*Standard iteration************************************/
19652+        movdqa     xmm0,[eax+192]
19653+         paddd   xmm7,xmm1
19654+        pmaddwd  xmm0,[ecx+192]
19655+         /*Stall*/
19656+        /*Standard iteration************************************/
19657+        movdqa     xmm2,[eax+208]
19658+         paddd   xmm7,xmm0
19659+        pmaddwd  xmm2,[ecx+208]
19660+         /*Stall*/
19661+        movdqa     xmm1,[eax+224]
19662+         paddd   xmm7,xmm2
19663+        pmaddwd  xmm1,[ecx+224]
19664+         /*Stall*/
19665+        /*Standard iteration************************************/
19666+        movdqa     xmm0,[eax+240]
19667+         paddd   xmm7,xmm1
19668+        pmaddwd  xmm0,[ecx+240]
19669+         /*Stall*/
19670+        /*Rest iteration************************************/
19671+        paddd    xmm7,xmm0
19672+
19673+        /* add up the sum squares */
19674+        movhlps     xmm0,xmm7   /* high half to low half */
19675+        paddd       xmm7,xmm0   /* add high to low */
19676+        pshuflw     xmm0,xmm7, 0xE /* reshuffle */
19677+        paddd       xmm7,xmm0   /* add remaining */
19678+        movd        back,xmm7
19679+
19680+        emms
19681+    }
19682+
19683+    return(back);
19684+#else
19685+    int back;
19686+
19687+    _asm
19688+    {
19689+        mov eax,f
19690+        mov ecx,g
19691+        /*First iteration************************************/
19692+        movq     mm0,[eax]
19693+         pxor    mm7,mm7      /*Set mm7 to zero*/
19694+        pmaddwd  mm0,[ecx]
19695+         /*Stall*/
19696+        movq     mm1,[eax+8]
19697+         /*Stall*/
19698+        pmaddwd  mm1,[ecx+8]
19699+         /*Stall*/
19700+        /*Standard iteration************************************/
19701+        movq     mm2,[eax+16]
19702+         paddd   mm7,mm0
19703+        pmaddwd  mm2,[ecx+16]
19704+         /*Stall*/
19705+        movq     mm0,[eax+24]
19706+         paddd   mm7,mm1
19707+        pmaddwd  mm0,[ecx+24]
19708+         /*Stall*/
19709+        movq     mm1,[eax+32]
19710+         paddd   mm7,mm2
19711+        pmaddwd  mm1,[ecx+32]
19712+         /*Stall*/
19713+        /*Standard iteration************************************/
19714+        movq     mm2,[eax+40]
19715+         paddd   mm7,mm0
19716+        pmaddwd  mm2,[ecx+40]
19717+         /*Stall*/
19718+        movq     mm0,[eax+48]
19719+         paddd   mm7,mm1
19720+        pmaddwd  mm0,[ecx+48]
19721+         /*Stall*/
19722+        movq     mm1,[eax+56]
19723+         paddd   mm7,mm2
19724+        pmaddwd  mm1,[ecx+56]
19725+         /*Stall*/
19726+        /*Standard iteration************************************/
19727+        movq     mm2,[eax+64]
19728+         paddd   mm7,mm0
19729+        pmaddwd  mm2,[ecx+64]
19730+         /*Stall*/
19731+        movq     mm0,[eax+72]
19732+         paddd   mm7,mm1
19733+        pmaddwd  mm0,[ecx+72]
19734+         /*Stall*/
19735+        movq     mm1,[eax+80]
19736+         paddd   mm7,mm2
19737+        pmaddwd  mm1,[ecx+80]
19738+         /*Stall*/
19739+        /*Standard iteration************************************/
19740+        movq     mm2,[eax+88]
19741+         paddd   mm7,mm0
19742+        pmaddwd  mm2,[ecx+88]
19743+         /*Stall*/
19744+        movq     mm0,[eax+96]
19745+         paddd   mm7,mm1
19746+        pmaddwd  mm0,[ecx+96]
19747+         /*Stall*/
19748+        movq     mm1,[eax+104]
19749+         paddd   mm7,mm2
19750+        pmaddwd  mm1,[ecx+104]
19751+         /*Stall*/
19752+        /*Standard iteration************************************/
19753+        movq     mm2,[eax+112]
19754+         paddd   mm7,mm0
19755+        pmaddwd  mm2,[ecx+112]
19756+         /*Stall*/
19757+        movq     mm0,[eax+120]
19758+         paddd   mm7,mm1
19759+        pmaddwd  mm0,[ecx+120]
19760+         /*Stall*/
19761+        movq     mm1,[eax+128]
19762+         paddd   mm7,mm2
19763+        pmaddwd  mm1,[ecx+128]
19764+         /*Stall*/
19765+        /*Standard iteration************************************/
19766+        movq     mm2,[eax+136]
19767+         paddd   mm7,mm0
19768+        pmaddwd  mm2,[ecx+136]
19769+         /*Stall*/
19770+        movq     mm0,[eax+144]
19771+         paddd   mm7,mm1
19772+        pmaddwd  mm0,[ecx+144]
19773+         /*Stall*/
19774+        movq     mm1,[eax+152]
19775+         paddd   mm7,mm2
19776+        pmaddwd  mm1,[ecx+152]
19777+         /*Stall*/
19778+        /*Standard iteration************************************/
19779+        movq     mm2,[eax+160]
19780+         paddd   mm7,mm0
19781+        pmaddwd  mm2,[ecx+160]
19782+         /*Stall*/
19783+        movq     mm0,[eax+168]
19784+         paddd   mm7,mm1
19785+        pmaddwd  mm0,[ecx+168]
19786+         /*Stall*/
19787+        movq     mm1,[eax+176]
19788+         paddd   mm7,mm2
19789+        pmaddwd  mm1,[ecx+176]
19790+         /*Stall*/
19791+        /*Standard iteration************************************/
19792+        movq     mm2,[eax+184]
19793+         paddd   mm7,mm0
19794+        pmaddwd  mm2,[ecx+184]
19795+         /*Stall*/
19796+        movq     mm0,[eax+192]
19797+         paddd   mm7,mm1
19798+        pmaddwd  mm0,[ecx+192]
19799+         /*Stall*/
19800+        movq     mm1,[eax+200]
19801+         paddd   mm7,mm2
19802+        pmaddwd  mm1,[ecx+200]
19803+         /*Stall*/
19804+        /*Standard iteration************************************/
19805+        movq     mm2,[eax+208]
19806+         paddd   mm7,mm0
19807+        pmaddwd  mm2,[ecx+208]
19808+         /*Stall*/
19809+        movq     mm0,[eax+216]
19810+         paddd   mm7,mm1
19811+        pmaddwd  mm0,[ecx+216]
19812+         /*Stall*/
19813+        movq     mm1,[eax+224]
19814+         paddd   mm7,mm2
19815+        pmaddwd  mm1,[ecx+224]
19816+         /*Stall*/
19817+        /*Standard iteration************************************/
19818+        movq     mm2,[eax+232]
19819+         paddd   mm7,mm0
19820+        pmaddwd  mm2,[ecx+232]
19821+         /*Stall*/
19822+        movq     mm0,[eax+240]
19823+         paddd   mm7,mm1
19824+        pmaddwd  mm0,[ecx+240]
19825+         /*Stall*/
19826+        movq     mm1,[eax+248]
19827+         paddd   mm7,mm2
19828+        pmaddwd  mm1,[ecx+248]
19829+         /*Stall*/
19830+        /*Rest iteration************************************/
19831+        paddd    mm7,mm0
19832+         /*Stall*/
19833+        /*Stall*/
19834+         /*Stall*/
19835+        paddd    mm7,mm1
19836+         /*Stall*/
19837+        movq     mm0,mm7
19838+         psrlq   mm7,32
19839+        paddd    mm0,mm7
19840+         /*Stall*/
19841+        /*Stall*/
19842+         /*Stall*/
19843+        movd     back,mm0
19844+        emms
19845+    }
19846+
19847+    return(back);
19848+#endif
19849+#endif /*DB_USE_MMX*/
19850+}
19851+
19852+/*!
19853+ \ingroup LMLinAlg
19854+ Scalar product of 16 byte aligned 128-vectors (float).
19855+  Compile-time control: SIMD (SSE) or standard C.
19856+ */
19857+inline float db_ScalarProduct128Aligned16_f(const float *f,const float *g)
19858+{
19859+#ifndef DB_USE_SIMD
19860+    float back;
19861+    back=0.0;
19862+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19863+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19864+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19865+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19866+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19867+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19868+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19869+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19870+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19871+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19872+
19873+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19874+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19875+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19876+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19877+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19878+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19879+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19880+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19881+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19882+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19883+
19884+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19885+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19886+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19887+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19888+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19889+    back+=(*f++)*(*g++); back+=(*f++)*(*g++); back+=(*f++)*(*g++);
19890+
19891+    return(back);
19892+#else
19893+    float back;
19894+
19895+    _asm
19896+    {
19897+        mov eax,f
19898+        mov ecx,g
19899+        /*First iteration************************************/
19900+        movaps     xmm0,[eax]
19901+         xorps      xmm7,xmm7       /*Set mm7 to zero*/
19902+        mulps      xmm0,[ecx]
19903+         /*Stall*/
19904+        movaps     xmm1,[eax+16]
19905+         /*Stall*/
19906+        mulps      xmm1,[ecx+16]
19907+         /*Stall*/
19908+        /*Standard iteration************************************/
19909+        movaps     xmm2,[eax+32]
19910+         addps      xmm7,xmm0
19911+        mulps      xmm2,[ecx+32]
19912+         /*Stall*/
19913+        movaps     xmm0,[eax+48]
19914+         addps      xmm7,xmm1
19915+        mulps      xmm0,[ecx+48]
19916+         /*Stall*/
19917+        movaps     xmm1,[eax+64]
19918+         addps      xmm7,xmm2
19919+        mulps      xmm1,[ecx+64]
19920+         /*Stall*/
19921+        /*Standard iteration************************************/
19922+        movaps     xmm2,[eax+80]
19923+         addps      xmm7,xmm0
19924+        mulps      xmm2,[ecx+80]
19925+         /*Stall*/
19926+        movaps     xmm0,[eax+96]
19927+         addps      xmm7,xmm1
19928+        mulps      xmm0,[ecx+96]
19929+         /*Stall*/
19930+        movaps     xmm1,[eax+112]
19931+         addps      xmm7,xmm2
19932+        mulps      xmm1,[ecx+112]
19933+         /*Stall*/
19934+        /*Standard iteration************************************/
19935+        movaps     xmm2,[eax+128]
19936+         addps      xmm7,xmm0
19937+        mulps      xmm2,[ecx+128]
19938+         /*Stall*/
19939+        movaps     xmm0,[eax+144]
19940+         addps      xmm7,xmm1
19941+        mulps      xmm0,[ecx+144]
19942+         /*Stall*/
19943+        movaps     xmm1,[eax+160]
19944+         addps      xmm7,xmm2
19945+        mulps      xmm1,[ecx+160]
19946+         /*Stall*/
19947+        /*Standard iteration************************************/
19948+        movaps     xmm2,[eax+176]
19949+         addps      xmm7,xmm0
19950+        mulps      xmm2,[ecx+176]
19951+         /*Stall*/
19952+        movaps     xmm0,[eax+192]
19953+         addps      xmm7,xmm1
19954+        mulps      xmm0,[ecx+192]
19955+         /*Stall*/
19956+        movaps     xmm1,[eax+208]
19957+         addps      xmm7,xmm2
19958+        mulps      xmm1,[ecx+208]
19959+         /*Stall*/
19960+        /*Standard iteration************************************/
19961+        movaps     xmm2,[eax+224]
19962+         addps      xmm7,xmm0
19963+        mulps      xmm2,[ecx+224]
19964+         /*Stall*/
19965+        movaps     xmm0,[eax+240]
19966+         addps      xmm7,xmm1
19967+        mulps      xmm0,[ecx+240]
19968+         /*Stall*/
19969+        movaps     xmm1,[eax+256]
19970+         addps      xmm7,xmm2
19971+        mulps      xmm1,[ecx+256]
19972+         /*Stall*/
19973+        /*Standard iteration************************************/
19974+        movaps     xmm2,[eax+272]
19975+         addps      xmm7,xmm0
19976+        mulps      xmm2,[ecx+272]
19977+         /*Stall*/
19978+        movaps     xmm0,[eax+288]
19979+         addps      xmm7,xmm1
19980+        mulps      xmm0,[ecx+288]
19981+         /*Stall*/
19982+        movaps     xmm1,[eax+304]
19983+         addps      xmm7,xmm2
19984+        mulps      xmm1,[ecx+304]
19985+         /*Stall*/
19986+        /*Standard iteration************************************/
19987+        movaps     xmm2,[eax+320]
19988+         addps      xmm7,xmm0
19989+        mulps      xmm2,[ecx+320]
19990+         /*Stall*/
19991+        movaps     xmm0,[eax+336]
19992+         addps      xmm7,xmm1
19993+        mulps      xmm0,[ecx+336]
19994+         /*Stall*/
19995+        movaps     xmm1,[eax+352]
19996+         addps      xmm7,xmm2
19997+        mulps      xmm1,[ecx+352]
19998+         /*Stall*/
19999+        /*Standard iteration************************************/
20000+        movaps     xmm2,[eax+368]
20001+         addps      xmm7,xmm0
20002+        mulps      xmm2,[ecx+368]
20003+         /*Stall*/
20004+        movaps     xmm0,[eax+384]
20005+         addps      xmm7,xmm1
20006+        mulps      xmm0,[ecx+384]
20007+         /*Stall*/
20008+        movaps     xmm1,[eax+400]
20009+         addps      xmm7,xmm2
20010+        mulps      xmm1,[ecx+400]
20011+         /*Stall*/
20012+        /*Standard iteration************************************/
20013+        movaps     xmm2,[eax+416]
20014+         addps      xmm7,xmm0
20015+        mulps      xmm2,[ecx+416]
20016+         /*Stall*/
20017+        movaps     xmm0,[eax+432]
20018+         addps      xmm7,xmm1
20019+        mulps      xmm0,[ecx+432]
20020+         /*Stall*/
20021+        movaps     xmm1,[eax+448]
20022+         addps      xmm7,xmm2
20023+        mulps      xmm1,[ecx+448]
20024+         /*Stall*/
20025+        /*Standard iteration************************************/
20026+        movaps     xmm2,[eax+464]
20027+         addps      xmm7,xmm0
20028+        mulps      xmm2,[ecx+464]
20029+         /*Stall*/
20030+        movaps     xmm0,[eax+480]
20031+         addps      xmm7,xmm1
20032+        mulps      xmm0,[ecx+480]
20033+         /*Stall*/
20034+        movaps     xmm1,[eax+496]
20035+         addps      xmm7,xmm2
20036+        mulps      xmm1,[ecx+496]
20037+         /*Stall*/
20038+        /*Rest iteration************************************/
20039+        addps      xmm7,xmm0
20040+         /*Stall*/
20041+        addps      xmm7,xmm1
20042+         /*Stall*/
20043+        movaps xmm6,xmm7
20044+         /*Stall*/
20045+        shufps xmm6,xmm6,4Eh
20046+         /*Stall*/
20047+        addps  xmm7,xmm6
20048+         /*Stall*/
20049+        movaps xmm6,xmm7
20050+         /*Stall*/
20051+        shufps xmm6,xmm6,11h
20052+         /*Stall*/
20053+        addps  xmm7,xmm6
20054+         /*Stall*/
20055+        movss  back,xmm7
20056+    }
20057+
20058+    return(back);
20059+#endif /*DB_USE_SIMD*/
20060+}
20061+
20062+#endif /* DB_UTILITIES_LINALG */
20063diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp b/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp
20064new file mode 100644
20065index 00000000..013ac726
20066--- /dev/null
20067+++ b/benchmark/feature_stab/db_vlvm/db_utilities_poly.cpp
20068@@ -0,0 +1,235 @@
20069+/*
20070+ * Copyright (C) 2011 The Android Open Source Project
20071+ *
20072+ * Licensed under the Apache License, Version 2.0 (the "License");
20073+ * you may not use this file except in compliance with the License.
20074+ * You may obtain a copy of the License at
20075+ *
20076+ *      http://www.apache.org/licenses/LICENSE-2.0
20077+ *
20078+ * Unless required by applicable law or agreed to in writing, software
20079+ * distributed under the License is distributed on an "AS IS" BASIS,
20080+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20081+ * See the License for the specific language governing permissions and
20082+ * limitations under the License.
20083+ */
20084+
20085+/* $Id: db_utilities_poly.cpp,v 1.2 2010/09/03 12:00:10 bsouthall Exp $ */
20086+
20087+#include "db_utilities_poly.h"
20088+#include "db_utilities.h"
20089+
20090+
20091+
20092+/*****************************************************************
20093+*    Lean and mean begins here                                   *
20094+*****************************************************************/
20095+
20096+void db_SolveCubic(double *roots,int *nr_roots,double a,double b,double c,double d)
20097+{
20098+    double bp,bp2,cp,dp,q,r,srq;
20099+    double r2_min_q3,theta,bp_through3,theta_through3;
20100+    double cos_theta_through3,sin_theta_through3,min2_cos_theta_plu,min2_cos_theta_min;
20101+    double si_r_srq,A;
20102+
20103+    /*For nondegenerate cubics with three roots
20104+    [24 mult 9 add 2sqrt 1acos 1cos=33flops 4func]
20105+    For nondegenerate cubics with one root
20106+    [16 mult 6 add 1sqrt 1qbrt=24flops 3func]*/
20107+
20108+    if(a==0.0) db_SolveQuadratic(roots,nr_roots,b,c,d);
20109+    else
20110+    {
20111+        bp=b/a;
20112+        bp2=bp*bp;
20113+        cp=c/a;
20114+        dp=d/a;
20115+
20116+        q=(bp2-3.0*cp)/9.0;
20117+        r=(2.0*bp2*bp-9.0*bp*cp+27.0*dp)/54.0;
20118+        r2_min_q3=r*r-q*q*q;
20119+        if(r2_min_q3<0.0)
20120+        {
20121+            *nr_roots=3;
20122+            /*q has to be > 0*/
20123+            srq=sqrt(q);
20124+            theta=acos(db_maxd(-1.0,db_mind(1.0,r/(q*srq))));
20125+            bp_through3=bp/3.0;
20126+            theta_through3=theta/3.0;
20127+            cos_theta_through3=cos(theta_through3);
20128+            sin_theta_through3=sqrt(db_maxd(0.0,1.0-cos_theta_through3*cos_theta_through3));
20129+
20130+            /*cos(theta_through3+2*pi/3)=cos_theta_through3*cos(2*pi/3)-sin_theta_through3*sin(2*pi/3)
20131+            = -0.5*cos_theta_through3-sqrt(3)/2.0*sin_theta_through3
20132+            = -0.5*(cos_theta_through3+sqrt(3)*sin_theta_through3)*/
20133+            min2_cos_theta_plu=cos_theta_through3+DB_SQRT3*sin_theta_through3;
20134+            min2_cos_theta_min=cos_theta_through3-DB_SQRT3*sin_theta_through3;
20135+
20136+            roots[0]= -2.0*srq*cos_theta_through3-bp_through3;
20137+            roots[1]=srq*min2_cos_theta_plu-bp_through3;
20138+            roots[2]=srq*min2_cos_theta_min-bp_through3;
20139+        }
20140+        else if(r2_min_q3>0.0)
20141+        {
20142+            *nr_roots=1;
20143+            A= -db_sign(r)*db_CubRoot(db_absd(r)+sqrt(r2_min_q3));
20144+            bp_through3=bp/3.0;
20145+            if(A!=0.0) roots[0]=A+q/A-bp_through3;
20146+            else roots[0]= -bp_through3;
20147+        }
20148+        else
20149+        {
20150+            *nr_roots=2;
20151+            bp_through3=bp/3.0;
20152+            /*q has to be >= 0*/
20153+            si_r_srq=db_sign(r)*sqrt(q);
20154+            /*Single root*/
20155+            roots[0]= -2.0*si_r_srq-bp_through3;
20156+            /*Double root*/
20157+            roots[1]=si_r_srq-bp_through3;
20158+        }
20159+    }
20160+}
20161+
20162+void db_SolveQuartic(double *roots,int *nr_roots,double a,double b,double c,double d,double e)
20163+{
20164+    /*Normalized coefficients*/
20165+    double c0,c1,c2,c3;
20166+    /*Temporary coefficients*/
20167+    double c3through2,c3through4,c3c3through4_min_c2,min4_c0;
20168+    double lz,ms,ns,mn,m,n,lz_through2;
20169+    /*Cubic polynomial roots, nr of roots and coefficients*/
20170+    double c_roots[3];
20171+    int nr_c_roots;
20172+    double k0,k1;
20173+    /*nr additional roots from second quadratic*/
20174+    int addroots;
20175+
20176+    /*For nondegenerate quartics
20177+    [16mult 11add 2sqrt 1cubic 2quadratic=74flops 8funcs]*/
20178+
20179+    if(a==0.0) db_SolveCubic(roots,nr_roots,b,c,d,e);
20180+    else if(e==0.0)
20181+    {
20182+        db_SolveCubic(roots,nr_roots,a,b,c,d);
20183+        roots[*nr_roots]=0.0;
20184+        *nr_roots+=1;
20185+    }
20186+    else
20187+    {
20188+        /*Compute normalized coefficients*/
20189+        c3=b/a;
20190+        c2=c/a;
20191+        c1=d/a;
20192+        c0=e/a;
20193+        /*Compute temporary coefficients*/
20194+        c3through2=c3/2.0;
20195+        c3through4=c3/4.0;
20196+        c3c3through4_min_c2=c3*c3through4-c2;
20197+        min4_c0= -4.0*c0;
20198+        /*Compute coefficients of cubic*/
20199+        k0=min4_c0*c3c3through4_min_c2-c1*c1;
20200+        k1=c1*c3+min4_c0;
20201+        /*k2= -c2*/
20202+        /*k3=1.0*/
20203+
20204+        /*Solve it for roots*/
20205+        db_SolveCubic(c_roots,&nr_c_roots,1.0,-c2,k1,k0);
20206+
20207+        if(nr_c_roots>0)
20208+        {
20209+            lz=c_roots[0];
20210+            lz_through2=lz/2.0;
20211+            ms=lz+c3c3through4_min_c2;
20212+            ns=lz_through2*lz_through2-c0;
20213+            mn=lz*c3through4-c1/2.0;
20214+
20215+            if((ms>=0.0)&&(ns>=0.0))
20216+            {
20217+                m=sqrt(ms);
20218+                n=sqrt(ns)*db_sign(mn);
20219+
20220+                db_SolveQuadratic(roots,nr_roots,
20221+                    1.0,c3through2+m,lz_through2+n);
20222+
20223+                db_SolveQuadratic(&roots[*nr_roots],&addroots,
20224+                    1.0,c3through2-m,lz_through2-n);
20225+
20226+                *nr_roots+=addroots;
20227+            }
20228+            else *nr_roots=0;
20229+        }
20230+        else *nr_roots=0;
20231+    }
20232+}
20233+
20234+void db_SolveQuarticForced(double *roots,int *nr_roots,double a,double b,double c,double d,double e)
20235+{
20236+    /*Normalized coefficients*/
20237+    double c0,c1,c2,c3;
20238+    /*Temporary coefficients*/
20239+    double c3through2,c3through4,c3c3through4_min_c2,min4_c0;
20240+    double lz,ms,ns,mn,m,n,lz_through2;
20241+    /*Cubic polynomial roots, nr of roots and coefficients*/
20242+    double c_roots[3];
20243+    int nr_c_roots;
20244+    double k0,k1;
20245+    /*nr additional roots from second quadratic*/
20246+    int addroots;
20247+
20248+    /*For nondegenerate quartics
20249+    [16mult 11add 2sqrt 1cubic 2quadratic=74flops 8funcs]*/
20250+
20251+    if(a==0.0) db_SolveCubic(roots,nr_roots,b,c,d,e);
20252+    else if(e==0.0)
20253+    {
20254+        db_SolveCubic(roots,nr_roots,a,b,c,d);
20255+        roots[*nr_roots]=0.0;
20256+        *nr_roots+=1;
20257+    }
20258+    else
20259+    {
20260+        /*Compute normalized coefficients*/
20261+        c3=b/a;
20262+        c2=c/a;
20263+        c1=d/a;
20264+        c0=e/a;
20265+        /*Compute temporary coefficients*/
20266+        c3through2=c3/2.0;
20267+        c3through4=c3/4.0;
20268+        c3c3through4_min_c2=c3*c3through4-c2;
20269+        min4_c0= -4.0*c0;
20270+        /*Compute coefficients of cubic*/
20271+        k0=min4_c0*c3c3through4_min_c2-c1*c1;
20272+        k1=c1*c3+min4_c0;
20273+        /*k2= -c2*/
20274+        /*k3=1.0*/
20275+
20276+        /*Solve it for roots*/
20277+        db_SolveCubic(c_roots,&nr_c_roots,1.0,-c2,k1,k0);
20278+
20279+        if(nr_c_roots>0)
20280+        {
20281+            lz=c_roots[0];
20282+            lz_through2=lz/2.0;
20283+            ms=lz+c3c3through4_min_c2;
20284+            ns=lz_through2*lz_through2-c0;
20285+            mn=lz*c3through4-c1/2.0;
20286+
20287+            if(ms<0.0) ms=0.0;
20288+            if(ns<0.0) ns=0.0;
20289+
20290+            m=sqrt(ms);
20291+            n=sqrt(ns)*db_sign(mn);
20292+
20293+            db_SolveQuadratic(roots,nr_roots,
20294+                1.0,c3through2+m,lz_through2+n);
20295+
20296+            db_SolveQuadratic(&roots[*nr_roots],&addroots,
20297+                1.0,c3through2-m,lz_through2-n);
20298+
20299+            *nr_roots+=addroots;
20300+        }
20301+        else *nr_roots=0;
20302+    }
20303+}
20304diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_poly.h b/benchmark/feature_stab/db_vlvm/db_utilities_poly.h
20305new file mode 100644
20306index 00000000..1f878907
20307--- /dev/null
20308+++ b/benchmark/feature_stab/db_vlvm/db_utilities_poly.h
20309@@ -0,0 +1,383 @@
20310+/*
20311+ * Copyright (C) 2011 The Android Open Source Project
20312+ *
20313+ * Licensed under the Apache License, Version 2.0 (the "License");
20314+ * you may not use this file except in compliance with the License.
20315+ * You may obtain a copy of the License at
20316+ *
20317+ *      http://www.apache.org/licenses/LICENSE-2.0
20318+ *
20319+ * Unless required by applicable law or agreed to in writing, software
20320+ * distributed under the License is distributed on an "AS IS" BASIS,
20321+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20322+ * See the License for the specific language governing permissions and
20323+ * limitations under the License.
20324+ */
20325+
20326+/* $Id: db_utilities_poly.h,v 1.2 2010/09/03 12:00:11 bsouthall Exp $ */
20327+
20328+#ifndef DB_UTILITIES_POLY
20329+#define DB_UTILITIES_POLY
20330+
20331+#include "db_utilities.h"
20332+
20333+
20334+
20335+/*****************************************************************
20336+*    Lean and mean begins here                                   *
20337+*****************************************************************/
20338+/*!
20339+ * \defgroup LMPolynomial (LM) Polynomial utilities (solvers, arithmetic, evaluation, etc.)
20340+ */
20341+/*\{*/
20342+
20343+/*!
20344+In debug mode closed form quadratic solving takes on the order of 15 microseconds
20345+while eig of the companion matrix takes about 1.1 milliseconds
20346+Speed-optimized code in release mode solves a quadratic in 0.3 microseconds on 450MHz
20347+*/
20348+inline void db_SolveQuadratic(double *roots,int *nr_roots,double a,double b,double c)
20349+{
20350+    double rs,srs,q;
20351+
20352+    /*For non-degenerate quadratics
20353+    [5 mult 2 add 1 sqrt=7flops 1func]*/
20354+    if(a==0.0)
20355+    {
20356+        if(b==0.0) *nr_roots=0;
20357+        else
20358+        {
20359+            roots[0]= -c/b;
20360+            *nr_roots=1;
20361+        }
20362+    }
20363+    else
20364+    {
20365+        rs=b*b-4.0*a*c;
20366+        if(rs>=0.0)
20367+        {
20368+            *nr_roots=2;
20369+            srs=sqrt(rs);
20370+            q= -0.5*(b+db_sign(b)*srs);
20371+            roots[0]=q/a;
20372+            /*If b is zero db_sign(b) returns 1,
20373+            so q is only zero when b=0 and c=0*/
20374+            if(q==0.0) *nr_roots=1;
20375+            else roots[1]=c/q;
20376+        }
20377+        else *nr_roots=0;
20378+    }
20379+}
20380+
20381+/*!
20382+In debug mode closed form cubic solving takes on the order of 45 microseconds
20383+while eig of the companion matrix takes about 1.3 milliseconds
20384+Speed-optimized code in release mode solves a cubic in 1.5 microseconds on 450MHz
20385+For a non-degenerate cubic with two roots, the first root is the single root and
20386+the second root is the double root
20387+*/
20388+DB_API void db_SolveCubic(double *roots,int *nr_roots,double a,double b,double c,double d);
20389+/*!
20390+In debug mode closed form quartic solving takes on the order of 0.1 milliseconds
20391+while eig of the companion matrix takes about 1.5 milliseconds
20392+Speed-optimized code in release mode solves a quartic in 2.6 microseconds on 450MHz*/
20393+DB_API void db_SolveQuartic(double *roots,int *nr_roots,double a,double b,double c,double d,double e);
20394+/*!
20395+Quartic solving where a solution is forced when splitting into quadratics, which
20396+can be good if the quartic is sometimes in fact a quadratic, such as in absolute orientation
20397+when the data is planar*/
20398+DB_API void db_SolveQuarticForced(double *roots,int *nr_roots,double a,double b,double c,double d,double e);
20399+
20400+inline double db_PolyEval1(const double p[2],double x)
20401+{
20402+    return(p[0]+x*p[1]);
20403+}
20404+
20405+inline void db_MultiplyPoly1_1(double *d,const double *a,const double *b)
20406+{
20407+    double a0,a1;
20408+    double b0,b1;
20409+    a0=a[0];a1=a[1];
20410+    b0=b[0];b1=b[1];
20411+
20412+    d[0]=a0*b0;
20413+    d[1]=a0*b1+a1*b0;
20414+    d[2]=      a1*b1;
20415+}
20416+
20417+inline void db_MultiplyPoly0_2(double *d,const double *a,const double *b)
20418+{
20419+    double a0;
20420+    double b0,b1,b2;
20421+    a0=a[0];
20422+    b0=b[0];b1=b[1];b2=b[2];
20423+
20424+    d[0]=a0*b0;
20425+    d[1]=a0*b1;
20426+    d[2]=a0*b2;
20427+}
20428+
20429+inline void db_MultiplyPoly1_2(double *d,const double *a,const double *b)
20430+{
20431+    double a0,a1;
20432+    double b0,b1,b2;
20433+    a0=a[0];a1=a[1];
20434+    b0=b[0];b1=b[1];b2=b[2];
20435+
20436+    d[0]=a0*b0;
20437+    d[1]=a0*b1+a1*b0;
20438+    d[2]=a0*b2+a1*b1;
20439+    d[3]=      a1*b2;
20440+}
20441+
20442+
20443+inline void db_MultiplyPoly1_3(double *d,const double *a,const double *b)
20444+{
20445+    double a0,a1;
20446+    double b0,b1,b2,b3;
20447+    a0=a[0];a1=a[1];
20448+    b0=b[0];b1=b[1];b2=b[2];b3=b[3];
20449+
20450+    d[0]=a0*b0;
20451+    d[1]=a0*b1+a1*b0;
20452+    d[2]=a0*b2+a1*b1;
20453+    d[3]=a0*b3+a1*b2;
20454+    d[4]=      a1*b3;
20455+}
20456+/*!
20457+Multiply d=a*b where a is one degree and b is two degree*/
20458+inline void db_AddPolyProduct0_1(double *d,const double *a,const double *b)
20459+{
20460+    double a0;
20461+    double b0,b1;
20462+    a0=a[0];
20463+    b0=b[0];b1=b[1];
20464+
20465+    d[0]+=a0*b0;
20466+    d[1]+=a0*b1;
20467+}
20468+inline void db_AddPolyProduct0_2(double *d,const double *a,const double *b)
20469+{
20470+    double a0;
20471+    double b0,b1,b2;
20472+    a0=a[0];
20473+    b0=b[0];b1=b[1];b2=b[2];
20474+
20475+    d[0]+=a0*b0;
20476+    d[1]+=a0*b1;
20477+    d[2]+=a0*b2;
20478+}
20479+/*!
20480+Multiply d=a*b where a is one degree and b is two degree*/
20481+inline void db_SubtractPolyProduct0_0(double *d,const double *a,const double *b)
20482+{
20483+    double a0;
20484+    double b0;
20485+    a0=a[0];
20486+    b0=b[0];
20487+
20488+    d[0]-=a0*b0;
20489+}
20490+
20491+inline void db_SubtractPolyProduct0_1(double *d,const double *a,const double *b)
20492+{
20493+    double a0;
20494+    double b0,b1;
20495+    a0=a[0];
20496+    b0=b[0];b1=b[1];
20497+
20498+    d[0]-=a0*b0;
20499+    d[1]-=a0*b1;
20500+}
20501+
20502+inline void db_SubtractPolyProduct0_2(double *d,const double *a,const double *b)
20503+{
20504+    double a0;
20505+    double b0,b1,b2;
20506+    a0=a[0];
20507+    b0=b[0];b1=b[1];b2=b[2];
20508+
20509+    d[0]-=a0*b0;
20510+    d[1]-=a0*b1;
20511+    d[2]-=a0*b2;
20512+}
20513+
20514+inline void db_SubtractPolyProduct1_3(double *d,const double *a,const double *b)
20515+{
20516+    double a0,a1;
20517+    double b0,b1,b2,b3;
20518+    a0=a[0];a1=a[1];
20519+    b0=b[0];b1=b[1];b2=b[2];b3=b[3];
20520+
20521+    d[0]-=a0*b0;
20522+    d[1]-=a0*b1+a1*b0;
20523+    d[2]-=a0*b2+a1*b1;
20524+    d[3]-=a0*b3+a1*b2;
20525+    d[4]-=      a1*b3;
20526+}
20527+
20528+inline void    db_CharacteristicPolynomial4x4(double p[5],const double A[16])
20529+{
20530+    /*All two by two determinants of the first two rows*/
20531+    double two01[3],two02[3],two03[3],two12[3],two13[3],two23[3];
20532+    /*Polynomials representing third and fourth row of A*/
20533+    double P0[2],P1[2],P2[2],P3[2];
20534+    double P4[2],P5[2],P6[2],P7[2];
20535+    /*All three by three determinants of the first three rows*/
20536+    double neg_three0[4],neg_three1[4],three2[4],three3[4];
20537+
20538+    /*Compute 2x2 determinants*/
20539+    two01[0]=A[0]*A[5]-A[1]*A[4];
20540+    two01[1]= -(A[0]+A[5]);
20541+    two01[2]=1.0;
20542+
20543+    two02[0]=A[0]*A[6]-A[2]*A[4];
20544+    two02[1]= -A[6];
20545+
20546+    two03[0]=A[0]*A[7]-A[3]*A[4];
20547+    two03[1]= -A[7];
20548+
20549+    two12[0]=A[1]*A[6]-A[2]*A[5];
20550+    two12[1]=A[2];
20551+
20552+    two13[0]=A[1]*A[7]-A[3]*A[5];
20553+    two13[1]=A[3];
20554+
20555+    two23[0]=A[2]*A[7]-A[3]*A[6];
20556+
20557+    P0[0]=A[8];
20558+    P1[0]=A[9];
20559+    P2[0]=A[10];P2[1]= -1.0;
20560+    P3[0]=A[11];
20561+
20562+    P4[0]=A[12];
20563+    P5[0]=A[13];
20564+    P6[0]=A[14];
20565+    P7[0]=A[15];P7[1]= -1.0;
20566+
20567+    /*Compute 3x3 determinants.Note that the highest
20568+    degree polynomial goes first and the smaller ones
20569+    are added or subtracted from it*/
20570+    db_MultiplyPoly1_1(       neg_three0,P2,two13);
20571+    db_SubtractPolyProduct0_0(neg_three0,P1,two23);
20572+    db_SubtractPolyProduct0_1(neg_three0,P3,two12);
20573+
20574+    db_MultiplyPoly1_1(       neg_three1,P2,two03);
20575+    db_SubtractPolyProduct0_1(neg_three1,P3,two02);
20576+    db_SubtractPolyProduct0_0(neg_three1,P0,two23);
20577+
20578+    db_MultiplyPoly0_2(       three2,P3,two01);
20579+    db_AddPolyProduct0_1(     three2,P0,two13);
20580+    db_SubtractPolyProduct0_1(three2,P1,two03);
20581+
20582+    db_MultiplyPoly1_2(       three3,P2,two01);
20583+    db_AddPolyProduct0_1(     three3,P0,two12);
20584+    db_SubtractPolyProduct0_1(three3,P1,two02);
20585+
20586+    /*Compute 4x4 determinants*/
20587+    db_MultiplyPoly1_3(       p,P7,three3);
20588+    db_AddPolyProduct0_2(     p,P4,neg_three0);
20589+    db_SubtractPolyProduct0_2(p,P5,neg_three1);
20590+    db_SubtractPolyProduct0_2(p,P6,three2);
20591+}
20592+
20593+inline void db_RealEigenvalues4x4(double lambda[4],int *nr_roots,const double A[16],int forced=0)
20594+{
20595+    double p[5];
20596+
20597+    db_CharacteristicPolynomial4x4(p,A);
20598+    if(forced) db_SolveQuarticForced(lambda,nr_roots,p[4],p[3],p[2],p[1],p[0]);
20599+     else db_SolveQuartic(lambda,nr_roots,p[4],p[3],p[2],p[1],p[0]);
20600+}
20601+
20602+/*!
20603+Compute the unit norm eigenvector v of the matrix A corresponding
20604+to the eigenvalue lambda
20605+[96mult 60add 1sqrt=156flops 1sqrt]*/
20606+inline void db_EigenVector4x4(double v[4],double lambda,const double A[16])
20607+{
20608+    double a0,a5,a10,a15;
20609+    double d01,d02,d03,d12,d13,d23;
20610+    double e01,e02,e03,e12,e13,e23;
20611+    double C[16],n0,n1,n2,n3,m;
20612+
20613+    /*Compute diagonal
20614+    [4add=4flops]*/
20615+    a0=A[0]-lambda;
20616+    a5=A[5]-lambda;
20617+    a10=A[10]-lambda;
20618+    a15=A[15]-lambda;
20619+
20620+    /*Compute 2x2 determinants of rows 1,2 and 3,4
20621+    [24mult 12add=36flops]*/
20622+    d01=a0*a5    -A[1]*A[4];
20623+    d02=a0*A[6]  -A[2]*A[4];
20624+    d03=a0*A[7]  -A[3]*A[4];
20625+    d12=A[1]*A[6]-A[2]*a5;
20626+    d13=A[1]*A[7]-A[3]*a5;
20627+    d23=A[2]*A[7]-A[3]*A[6];
20628+
20629+    e01=A[8]*A[13]-A[9] *A[12];
20630+    e02=A[8]*A[14]-a10  *A[12];
20631+    e03=A[8]*a15  -A[11]*A[12];
20632+    e12=A[9]*A[14]-a10  *A[13];
20633+    e13=A[9]*a15  -A[11]*A[13];
20634+    e23=a10 *a15  -A[11]*A[14];
20635+
20636+    /*Compute matrix of cofactors
20637+    [48mult 32 add=80flops*/
20638+    C[0]=  (a5  *e23-A[6]*e13+A[7]*e12);
20639+    C[1]= -(A[4]*e23-A[6]*e03+A[7]*e02);
20640+    C[2]=  (A[4]*e13-a5  *e03+A[7]*e01);
20641+    C[3]= -(A[4]*e12-a5  *e02+A[6]*e01);
20642+
20643+    C[4]= -(A[1]*e23-A[2]*e13+A[3]*e12);
20644+    C[5]=  (a0  *e23-A[2]*e03+A[3]*e02);
20645+    C[6]= -(a0  *e13-A[1]*e03+A[3]*e01);
20646+    C[7]=  (a0  *e12-A[1]*e02+A[2]*e01);
20647+
20648+    C[8]=   (A[13]*d23-A[14]*d13+a15  *d12);
20649+    C[9]=  -(A[12]*d23-A[14]*d03+a15  *d02);
20650+    C[10]=  (A[12]*d13-A[13]*d03+a15  *d01);
20651+    C[11]= -(A[12]*d12-A[13]*d02+A[14]*d01);
20652+
20653+    C[12]= -(A[9]*d23-a10 *d13+A[11]*d12);
20654+    C[13]=  (A[8]*d23-a10 *d03+A[11]*d02);
20655+    C[14]= -(A[8]*d13-A[9]*d03+A[11]*d01);
20656+    C[15]=  (A[8]*d12-A[9]*d02+a10  *d01);
20657+
20658+    /*Compute square sums of rows
20659+    [16mult 12add=28flops*/
20660+    n0=db_sqr(C[0]) +db_sqr(C[1]) +db_sqr(C[2]) +db_sqr(C[3]);
20661+    n1=db_sqr(C[4]) +db_sqr(C[5]) +db_sqr(C[6]) +db_sqr(C[7]);
20662+    n2=db_sqr(C[8]) +db_sqr(C[9]) +db_sqr(C[10])+db_sqr(C[11]);
20663+    n3=db_sqr(C[12])+db_sqr(C[13])+db_sqr(C[14])+db_sqr(C[15]);
20664+
20665+    /*Take the largest norm row and normalize
20666+    [4mult 1 sqrt=4flops 1sqrt]*/
20667+    if(n0>=n1 && n0>=n2 && n0>=n3)
20668+    {
20669+        m=db_SafeReciprocal(sqrt(n0));
20670+        db_MultiplyScalarCopy4(v,C,m);
20671+    }
20672+    else if(n1>=n2 && n1>=n3)
20673+    {
20674+        m=db_SafeReciprocal(sqrt(n1));
20675+        db_MultiplyScalarCopy4(v,&(C[4]),m);
20676+    }
20677+    else if(n2>=n3)
20678+    {
20679+        m=db_SafeReciprocal(sqrt(n2));
20680+        db_MultiplyScalarCopy4(v,&(C[8]),m);
20681+    }
20682+    else
20683+    {
20684+        m=db_SafeReciprocal(sqrt(n3));
20685+        db_MultiplyScalarCopy4(v,&(C[12]),m);
20686+    }
20687+}
20688+
20689+
20690+
20691+/*\}*/
20692+#endif /* DB_UTILITIES_POLY */
20693diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_random.h b/benchmark/feature_stab/db_vlvm/db_utilities_random.h
20694new file mode 100644
20695index 00000000..ef24039c
20696--- /dev/null
20697+++ b/benchmark/feature_stab/db_vlvm/db_utilities_random.h
20698@@ -0,0 +1,98 @@
20699+/*
20700+ * Copyright (C) 2011 The Android Open Source Project
20701+ *
20702+ * Licensed under the Apache License, Version 2.0 (the "License");
20703+ * you may not use this file except in compliance with the License.
20704+ * You may obtain a copy of the License at
20705+ *
20706+ *      http://www.apache.org/licenses/LICENSE-2.0
20707+ *
20708+ * Unless required by applicable law or agreed to in writing, software
20709+ * distributed under the License is distributed on an "AS IS" BASIS,
20710+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20711+ * See the License for the specific language governing permissions and
20712+ * limitations under the License.
20713+ */
20714+
20715+/* $Id: db_utilities_random.h,v 1.1 2010/08/19 18:09:20 bsouthall Exp $ */
20716+
20717+#ifndef DB_UTILITIES_RANDOM
20718+#define DB_UTILITIES_RANDOM
20719+
20720+#include "db_utilities.h"
20721+
20722+
20723+
20724+/*****************************************************************
20725+*    Lean and mean begins here                                   *
20726+*****************************************************************/
20727+/*!
20728+ * \defgroup LMRandom (LM) Random numbers, random sampling
20729+ */
20730+/*\{*/
20731+/*!
20732+ Random Number generator. Initialize with non-zero
20733+integer value r. A double between zero and one is
20734+returned.
20735+\param r    seed
20736+\return random double
20737+*/
20738+inline double db_QuickRandomDouble(int &r)
20739+{
20740+    int c;
20741+    c=r/127773;
20742+    r=16807*(r-c*127773)-2836*c;
20743+    if(r<0) r+=2147483647;
20744+    return((1.0/((double)2147483647))*r);
20745+    //return (((double)rand())/(double)RAND_MAX);
20746+}
20747+
20748+/*!
20749+Random Number generator. Initialize with non-zero
20750+integer value r. An int between and including 0 and max
20751+ \param r    seed
20752+ \param max    upped limit
20753+ \return random int
20754+*/
20755+inline int db_RandomInt(int &r,int max)
20756+{
20757+    double dtemp;
20758+    int itemp;
20759+    dtemp=db_QuickRandomDouble(r)*(max+1);
20760+    itemp=(int) dtemp;
20761+    if(itemp<=0) return(0);
20762+    if(itemp>=max) return(max);
20763+    return(itemp);
20764+}
20765+
20766+/*!
20767+ Generate a random sample indexing into [0..pool_size-1].
20768+ \param s            sample (out) pre-allocated array of size sample_size
20769+ \param sample_size    size of sample
20770+ \param pool_size    upper limit on item index
20771+ \param r_seed        random number generator seed
20772+ */
20773+inline void db_RandomSample(int *s,int sample_size,int pool_size,int &r_seed)
20774+{
20775+    int temp,temp2,i,j;
20776+
20777+    for(i=0;i<sample_size;i++)
20778+    {
20779+        temp=db_RandomInt(r_seed,pool_size-1-i);
20780+
20781+        for(j=0;j<i;j++)
20782+        {
20783+            if(s[j]<=temp) temp++;
20784+            else
20785+            {
20786+                /*swap*/
20787+                temp2=temp;
20788+                temp=s[j];
20789+                s[j]=temp2;
20790+            }
20791+        }
20792+        s[i]=temp;
20793+    }
20794+}
20795+/*\}*/
20796+#endif /* DB_UTILITIES_RANDOM */
20797diff --git a/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h b/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h
20798new file mode 100644
20799index 00000000..7f5f937b
20800--- /dev/null
20801+++ b/benchmark/feature_stab/db_vlvm/db_utilities_rotation.h
20802@@ -0,0 +1,59 @@
20803+/*
20804+ * Copyright (C) 2011 The Android Open Source Project
20805+ *
20806+ * Licensed under the Apache License, Version 2.0 (the "License");
20807+ * you may not use this file except in compliance with the License.
20808+ * You may obtain a copy of the License at
20809+ *
20810+ *      http://www.apache.org/licenses/LICENSE-2.0
20811+ *
20812+ * Unless required by applicable law or agreed to in writing, software
20813+ * distributed under the License is distributed on an "AS IS" BASIS,
20814+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20815+ * See the License for the specific language governing permissions and
20816+ * limitations under the License.
20817+ */
20818+
20819+/* $Id: db_utilities_rotation.h,v 1.2 2010/09/03 12:00:11 bsouthall Exp $ */
20820+
20821+#ifndef DB_UTILITIES_ROTATION
20822+#define DB_UTILITIES_ROTATION
20823+
20824+#include "db_utilities.h"
20825+
20826+
20827+
20828+/*****************************************************************
20829+*    Lean and mean begins here                                   *
20830+*****************************************************************/
20831+/*!
20832+ * \defgroup LMRotation (LM) Rotation Utilities (quaternions, orthonormal)
20833+ */
20834+/*\{*/
20835+/*!
20836+ Takes a unit quaternion and gives its corresponding rotation matrix.
20837+ \param R rotation matrix (out)
20838+ \param q quaternion
20839+ */
20840+inline void db_QuaternionToRotation(double R[9],const double q[4])
20841+{
20842+    double q0q0,q0qx,q0qy,q0qz,qxqx,qxqy,qxqz,qyqy,qyqz,qzqz;
20843+
20844+    q0q0=q[0]*q[0];
20845+    q0qx=q[0]*q[1];
20846+    q0qy=q[0]*q[2];
20847+    q0qz=q[0]*q[3];
20848+    qxqx=q[1]*q[1];
20849+    qxqy=q[1]*q[2];
20850+    qxqz=q[1]*q[3];
20851+    qyqy=q[2]*q[2];
20852+    qyqz=q[2]*q[3];
20853+    qzqz=q[3]*q[3];
20854+
20855+    R[0]=q0q0+qxqx-qyqy-qzqz; R[1]=2.0*(qxqy-q0qz);     R[2]=2.0*(qxqz+q0qy);
20856+    R[3]=2.0*(qxqy+q0qz);     R[4]=q0q0-qxqx+qyqy-qzqz; R[5]=2.0*(qyqz-q0qx);
20857+    R[6]=2.0*(qxqz-q0qy);     R[7]=2.0*(qyqz+q0qx);     R[8]=q0q0-qxqx-qyqy+qzqz;
20858+}
20859+
20860+/*\}*/
20861+#endif /* DB_UTILITIES_ROTATION */
20862diff --git a/benchmark/feature_stab/doc/Readme.txt b/benchmark/feature_stab/doc/Readme.txt
20863new file mode 100644
20864index 00000000..fcd7c38c
20865--- /dev/null
20866+++ b/benchmark/feature_stab/doc/Readme.txt
20867@@ -0,0 +1,3 @@
20868+To generate the html docs, execute
20869+doxygen dbreg_API_doxyfile
20870+
20871diff --git a/benchmark/feature_stab/doc/dbreg_API_doxyfile b/benchmark/feature_stab/doc/dbreg_API_doxyfile
20872new file mode 100755
20873index 00000000..dc61a9c0
20874--- /dev/null
20875+++ b/benchmark/feature_stab/doc/dbreg_API_doxyfile
20876@@ -0,0 +1,1557 @@
20877+# Doxyfile 1.6.1
20878+
20879+# This file describes the settings to be used by the documentation system
20880+# doxygen (www.doxygen.org) for a project
20881+#
20882+# All text after a hash (#) is considered a comment and will be ignored
20883+# The format is:
20884+#       TAG = value [value, ...]
20885+# For lists items can also be appended using:
20886+#       TAG += value [value, ...]
20887+# Values that contain spaces should be placed between quotes (" ")
20888+
20889+#---------------------------------------------------------------------------
20890+# Project related configuration options
20891+#---------------------------------------------------------------------------
20892+
20893+# This tag specifies the encoding used for all characters in the config file
20894+# that follow. The default is UTF-8 which is also the encoding used for all
20895+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
20896+# iconv built into libc) for the transcoding. See
20897+# http://www.gnu.org/software/libiconv for the list of possible encodings.
20898+
20899+DOXYFILE_ENCODING      = UTF-8
20900+
20901+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
20902+# by quotes) that should identify the project.
20903+
20904+PROJECT_NAME           =
20905+
20906+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
20907+# This could be handy for archiving the generated documentation or
20908+# if some version control system is used.
20909+
20910+PROJECT_NUMBER         =
20911+
20912+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
20913+# base path where the generated documentation will be put.
20914+# If a relative path is entered, it will be relative to the location
20915+# where doxygen was started. If left blank the current directory will be used.
20916+
20917+OUTPUT_DIRECTORY       = .
20918+
20919+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
20920+# 4096 sub-directories (in 2 levels) under the output directory of each output
20921+# format and will distribute the generated files over these directories.
20922+# Enabling this option can be useful when feeding doxygen a huge amount of
20923+# source files, where putting all generated files in the same directory would
20924+# otherwise cause performance problems for the file system.
20925+
20926+CREATE_SUBDIRS         = NO
20927+
20928+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
20929+# documentation generated by doxygen is written. Doxygen will use this
20930+# information to generate all constant output in the proper language.
20931+# The default language is English, other supported languages are:
20932+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
20933+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
20934+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
20935+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
20936+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
20937+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
20938+
20939+OUTPUT_LANGUAGE        = English
20940+
20941+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
20942+# include brief member descriptions after the members that are listed in
20943+# the file and class documentation (similar to JavaDoc).
20944+# Set to NO to disable this.
20945+
20946+BRIEF_MEMBER_DESC      = YES
20947+
20948+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
20949+# the brief description of a member or function before the detailed description.
20950+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
20951+# brief descriptions will be completely suppressed.
20952+
20953+REPEAT_BRIEF           = YES
20954+
20955+# This tag implements a quasi-intelligent brief description abbreviator
20956+# that is used to form the text in various listings. Each string
20957+# in this list, if found as the leading text of the brief description, will be
20958+# stripped from the text and the result after processing the whole list, is
20959+# used as the annotated text. Otherwise, the brief description is used as-is.
20960+# If left blank, the following values are used ("$name" is automatically
20961+# replaced with the name of the entity): "The $name class" "The $name widget"
20962+# "The $name file" "is" "provides" "specifies" "contains"
20963+# "represents" "a" "an" "the"
20964+
20965+ABBREVIATE_BRIEF       = "The $name class" \
20966+                         "The $name widget" \
20967+                         "The $name file" \
20968+                         is \
20969+                         provides \
20970+                         specifies \
20971+                         contains \
20972+                         represents \
20973+                         a \
20974+                         an \
20975+                         the
20976+
20977+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
20978+# Doxygen will generate a detailed section even if there is only a brief
20979+# description.
20980+
20981+ALWAYS_DETAILED_SEC    = NO
20982+
20983+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
20984+# inherited members of a class in the documentation of that class as if those
20985+# members were ordinary class members. Constructors, destructors and assignment
20986+# operators of the base classes will not be shown.
20987+
20988+INLINE_INHERITED_MEMB  = NO
20989+
20990+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
20991+# path before files name in the file list and in the header files. If set
20992+# to NO the shortest path that makes the file name unique will be used.
20993+
20994+FULL_PATH_NAMES        = YES
20995+
20996+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
20997+# can be used to strip a user-defined part of the path. Stripping is
20998+# only done if one of the specified strings matches the left-hand part of
20999+# the path. The tag can be used to show relative paths in the file list.
21000+# If left blank the directory from which doxygen is run is used as the
21001+# path to strip.
21002+
21003+STRIP_FROM_PATH        = /Users/dimitri/doxygen/mail/1.5.7/doxywizard/
21004+
21005+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
21006+# the path mentioned in the documentation of a class, which tells
21007+# the reader which header file to include in order to use a class.
21008+# If left blank only the name of the header file containing the class
21009+# definition is used. Otherwise one should specify the include paths that
21010+# are normally passed to the compiler using the -I flag.
21011+
21012+STRIP_FROM_INC_PATH    =
21013+
21014+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
21015+# (but less readable) file names. This can be useful is your file systems
21016+# doesn't support long names like on DOS, Mac, or CD-ROM.
21017+
21018+SHORT_NAMES            = NO
21019+
21020+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
21021+# will interpret the first line (until the first dot) of a JavaDoc-style
21022+# comment as the brief description. If set to NO, the JavaDoc
21023+# comments will behave just like regular Qt-style comments
21024+# (thus requiring an explicit @brief command for a brief description.)
21025+
21026+JAVADOC_AUTOBRIEF      = NO
21027+
21028+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
21029+# interpret the first line (until the first dot) of a Qt-style
21030+# comment as the brief description. If set to NO, the comments
21031+# will behave just like regular Qt-style comments (thus requiring
21032+# an explicit \brief command for a brief description.)
21033+
21034+QT_AUTOBRIEF           = NO
21035+
21036+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
21037+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
21038+# comments) as a brief description. This used to be the default behaviour.
21039+# The new default is to treat a multi-line C++ comment block as a detailed
21040+# description. Set this tag to YES if you prefer the old behaviour instead.
21041+
21042+MULTILINE_CPP_IS_BRIEF = NO
21043+
21044+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
21045+# member inherits the documentation from any documented member that it
21046+# re-implements.
21047+
21048+INHERIT_DOCS           = YES
21049+
21050+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
21051+# a new page for each member. If set to NO, the documentation of a member will
21052+# be part of the file/class/namespace that contains it.
21053+
21054+SEPARATE_MEMBER_PAGES  = NO
21055+
21056+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
21057+# Doxygen uses this value to replace tabs by spaces in code fragments.
21058+
21059+TAB_SIZE               = 8
21060+
21061+# This tag can be used to specify a number of aliases that acts
21062+# as commands in the documentation. An alias has the form "name=value".
21063+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
21064+# put the command \sideeffect (or @sideeffect) in the documentation, which
21065+# will result in a user-defined paragraph with heading "Side Effects:".
21066+# You can put \n's in the value part of an alias to insert newlines.
21067+
21068+ALIASES                =
21069+
21070+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
21071+# sources only. Doxygen will then generate output that is more tailored for C.
21072+# For instance, some of the names that are used will be different. The list
21073+# of all members will be omitted, etc.
21074+
21075+OPTIMIZE_OUTPUT_FOR_C  = NO
21076+
21077+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
21078+# sources only. Doxygen will then generate output that is more tailored for
21079+# Java. For instance, namespaces will be presented as packages, qualified
21080+# scopes will look different, etc.
21081+
21082+OPTIMIZE_OUTPUT_JAVA   = NO
21083+
21084+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
21085+# sources only. Doxygen will then generate output that is more tailored for
21086+# Fortran.
21087+
21088+OPTIMIZE_FOR_FORTRAN   = NO
21089+
21090+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
21091+# sources. Doxygen will then generate output that is tailored for
21092+# VHDL.
21093+
21094+OPTIMIZE_OUTPUT_VHDL   = NO
21095+
21096+# Doxygen selects the parser to use depending on the extension of the files it parses.
21097+# With this tag you can assign which parser to use for a given extension.
21098+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
21099+# The format is ext=language, where ext is a file extension, and language is one of
21100+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
21101+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
21102+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
21103+# use: inc=Fortran f=C. Note that for custom extensions you also need to set
21104+# FILE_PATTERNS otherwise the files are not read by doxygen.
21105+
21106+EXTENSION_MAPPING      =
21107+
21108+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
21109+# to include (a tag file for) the STL sources as input, then you should
21110+# set this tag to YES in order to let doxygen match functions declarations and
21111+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
21112+# func(std::string) {}). This also make the inheritance and collaboration
21113+# diagrams that involve STL classes more complete and accurate.
21114+
21115+BUILTIN_STL_SUPPORT    = NO
21116+
21117+# If you use Microsoft's C++/CLI language, you should set this option to YES to
21118+# enable parsing support.
21119+
21120+CPP_CLI_SUPPORT        = NO
21121+
21122+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
21123+# Doxygen will parse them like normal C++ but will assume all classes use public
21124+# instead of private inheritance when no explicit protection keyword is present.
21125+
21126+SIP_SUPPORT            = NO
21127+
21128+# For Microsoft's IDL there are propget and propput attributes to indicate getter
21129+# and setter methods for a property. Setting this option to YES (the default)
21130+# will make doxygen to replace the get and set methods by a property in the
21131+# documentation. This will only work if the methods are indeed getting or
21132+# setting a simple type. If this is not the case, or you want to show the
21133+# methods anyway, you should set this option to NO.
21134+
21135+IDL_PROPERTY_SUPPORT   = YES
21136+
21137+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
21138+# tag is set to YES, then doxygen will reuse the documentation of the first
21139+# member in the group (if any) for the other members of the group. By default
21140+# all members of a group must be documented explicitly.
21141+
21142+DISTRIBUTE_GROUP_DOC   = NO
21143+
21144+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
21145+# the same type (for instance a group of public functions) to be put as a
21146+# subgroup of that type (e.g. under the Public Functions section). Set it to
21147+# NO to prevent subgrouping. Alternatively, this can be done per class using
21148+# the \nosubgrouping command.
21149+
21150+SUBGROUPING            = YES
21151+
21152+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
21153+# is documented as struct, union, or enum with the name of the typedef. So
21154+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
21155+# with name TypeT. When disabled the typedef will appear as a member of a file,
21156+# namespace, or class. And the struct will be named TypeS. This can typically
21157+# be useful for C code in case the coding convention dictates that all compound
21158+# types are typedef'ed and only the typedef is referenced, never the tag name.
21159+
21160+TYPEDEF_HIDES_STRUCT   = NO
21161+
21162+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
21163+# determine which symbols to keep in memory and which to flush to disk.
21164+# When the cache is full, less often used symbols will be written to disk.
21165+# For small to medium size projects (<1000 input files) the default value is
21166+# probably good enough. For larger projects a too small cache size can cause
21167+# doxygen to be busy swapping symbols to and from disk most of the time
21168+# causing a significant performance penality.
21169+# If the system has enough physical memory increasing the cache will improve the
21170+# performance by keeping more symbols in memory. Note that the value works on
21171+# a logarithmic scale so increasing the size by one will rougly double the
21172+# memory usage. The cache size is given by this formula:
21173+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
21174+# corresponding to a cache size of 2^16 = 65536 symbols
21175+
21176+SYMBOL_CACHE_SIZE      = 0
21177+
21178+#---------------------------------------------------------------------------
21179+# Build related configuration options
21180+#---------------------------------------------------------------------------
21181+
21182+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
21183+# documentation are documented, even if no documentation was available.
21184+# Private class members and static file members will be hidden unless
21185+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
21186+
21187+EXTRACT_ALL            = NO
21188+
21189+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
21190+# will be included in the documentation.
21191+
21192+EXTRACT_PRIVATE        = NO
21193+
21194+# If the EXTRACT_STATIC tag is set to YES all static members of a file
21195+# will be included in the documentation.
21196+
21197+EXTRACT_STATIC         = NO
21198+
21199+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
21200+# defined locally in source files will be included in the documentation.
21201+# If set to NO only classes defined in header files are included.
21202+
21203+EXTRACT_LOCAL_CLASSES  = YES
21204+
21205+# This flag is only useful for Objective-C code. When set to YES local
21206+# methods, which are defined in the implementation section but not in
21207+# the interface are included in the documentation.
21208+# If set to NO (the default) only methods in the interface are included.
21209+
21210+EXTRACT_LOCAL_METHODS  = NO
21211+
21212+# If this flag is set to YES, the members of anonymous namespaces will be
21213+# extracted and appear in the documentation as a namespace called
21214+# 'anonymous_namespace{file}', where file will be replaced with the base
21215+# name of the file that contains the anonymous namespace. By default
21216+# anonymous namespace are hidden.
21217+
21218+EXTRACT_ANON_NSPACES   = NO
21219+
21220+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
21221+# undocumented members of documented classes, files or namespaces.
21222+# If set to NO (the default) these members will be included in the
21223+# various overviews, but no documentation section is generated.
21224+# This option has no effect if EXTRACT_ALL is enabled.
21225+
21226+HIDE_UNDOC_MEMBERS     = NO
21227+
21228+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
21229+# undocumented classes that are normally visible in the class hierarchy.
21230+# If set to NO (the default) these classes will be included in the various
21231+# overviews. This option has no effect if EXTRACT_ALL is enabled.
21232+
21233+HIDE_UNDOC_CLASSES     = NO
21234+
21235+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
21236+# friend (class|struct|union) declarations.
21237+# If set to NO (the default) these declarations will be included in the
21238+# documentation.
21239+
21240+HIDE_FRIEND_COMPOUNDS  = NO
21241+
21242+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
21243+# documentation blocks found inside the body of a function.
21244+# If set to NO (the default) these blocks will be appended to the
21245+# function's detailed documentation block.
21246+
21247+HIDE_IN_BODY_DOCS      = NO
21248+
21249+# The INTERNAL_DOCS tag determines if documentation
21250+# that is typed after a \internal command is included. If the tag is set
21251+# to NO (the default) then the documentation will be excluded.
21252+# Set it to YES to include the internal documentation.
21253+
21254+INTERNAL_DOCS          = NO
21255+
21256+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
21257+# file names in lower-case letters. If set to YES upper-case letters are also
21258+# allowed. This is useful if you have classes or files whose names only differ
21259+# in case and if your file system supports case sensitive file names. Windows
21260+# and Mac users are advised to set this option to NO.
21261+
21262+CASE_SENSE_NAMES       = NO
21263+
21264+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
21265+# will show members with their full class and namespace scopes in the
21266+# documentation. If set to YES the scope will be hidden.
21267+
21268+HIDE_SCOPE_NAMES       = NO
21269+
21270+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
21271+# will put a list of the files that are included by a file in the documentation
21272+# of that file.
21273+
21274+SHOW_INCLUDE_FILES     = YES
21275+
21276+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
21277+# is inserted in the documentation for inline members.
21278+
21279+INLINE_INFO            = YES
21280+
21281+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
21282+# will sort the (detailed) documentation of file and class members
21283+# alphabetically by member name. If set to NO the members will appear in
21284+# declaration order.
21285+
21286+SORT_MEMBER_DOCS       = YES
21287+
21288+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
21289+# brief documentation of file, namespace and class members alphabetically
21290+# by member name. If set to NO (the default) the members will appear in
21291+# declaration order.
21292+
21293+SORT_BRIEF_DOCS        = NO
21294+
21295+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
21296+# will sort the (brief and detailed) documentation of class members so that
21297+# constructors and destructors are listed first. If set to NO (the default)
21298+# the constructors will appear in the respective orders defined by
21299+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
21300+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
21301+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
21302+
21303+SORT_MEMBERS_CTORS_1ST = NO
21304+
21305+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
21306+# hierarchy of group names into alphabetical order. If set to NO (the default)
21307+# the group names will appear in their defined order.
21308+
21309+SORT_GROUP_NAMES       = NO
21310+
21311+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
21312+# sorted by fully-qualified names, including namespaces. If set to
21313+# NO (the default), the class list will be sorted only by class name,
21314+# not including the namespace part.
21315+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
21316+# Note: This option applies only to the class list, not to the
21317+# alphabetical list.
21318+
21319+SORT_BY_SCOPE_NAME     = NO
21320+
21321+# The GENERATE_TODOLIST tag can be used to enable (YES) or
21322+# disable (NO) the todo list. This list is created by putting \todo
21323+# commands in the documentation.
21324+
21325+GENERATE_TODOLIST      = YES
21326+
21327+# The GENERATE_TESTLIST tag can be used to enable (YES) or
21328+# disable (NO) the test list. This list is created by putting \test
21329+# commands in the documentation.
21330+
21331+GENERATE_TESTLIST      = YES
21332+
21333+# The GENERATE_BUGLIST tag can be used to enable (YES) or
21334+# disable (NO) the bug list. This list is created by putting \bug
21335+# commands in the documentation.
21336+
21337+GENERATE_BUGLIST       = YES
21338+
21339+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
21340+# disable (NO) the deprecated list. This list is created by putting
21341+# \deprecated commands in the documentation.
21342+
21343+GENERATE_DEPRECATEDLIST= YES
21344+
21345+# The ENABLED_SECTIONS tag can be used to enable conditional
21346+# documentation sections, marked by \if sectionname ... \endif.
21347+
21348+ENABLED_SECTIONS       =
21349+
21350+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
21351+# the initial value of a variable or define consists of for it to appear in
21352+# the documentation. If the initializer consists of more lines than specified
21353+# here it will be hidden. Use a value of 0 to hide initializers completely.
21354+# The appearance of the initializer of individual variables and defines in the
21355+# documentation can be controlled using \showinitializer or \hideinitializer
21356+# command in the documentation regardless of this setting.
21357+
21358+MAX_INITIALIZER_LINES  = 30
21359+
21360+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
21361+# at the bottom of the documentation of classes and structs. If set to YES the
21362+# list will mention the files that were used to generate the documentation.
21363+
21364+SHOW_USED_FILES        = YES
21365+
21366+# If the sources in your project are distributed over multiple directories
21367+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
21368+# in the documentation. The default is NO.
21369+
21370+SHOW_DIRECTORIES       = NO
21371+
21372+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
21373+# This will remove the Files entry from the Quick Index and from the
21374+# Folder Tree View (if specified). The default is YES.
21375+
21376+SHOW_FILES             = YES
21377+
21378+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
21379+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
21380+# and from the Folder Tree View (if specified). The default is YES.
21381+
21382+SHOW_NAMESPACES        = YES
21383+
21384+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
21385+# doxygen should invoke to get the current version for each file (typically from
21386+# the version control system). Doxygen will invoke the program by executing (via
21387+# popen()) the command <command> <input-file>, where <command> is the value of
21388+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
21389+# provided by doxygen. Whatever the program writes to standard output
21390+# is used as the file version. See the manual for examples.
21391+
21392+FILE_VERSION_FILTER    =
21393+
21394+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
21395+# doxygen. The layout file controls the global structure of the generated output files
21396+# in an output format independent way. The create the layout file that represents
21397+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
21398+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
21399+# of the layout file.
21400+
21401+LAYOUT_FILE            =
21402+
21403+#---------------------------------------------------------------------------
21404+# configuration options related to warning and progress messages
21405+#---------------------------------------------------------------------------
21406+
21407+# The QUIET tag can be used to turn on/off the messages that are generated
21408+# by doxygen. Possible values are YES and NO. If left blank NO is used.
21409+
21410+QUIET                  = NO
21411+
21412+# The WARNINGS tag can be used to turn on/off the warning messages that are
21413+# generated by doxygen. Possible values are YES and NO. If left blank
21414+# NO is used.
21415+
21416+WARNINGS               = YES
21417+
21418+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
21419+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
21420+# automatically be disabled.
21421+
21422+WARN_IF_UNDOCUMENTED   = YES
21423+
21424+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
21425+# potential errors in the documentation, such as not documenting some
21426+# parameters in a documented function, or documenting parameters that
21427+# don't exist or using markup commands wrongly.
21428+
21429+WARN_IF_DOC_ERROR      = YES
21430+
21431+# This WARN_NO_PARAMDOC option can be abled to get warnings for
21432+# functions that are documented, but have no documentation for their parameters
21433+# or return value. If set to NO (the default) doxygen will only warn about
21434+# wrong or incomplete parameter documentation, but not about the absence of
21435+# documentation.
21436+
21437+WARN_NO_PARAMDOC       = NO
21438+
21439+# The WARN_FORMAT tag determines the format of the warning messages that
21440+# doxygen can produce. The string should contain the $file, $line, and $text
21441+# tags, which will be replaced by the file and line number from which the
21442+# warning originated and the warning text. Optionally the format may contain
21443+# $version, which will be replaced by the version of the file (if it could
21444+# be obtained via FILE_VERSION_FILTER)
21445+
21446+WARN_FORMAT            = "$file:$line: $text"
21447+
21448+# The WARN_LOGFILE tag can be used to specify a file to which warning
21449+# and error messages should be written. If left blank the output is written
21450+# to stderr.
21451+
21452+WARN_LOGFILE           =
21453+
21454+#---------------------------------------------------------------------------
21455+# configuration options related to the input files
21456+#---------------------------------------------------------------------------
21457+
21458+# The INPUT tag can be used to specify the files and/or directories that contain
21459+# documented source files. You may enter file names like "myfile.cpp" or
21460+# directories like "/usr/src/myproject". Separate the files or directories
21461+# with spaces.
21462+
21463+INPUT                  = ../src/dbreg/dbreg.h
21464+
21465+# This tag can be used to specify the character encoding of the source files
21466+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
21467+# also the default input encoding. Doxygen uses libiconv (or the iconv built
21468+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
21469+# the list of possible encodings.
21470+
21471+INPUT_ENCODING         = UTF-8
21472+
21473+# If the value of the INPUT tag contains directories, you can use the
21474+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
21475+# and *.h) to filter out the source-files in the directories. If left
21476+# blank the following patterns are tested:
21477+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
21478+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
21479+
21480+FILE_PATTERNS          = *.c \
21481+                         *.cc \
21482+                         *.cxx \
21483+                         *.cpp \
21484+                         *.c++ \
21485+                         *.d \
21486+                         *.java \
21487+                         *.ii \
21488+                         *.ixx \
21489+                         *.ipp \
21490+                         *.i++ \
21491+                         *.inl \
21492+                         *.h \
21493+                         *.hh \
21494+                         *.hxx \
21495+                         *.hpp \
21496+                         *.h++ \
21497+                         *.idl \
21498+                         *.odl \
21499+                         *.cs \
21500+                         *.php \
21501+                         *.php3 \
21502+                         *.inc \
21503+                         *.m \
21504+                         *.mm \
21505+                         *.dox \
21506+                         *.py \
21507+                         *.f90 \
21508+                         *.f \
21509+                         *.vhd \
21510+                         *.vhdl
21511+
21512+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
21513+# should be searched for input files as well. Possible values are YES and NO.
21514+# If left blank NO is used.
21515+
21516+RECURSIVE              = NO
21517+
21518+# The EXCLUDE tag can be used to specify files and/or directories that should
21519+# excluded from the INPUT source files. This way you can easily exclude a
21520+# subdirectory from a directory tree whose root is specified with the INPUT tag.
21521+
21522+EXCLUDE                =
21523+
21524+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
21525+# directories that are symbolic links (a Unix filesystem feature) are excluded
21526+# from the input.
21527+
21528+EXCLUDE_SYMLINKS       = NO
21529+
21530+# If the value of the INPUT tag contains directories, you can use the
21531+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
21532+# certain files from those directories. Note that the wildcards are matched
21533+# against the file with absolute path, so to exclude all test directories
21534+# for example use the pattern */test/*
21535+
21536+EXCLUDE_PATTERNS       =
21537+
21538+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
21539+# (namespaces, classes, functions, etc.) that should be excluded from the
21540+# output. The symbol name can be a fully qualified name, a word, or if the
21541+# wildcard * is used, a substring. Examples: ANamespace, AClass,
21542+# AClass::ANamespace, ANamespace::*Test
21543+
21544+EXCLUDE_SYMBOLS        =
21545+
21546+# The EXAMPLE_PATH tag can be used to specify one or more files or
21547+# directories that contain example code fragments that are included (see
21548+# the \include command).
21549+
21550+EXAMPLE_PATH           =
21551+
21552+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
21553+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
21554+# and *.h) to filter out the source-files in the directories. If left
21555+# blank all files are included.
21556+
21557+EXAMPLE_PATTERNS       = *
21558+
21559+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
21560+# searched for input files to be used with the \include or \dontinclude
21561+# commands irrespective of the value of the RECURSIVE tag.
21562+# Possible values are YES and NO. If left blank NO is used.
21563+
21564+EXAMPLE_RECURSIVE      = NO
21565+
21566+# The IMAGE_PATH tag can be used to specify one or more files or
21567+# directories that contain image that are included in the documentation (see
21568+# the \image command).
21569+
21570+IMAGE_PATH             =
21571+
21572+# The INPUT_FILTER tag can be used to specify a program that doxygen should
21573+# invoke to filter for each input file. Doxygen will invoke the filter program
21574+# by executing (via popen()) the command <filter> <input-file>, where <filter>
21575+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
21576+# input file. Doxygen will then use the output that the filter program writes
21577+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
21578+# ignored.
21579+
21580+INPUT_FILTER           =
21581+
21582+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
21583+# basis.  Doxygen will compare the file name with each pattern and apply the
21584+# filter if there is a match.  The filters are a list of the form:
21585+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
21586+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
21587+# is applied to all files.
21588+
21589+FILTER_PATTERNS        =
21590+
21591+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
21592+# INPUT_FILTER) will be used to filter the input files when producing source
21593+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
21594+
21595+FILTER_SOURCE_FILES    = NO
21596+
21597+#---------------------------------------------------------------------------
21598+# configuration options related to source browsing
21599+#---------------------------------------------------------------------------
21600+
21601+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
21602+# be generated. Documented entities will be cross-referenced with these sources.
21603+# Note: To get rid of all source code in the generated output, make sure also
21604+# VERBATIM_HEADERS is set to NO.
21605+
21606+SOURCE_BROWSER         = NO
21607+
21608+# Setting the INLINE_SOURCES tag to YES will include the body
21609+# of functions and classes directly in the documentation.
21610+
21611+INLINE_SOURCES         = NO
21612+
21613+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
21614+# doxygen to hide any special comment blocks from generated source code
21615+# fragments. Normal C and C++ comments will always remain visible.
21616+
21617+STRIP_CODE_COMMENTS    = YES
21618+
21619+# If the REFERENCED_BY_RELATION tag is set to YES
21620+# then for each documented function all documented
21621+# functions referencing it will be listed.
21622+
21623+REFERENCED_BY_RELATION = NO
21624+
21625+# If the REFERENCES_RELATION tag is set to YES
21626+# then for each documented function all documented entities
21627+# called/used by that function will be listed.
21628+
21629+REFERENCES_RELATION    = NO
21630+
21631+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
21632+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
21633+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
21634+# link to the source code.  Otherwise they will link to the documentation.
21635+
21636+REFERENCES_LINK_SOURCE = YES
21637+
21638+# If the USE_HTAGS tag is set to YES then the references to source code
21639+# will point to the HTML generated by the htags(1) tool instead of doxygen
21640+# built-in source browser. The htags tool is part of GNU's global source
21641+# tagging system (see http://www.gnu.org/software/global/global.html). You
21642+# will need version 4.8.6 or higher.
21643+
21644+USE_HTAGS              = NO
21645+
21646+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
21647+# will generate a verbatim copy of the header file for each class for
21648+# which an include is specified. Set to NO to disable this.
21649+
21650+VERBATIM_HEADERS       = YES
21651+
21652+#---------------------------------------------------------------------------
21653+# configuration options related to the alphabetical class index
21654+#---------------------------------------------------------------------------
21655+
21656+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
21657+# of all compounds will be generated. Enable this if the project
21658+# contains a lot of classes, structs, unions or interfaces.
21659+
21660+ALPHABETICAL_INDEX     = NO
21661+
21662+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
21663+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
21664+# in which this list will be split (can be a number in the range [1..20])
21665+
21666+COLS_IN_ALPHA_INDEX    = 5
21667+
21668+# In case all classes in a project start with a common prefix, all
21669+# classes will be put under the same header in the alphabetical index.
21670+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
21671+# should be ignored while generating the index headers.
21672+
21673+IGNORE_PREFIX          =
21674+
21675+#---------------------------------------------------------------------------
21676+# configuration options related to the HTML output
21677+#---------------------------------------------------------------------------
21678+
21679+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
21680+# generate HTML output.
21681+
21682+GENERATE_HTML          = YES
21683+
21684+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
21685+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
21686+# put in front of it. If left blank `html' will be used as the default path.
21687+
21688+HTML_OUTPUT            = html
21689+
21690+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
21691+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
21692+# doxygen will generate files with .html extension.
21693+
21694+HTML_FILE_EXTENSION    = .html
21695+
21696+# The HTML_HEADER tag can be used to specify a personal HTML header for
21697+# each generated HTML page. If it is left blank doxygen will generate a
21698+# standard header.
21699+
21700+HTML_HEADER            =
21701+
21702+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
21703+# each generated HTML page. If it is left blank doxygen will generate a
21704+# standard footer.
21705+
21706+HTML_FOOTER            =
21707+
21708+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
21709+# style sheet that is used by each HTML page. It can be used to
21710+# fine-tune the look of the HTML output. If the tag is left blank doxygen
21711+# will generate a default style sheet. Note that doxygen will try to copy
21712+# the style sheet file to the HTML output directory, so don't put your own
21713+# stylesheet in the HTML output directory as well, or it will be erased!
21714+
21715+HTML_STYLESHEET        =
21716+
21717+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
21718+# files or namespaces will be aligned in HTML using tables. If set to
21719+# NO a bullet list will be used.
21720+
21721+HTML_ALIGN_MEMBERS     = YES
21722+
21723+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
21724+# documentation will contain sections that can be hidden and shown after the
21725+# page has loaded. For this to work a browser that supports
21726+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
21727+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
21728+
21729+HTML_DYNAMIC_SECTIONS  = NO
21730+
21731+# If the GENERATE_DOCSET tag is set to YES, additional index files
21732+# will be generated that can be used as input for Apple's Xcode 3
21733+# integrated development environment, introduced with OSX 10.5 (Leopard).
21734+# To create a documentation set, doxygen will generate a Makefile in the
21735+# HTML output directory. Running make will produce the docset in that
21736+# directory and running "make install" will install the docset in
21737+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
21738+# it at startup.
21739+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
21740+
21741+GENERATE_DOCSET        = NO
21742+
21743+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
21744+# feed. A documentation feed provides an umbrella under which multiple
21745+# documentation sets from a single provider (such as a company or product suite)
21746+# can be grouped.
21747+
21748+DOCSET_FEEDNAME        = "Doxygen generated docs"
21749+
21750+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
21751+# should uniquely identify the documentation set bundle. This should be a
21752+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
21753+# will append .docset to the name.
21754+
21755+DOCSET_BUNDLE_ID       = org.doxygen.Project
21756+
21757+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
21758+# will be generated that can be used as input for tools like the
21759+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
21760+# of the generated HTML documentation.
21761+
21762+GENERATE_HTMLHELP      = NO
21763+
21764+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
21765+# be used to specify the file name of the resulting .chm file. You
21766+# can add a path in front of the file if the result should not be
21767+# written to the html output directory.
21768+
21769+CHM_FILE               =
21770+
21771+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
21772+# be used to specify the location (absolute path including file name) of
21773+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
21774+# the HTML help compiler on the generated index.hhp.
21775+
21776+HHC_LOCATION           =
21777+
21778+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
21779+# controls if a separate .chi index file is generated (YES) or that
21780+# it should be included in the master .chm file (NO).
21781+
21782+GENERATE_CHI           = NO
21783+
21784+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
21785+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
21786+# content.
21787+
21788+CHM_INDEX_ENCODING     =
21789+
21790+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
21791+# controls whether a binary table of contents is generated (YES) or a
21792+# normal table of contents (NO) in the .chm file.
21793+
21794+BINARY_TOC             = NO
21795+
21796+# The TOC_EXPAND flag can be set to YES to add extra items for group members
21797+# to the contents of the HTML help documentation and to the tree view.
21798+
21799+TOC_EXPAND             = NO
21800+
21801+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
21802+# are set, an additional index file will be generated that can be used as input for
21803+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
21804+# HTML documentation.
21805+
21806+GENERATE_QHP           = NO
21807+
21808+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
21809+# be used to specify the file name of the resulting .qch file.
21810+# The path specified is relative to the HTML output folder.
21811+
21812+QCH_FILE               =
21813+
21814+# The QHP_NAMESPACE tag specifies the namespace to use when generating
21815+# Qt Help Project output. For more information please see
21816+# http://doc.trolltech.com/qthelpproject.html#namespace
21817+
21818+QHP_NAMESPACE          =
21819+
21820+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
21821+# Qt Help Project output. For more information please see
21822+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
21823+
21824+QHP_VIRTUAL_FOLDER     = doc
21825+
21826+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
21827+# For more information please see
21828+# http://doc.trolltech.com/qthelpproject.html#custom-filters
21829+
21830+QHP_CUST_FILTER_NAME   =
21831+
21832+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
21833+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
21834+
21835+QHP_CUST_FILTER_ATTRS  =
21836+
21837+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
21838+# filter section matches.
21839+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
21840+
21841+QHP_SECT_FILTER_ATTRS  =
21842+
21843+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
21844+# be used to specify the location of Qt's qhelpgenerator.
21845+# If non-empty doxygen will try to run qhelpgenerator on the generated
21846+# .qhp file.
21847+
21848+QHG_LOCATION           =
21849+
21850+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
21851+# top of each HTML page. The value NO (the default) enables the index and
21852+# the value YES disables it.
21853+
21854+DISABLE_INDEX          = NO
21855+
21856+# This tag can be used to set the number of enum values (range [1..20])
21857+# that doxygen will group on one line in the generated HTML documentation.
21858+
21859+ENUM_VALUES_PER_LINE   = 4
21860+
21861+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
21862+# structure should be generated to display hierarchical information.
21863+# If the tag value is set to YES, a side panel will be generated
21864+# containing a tree-like index structure (just like the one that
21865+# is generated for HTML Help). For this to work a browser that supports
21866+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
21867+# Windows users are probably better off using the HTML help feature.
21868+
21869+GENERATE_TREEVIEW      = NO
21870+
21871+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
21872+# and Class Hierarchy pages using a tree view instead of an ordered list.
21873+
21874+USE_INLINE_TREES       = NO
21875+
21876+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
21877+# used to set the initial width (in pixels) of the frame in which the tree
21878+# is shown.
21879+
21880+TREEVIEW_WIDTH         = 250
21881+
21882+# Use this tag to change the font size of Latex formulas included
21883+# as images in the HTML documentation. The default is 10. Note that
21884+# when you change the font size after a successful doxygen run you need
21885+# to manually remove any form_*.png images from the HTML output directory
21886+# to force them to be regenerated.
21887+
21888+FORMULA_FONTSIZE       = 10
21889+
21890+# When the SEARCHENGINE tag is enable doxygen will generate a search box
21891+# for the HTML output. The underlying search engine uses javascript
21892+# and DHTML and should work on any modern browser. Note that when using
21893+# HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP)
21894+# there is already a search function so this one should typically
21895+# be disabled.
21896+
21897+SEARCHENGINE           = YES
21898+
21899+#---------------------------------------------------------------------------
21900+# configuration options related to the LaTeX output
21901+#---------------------------------------------------------------------------
21902+
21903+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
21904+# generate Latex output.
21905+
21906+GENERATE_LATEX         = NO
21907+
21908+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
21909+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
21910+# put in front of it. If left blank `latex' will be used as the default path.
21911+
21912+LATEX_OUTPUT           = latex
21913+
21914+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
21915+# invoked. If left blank `latex' will be used as the default command name.
21916+
21917+LATEX_CMD_NAME         = latex
21918+
21919+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
21920+# generate index for LaTeX. If left blank `makeindex' will be used as the
21921+# default command name.
21922+
21923+MAKEINDEX_CMD_NAME     = makeindex
21924+
21925+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
21926+# LaTeX documents. This may be useful for small projects and may help to
21927+# save some trees in general.
21928+
21929+COMPACT_LATEX          = NO
21930+
21931+# The PAPER_TYPE tag can be used to set the paper type that is used
21932+# by the printer. Possible values are: a4, a4wide, letter, legal and
21933+# executive. If left blank a4wide will be used.
21934+
21935+PAPER_TYPE             = a4wide
21936+
21937+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
21938+# packages that should be included in the LaTeX output.
21939+
21940+EXTRA_PACKAGES         =
21941+
21942+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
21943+# the generated latex document. The header should contain everything until
21944+# the first chapter. If it is left blank doxygen will generate a
21945+# standard header. Notice: only use this tag if you know what you are doing!
21946+
21947+LATEX_HEADER           =
21948+
21949+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
21950+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
21951+# contain links (just like the HTML output) instead of page references
21952+# This makes the output suitable for online browsing using a pdf viewer.
21953+
21954+PDF_HYPERLINKS         = YES
21955+
21956+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
21957+# plain latex in the generated Makefile. Set this option to YES to get a
21958+# higher quality PDF documentation.
21959+
21960+USE_PDFLATEX           = YES
21961+
21962+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
21963+# command to the generated LaTeX files. This will instruct LaTeX to keep
21964+# running if errors occur, instead of asking the user for help.
21965+# This option is also used when generating formulas in HTML.
21966+
21967+LATEX_BATCHMODE        = NO
21968+
21969+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
21970+# include the index chapters (such as File Index, Compound Index, etc.)
21971+# in the output.
21972+
21973+LATEX_HIDE_INDICES     = NO
21974+
21975+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
21976+# source code with syntax highlighting in the LaTeX output.
21977+# Note that which sources are shown also depends on other settings
21978+# such as SOURCE_BROWSER.
21979+
21980+LATEX_SOURCE_CODE      = NO
21981+
21982+#---------------------------------------------------------------------------
21983+# configuration options related to the RTF output
21984+#---------------------------------------------------------------------------
21985+
21986+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
21987+# The RTF output is optimized for Word 97 and may not look very pretty with
21988+# other RTF readers or editors.
21989+
21990+GENERATE_RTF           = NO
21991+
21992+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
21993+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
21994+# put in front of it. If left blank `rtf' will be used as the default path.
21995+
21996+RTF_OUTPUT             = rtf
21997+
21998+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
21999+# RTF documents. This may be useful for small projects and may help to
22000+# save some trees in general.
22001+
22002+COMPACT_RTF            = NO
22003+
22004+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
22005+# will contain hyperlink fields. The RTF file will
22006+# contain links (just like the HTML output) instead of page references.
22007+# This makes the output suitable for online browsing using WORD or other
22008+# programs which support those fields.
22009+# Note: wordpad (write) and others do not support links.
22010+
22011+RTF_HYPERLINKS         = NO
22012+
22013+# Load stylesheet definitions from file. Syntax is similar to doxygen's
22014+# config file, i.e. a series of assignments. You only have to provide
22015+# replacements, missing definitions are set to their default value.
22016+
22017+RTF_STYLESHEET_FILE    =
22018+
22019+# Set optional variables used in the generation of an rtf document.
22020+# Syntax is similar to doxygen's config file.
22021+
22022+RTF_EXTENSIONS_FILE    =
22023+
22024+#---------------------------------------------------------------------------
22025+# configuration options related to the man page output
22026+#---------------------------------------------------------------------------
22027+
22028+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
22029+# generate man pages
22030+
22031+GENERATE_MAN           = NO
22032+
22033+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
22034+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
22035+# put in front of it. If left blank `man' will be used as the default path.
22036+
22037+MAN_OUTPUT             = man
22038+
22039+# The MAN_EXTENSION tag determines the extension that is added to
22040+# the generated man pages (default is the subroutine's section .3)
22041+
22042+MAN_EXTENSION          = .3
22043+
22044+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
22045+# then it will generate one additional man file for each entity
22046+# documented in the real man page(s). These additional files
22047+# only source the real man page, but without them the man command
22048+# would be unable to find the correct page. The default is NO.
22049+
22050+MAN_LINKS              = NO
22051+
22052+#---------------------------------------------------------------------------
22053+# configuration options related to the XML output
22054+#---------------------------------------------------------------------------
22055+
22056+# If the GENERATE_XML tag is set to YES Doxygen will
22057+# generate an XML file that captures the structure of
22058+# the code including all documentation.
22059+
22060+GENERATE_XML           = NO
22061+
22062+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
22063+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
22064+# put in front of it. If left blank `xml' will be used as the default path.
22065+
22066+XML_OUTPUT             = xml
22067+
22068+# The XML_SCHEMA tag can be used to specify an XML schema,
22069+# which can be used by a validating XML parser to check the
22070+# syntax of the XML files.
22071+
22072+XML_SCHEMA             =
22073+
22074+# The XML_DTD tag can be used to specify an XML DTD,
22075+# which can be used by a validating XML parser to check the
22076+# syntax of the XML files.
22077+
22078+XML_DTD                =
22079+
22080+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
22081+# dump the program listings (including syntax highlighting
22082+# and cross-referencing information) to the XML output. Note that
22083+# enabling this will significantly increase the size of the XML output.
22084+
22085+XML_PROGRAMLISTING     = YES
22086+
22087+#---------------------------------------------------------------------------
22088+# configuration options for the AutoGen Definitions output
22089+#---------------------------------------------------------------------------
22090+
22091+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
22092+# generate an AutoGen Definitions (see autogen.sf.net) file
22093+# that captures the structure of the code including all
22094+# documentation. Note that this feature is still experimental
22095+# and incomplete at the moment.
22096+
22097+GENERATE_AUTOGEN_DEF   = NO
22098+
22099+#---------------------------------------------------------------------------
22100+# configuration options related to the Perl module output
22101+#---------------------------------------------------------------------------
22102+
22103+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
22104+# generate a Perl module file that captures the structure of
22105+# the code including all documentation. Note that this
22106+# feature is still experimental and incomplete at the
22107+# moment.
22108+
22109+GENERATE_PERLMOD       = NO
22110+
22111+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
22112+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
22113+# to generate PDF and DVI output from the Perl module output.
22114+
22115+PERLMOD_LATEX          = NO
22116+
22117+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
22118+# nicely formatted so it can be parsed by a human reader.  This is useful
22119+# if you want to understand what is going on.  On the other hand, if this
22120+# tag is set to NO the size of the Perl module output will be much smaller
22121+# and Perl will parse it just the same.
22122+
22123+PERLMOD_PRETTY         = YES
22124+
22125+# The names of the make variables in the generated doxyrules.make file
22126+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
22127+# This is useful so different doxyrules.make files included by the same
22128+# Makefile don't overwrite each other's variables.
22129+
22130+PERLMOD_MAKEVAR_PREFIX =
22131+
22132+#---------------------------------------------------------------------------
22133+# Configuration options related to the preprocessor
22134+#---------------------------------------------------------------------------
22135+
22136+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
22137+# evaluate all C-preprocessor directives found in the sources and include
22138+# files.
22139+
22140+ENABLE_PREPROCESSING   = YES
22141+
22142+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
22143+# names in the source code. If set to NO (the default) only conditional
22144+# compilation will be performed. Macro expansion can be done in a controlled
22145+# way by setting EXPAND_ONLY_PREDEF to YES.
22146+
22147+MACRO_EXPANSION        = NO
22148+
22149+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
22150+# then the macro expansion is limited to the macros specified with the
22151+# PREDEFINED and EXPAND_AS_DEFINED tags.
22152+
22153+EXPAND_ONLY_PREDEF     = NO
22154+
22155+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
22156+# in the INCLUDE_PATH (see below) will be search if a #include is found.
22157+
22158+SEARCH_INCLUDES        = YES
22159+
22160+# The INCLUDE_PATH tag can be used to specify one or more directories that
22161+# contain include files that are not input files but should be processed by
22162+# the preprocessor.
22163+
22164+INCLUDE_PATH           =
22165+
22166+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
22167+# patterns (like *.h and *.hpp) to filter out the header-files in the
22168+# directories. If left blank, the patterns specified with FILE_PATTERNS will
22169+# be used.
22170+
22171+INCLUDE_FILE_PATTERNS  =
22172+
22173+# The PREDEFINED tag can be used to specify one or more macro names that
22174+# are defined before the preprocessor is started (similar to the -D option of
22175+# gcc). The argument of the tag is a list of macros of the form: name
22176+# or name=definition (no spaces). If the definition and the = are
22177+# omitted =1 is assumed. To prevent a macro definition from being
22178+# undefined via #undef or recursively expanded use the := operator
22179+# instead of the = operator.
22180+
22181+PREDEFINED             =
22182+
22183+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
22184+# this tag can be used to specify a list of macro names that should be expanded.
22185+# The macro definition that is found in the sources will be used.
22186+# Use the PREDEFINED tag if you want to use a different macro definition.
22187+
22188+EXPAND_AS_DEFINED      =
22189+
22190+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
22191+# doxygen's preprocessor will remove all function-like macros that are alone
22192+# on a line, have an all uppercase name, and do not end with a semicolon. Such
22193+# function macros are typically used for boiler-plate code, and will confuse
22194+# the parser if not removed.
22195+
22196+SKIP_FUNCTION_MACROS   = YES
22197+
22198+#---------------------------------------------------------------------------
22199+# Configuration::additions related to external references
22200+#---------------------------------------------------------------------------
22201+
22202+# The TAGFILES option can be used to specify one or more tagfiles.
22203+# Optionally an initial location of the external documentation
22204+# can be added for each tagfile. The format of a tag file without
22205+# this location is as follows:
22206+#   TAGFILES = file1 file2 ...
22207+# Adding location for the tag files is done as follows:
22208+#   TAGFILES = file1=loc1 "file2 = loc2" ...
22209+# where "loc1" and "loc2" can be relative or absolute paths or
22210+# URLs. If a location is present for each tag, the installdox tool
22211+# does not have to be run to correct the links.
22212+# Note that each tag file must have a unique name
22213+# (where the name does NOT include the path)
22214+# If a tag file is not located in the directory in which doxygen
22215+# is run, you must also specify the path to the tagfile here.
22216+
22217+TAGFILES               =
22218+
22219+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
22220+# a tag file that is based on the input files it reads.
22221+
22222+GENERATE_TAGFILE       =
22223+
22224+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
22225+# in the class index. If set to NO only the inherited external classes
22226+# will be listed.
22227+
22228+ALLEXTERNALS           = NO
22229+
22230+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
22231+# in the modules index. If set to NO, only the current project's groups will
22232+# be listed.
22233+
22234+EXTERNAL_GROUPS        = YES
22235+
22236+# The PERL_PATH should be the absolute path and name of the perl script
22237+# interpreter (i.e. the result of `which perl').
22238+
22239+PERL_PATH              = /usr/bin/perl
22240+
22241+#---------------------------------------------------------------------------
22242+# Configuration options related to the dot tool
22243+#---------------------------------------------------------------------------
22244+
22245+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
22246+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
22247+# or super classes. Setting the tag to NO turns the diagrams off. Note that
22248+# this option is superseded by the HAVE_DOT option below. This is only a
22249+# fallback. It is recommended to install and use dot, since it yields more
22250+# powerful graphs.
22251+
22252+CLASS_DIAGRAMS         = YES
22253+
22254+# You can define message sequence charts within doxygen comments using the \msc
22255+# command. Doxygen will then run the mscgen tool (see
22256+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
22257+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
22258+# the mscgen tool resides. If left empty the tool is assumed to be found in the
22259+# default search path.
22260+
22261+MSCGEN_PATH            =
22262+
22263+# If set to YES, the inheritance and collaboration graphs will hide
22264+# inheritance and usage relations if the target is undocumented
22265+# or is not a class.
22266+
22267+HIDE_UNDOC_RELATIONS   = YES
22268+
22269+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
22270+# available from the path. This tool is part of Graphviz, a graph visualization
22271+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
22272+# have no effect if this option is set to NO (the default)
22273+
22274+HAVE_DOT               = NO
22275+
22276+# By default doxygen will write a font called FreeSans.ttf to the output
22277+# directory and reference it in all dot files that doxygen generates. This
22278+# font does not include all possible unicode characters however, so when you need
22279+# these (or just want a differently looking font) you can specify the font name
22280+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
22281+# which can be done by putting it in a standard location or by setting the
22282+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
22283+# containing the font.
22284+
22285+DOT_FONTNAME           = FreeSans
22286+
22287+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
22288+# The default size is 10pt.
22289+
22290+DOT_FONTSIZE           = 10
22291+
22292+# By default doxygen will tell dot to use the output directory to look for the
22293+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
22294+# different font using DOT_FONTNAME you can set the path where dot
22295+# can find it using this tag.
22296+
22297+DOT_FONTPATH           =
22298+
22299+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
22300+# will generate a graph for each documented class showing the direct and
22301+# indirect inheritance relations. Setting this tag to YES will force the
22302+# the CLASS_DIAGRAMS tag to NO.
22303+
22304+CLASS_GRAPH            = YES
22305+
22306+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
22307+# will generate a graph for each documented class showing the direct and
22308+# indirect implementation dependencies (inheritance, containment, and
22309+# class references variables) of the class with other documented classes.
22310+
22311+COLLABORATION_GRAPH    = YES
22312+
22313+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
22314+# will generate a graph for groups, showing the direct groups dependencies
22315+
22316+GROUP_GRAPHS           = YES
22317+
22318+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
22319+# collaboration diagrams in a style similar to the OMG's Unified Modeling
22320+# Language.
22321+
22322+UML_LOOK               = NO
22323+
22324+# If set to YES, the inheritance and collaboration graphs will show the
22325+# relations between templates and their instances.
22326+
22327+TEMPLATE_RELATIONS     = NO
22328+
22329+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
22330+# tags are set to YES then doxygen will generate a graph for each documented
22331+# file showing the direct and indirect include dependencies of the file with
22332+# other documented files.
22333+
22334+INCLUDE_GRAPH          = YES
22335+
22336+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
22337+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
22338+# documented header file showing the documented files that directly or
22339+# indirectly include this file.
22340+
22341+INCLUDED_BY_GRAPH      = YES
22342+
22343+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
22344+# doxygen will generate a call dependency graph for every global function
22345+# or class method. Note that enabling this option will significantly increase
22346+# the time of a run. So in most cases it will be better to enable call graphs
22347+# for selected functions only using the \callgraph command.
22348+
22349+CALL_GRAPH             = NO
22350+
22351+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
22352+# doxygen will generate a caller dependency graph for every global function
22353+# or class method. Note that enabling this option will significantly increase
22354+# the time of a run. So in most cases it will be better to enable caller
22355+# graphs for selected functions only using the \callergraph command.
22356+
22357+CALLER_GRAPH           = NO
22358+
22359+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
22360+# will graphical hierarchy of all classes instead of a textual one.
22361+
22362+GRAPHICAL_HIERARCHY    = YES
22363+
22364+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
22365+# then doxygen will show the dependencies a directory has on other directories
22366+# in a graphical way. The dependency relations are determined by the #include
22367+# relations between the files in the directories.
22368+
22369+DIRECTORY_GRAPH        = YES
22370+
22371+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
22372+# generated by dot. Possible values are png, jpg, or gif
22373+# If left blank png will be used.
22374+
22375+DOT_IMAGE_FORMAT       = png
22376+
22377+# The tag DOT_PATH can be used to specify the path where the dot tool can be
22378+# found. If left blank, it is assumed the dot tool can be found in the path.
22379+
22380+DOT_PATH               =
22381+
22382+# The DOTFILE_DIRS tag can be used to specify one or more directories that
22383+# contain dot files that are included in the documentation (see the
22384+# \dotfile command).
22385+
22386+DOTFILE_DIRS           =
22387+
22388+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
22389+# nodes that will be shown in the graph. If the number of nodes in a graph
22390+# becomes larger than this value, doxygen will truncate the graph, which is
22391+# visualized by representing a node as a red box. Note that doxygen if the
22392+# number of direct children of the root node in a graph is already larger than
22393+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
22394+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
22395+
22396+DOT_GRAPH_MAX_NODES    = 50
22397+
22398+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
22399+# graphs generated by dot. A depth value of 3 means that only nodes reachable
22400+# from the root by following a path via at most 3 edges will be shown. Nodes
22401+# that lay further from the root node will be omitted. Note that setting this
22402+# option to 1 or 2 may greatly reduce the computation time needed for large
22403+# code bases. Also note that the size of a graph can be further restricted by
22404+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
22405+
22406+MAX_DOT_GRAPH_DEPTH    = 0
22407+
22408+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
22409+# background. This is disabled by default, because dot on Windows does not
22410+# seem to support this out of the box. Warning: Depending on the platform used,
22411+# enabling this option may lead to badly anti-aliased labels on the edges of
22412+# a graph (i.e. they become hard to read).
22413+
22414+DOT_TRANSPARENT        = NO
22415+
22416+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
22417+# files in one run (i.e. multiple -o and -T options on the command line). This
22418+# makes dot run faster, but since only newer versions of dot (>1.8.10)
22419+# support this, this feature is disabled by default.
22420+
22421+DOT_MULTI_TARGETS      = NO
22422+
22423+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
22424+# generate a legend page explaining the meaning of the various boxes and
22425+# arrows in the dot generated graphs.
22426+
22427+GENERATE_LEGEND        = YES
22428+
22429+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
22430+# remove the intermediate dot files that are used to generate
22431+# the various graphs.
22432+
22433+DOT_CLEANUP            = YES
22434diff --git a/benchmark/feature_stab/src/dbreg/dbreg.cpp b/benchmark/feature_stab/src/dbreg/dbreg.cpp
22435new file mode 100644
22436index 00000000..986e255e
22437--- /dev/null
22438+++ b/benchmark/feature_stab/src/dbreg/dbreg.cpp
22439@@ -0,0 +1,793 @@
22440+/*
22441+ * Copyright (C) 2011 The Android Open Source Project
22442+ *
22443+ * Licensed under the Apache License, Version 2.0 (the "License");
22444+ * you may not use this file except in compliance with the License.
22445+ * You may obtain a copy of the License at
22446+ *
22447+ *      http://www.apache.org/licenses/LICENSE-2.0
22448+ *
22449+ * Unless required by applicable law or agreed to in writing, software
22450+ * distributed under the License is distributed on an "AS IS" BASIS,
22451+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22452+ * See the License for the specific language governing permissions and
22453+ * limitations under the License.
22454+ */
22455+
22456+// $Id: dbreg.cpp,v 1.31 2011/06/17 14:04:32 mbansal Exp $
22457+#include "dbreg.h"
22458+#include <string.h>
22459+#include <stdio.h>
22460+
22461+
22462+#if PROFILE
22463+#endif
22464+
22465+//#include <iostream>
22466+
22467+db_FrameToReferenceRegistration::db_FrameToReferenceRegistration() :
22468+  m_initialized(false),m_nr_matches(0),m_over_allocation(256),m_nr_bins(20),m_max_cost_pix(30), m_quarter_resolution(false)
22469+{
22470+  m_reference_image = NULL;
22471+  m_aligned_ins_image = NULL;
22472+
22473+  m_quarter_res_image = NULL;
22474+  m_horz_smooth_subsample_image = NULL;
22475+
22476+  m_x_corners_ref = NULL;
22477+  m_y_corners_ref = NULL;
22478+
22479+  m_x_corners_ins = NULL;
22480+  m_y_corners_ins = NULL;
22481+
22482+  m_match_index_ref = NULL;
22483+  m_match_index_ins = NULL;
22484+
22485+  m_inlier_indices = NULL;
22486+
22487+  m_num_inlier_indices = 0;
22488+
22489+  m_temp_double = NULL;
22490+  m_temp_int = NULL;
22491+
22492+  m_corners_ref = NULL;
22493+  m_corners_ins = NULL;
22494+
22495+  m_sq_cost = NULL;
22496+  m_cost_histogram = NULL;
22497+
22498+  profile_string = NULL;
22499+
22500+  db_Identity3x3(m_K);
22501+  db_Identity3x3(m_H_ref_to_ins);
22502+  db_Identity3x3(m_H_dref_to_ref);
22503+
22504+  m_sq_cost_computed = false;
22505+  m_reference_set = false;
22506+
22507+  m_reference_update_period = 0;
22508+  m_nr_frames_processed = 0;
22509+
22510+  return;
22511+}
22512+
22513+db_FrameToReferenceRegistration::~db_FrameToReferenceRegistration()
22514+{
22515+  Clean();
22516+}
22517+
22518+void db_FrameToReferenceRegistration::Clean()
22519+{
22520+  if ( m_reference_image )
22521+    db_FreeImage_u(m_reference_image,m_im_height);
22522+
22523+  if ( m_aligned_ins_image )
22524+    db_FreeImage_u(m_aligned_ins_image,m_im_height);
22525+
22526+  if ( m_quarter_res_image )
22527+  {
22528+    db_FreeImage_u(m_quarter_res_image, m_im_height);
22529+  }
22530+
22531+  if ( m_horz_smooth_subsample_image )
22532+  {
22533+    db_FreeImage_u(m_horz_smooth_subsample_image, m_im_height*2);
22534+  }
22535+
22536+  delete [] m_x_corners_ref;
22537+  delete [] m_y_corners_ref;
22538+
22539+  delete [] m_x_corners_ins;
22540+  delete [] m_y_corners_ins;
22541+
22542+  delete [] m_match_index_ref;
22543+  delete [] m_match_index_ins;
22544+
22545+  delete [] m_temp_double;
22546+  delete [] m_temp_int;
22547+
22548+  delete [] m_corners_ref;
22549+  delete [] m_corners_ins;
22550+
22551+  delete [] m_sq_cost;
22552+  delete [] m_cost_histogram;
22553+
22554+  delete [] m_inlier_indices;
22555+
22556+  if(profile_string)
22557+    delete [] profile_string;
22558+
22559+  m_reference_image = NULL;
22560+  m_aligned_ins_image = NULL;
22561+
22562+  m_quarter_res_image = NULL;
22563+  m_horz_smooth_subsample_image = NULL;
22564+
22565+  m_x_corners_ref = NULL;
22566+  m_y_corners_ref = NULL;
22567+
22568+  m_x_corners_ins = NULL;
22569+  m_y_corners_ins = NULL;
22570+
22571+  m_match_index_ref = NULL;
22572+  m_match_index_ins = NULL;
22573+
22574+  m_inlier_indices = NULL;
22575+
22576+  m_temp_double = NULL;
22577+  m_temp_int = NULL;
22578+
22579+  m_corners_ref = NULL;
22580+  m_corners_ins = NULL;
22581+
22582+  m_sq_cost = NULL;
22583+  m_cost_histogram = NULL;
22584+}
22585+
22586+void db_FrameToReferenceRegistration::Init(int width, int height,
22587+                       int    homography_type,
22588+                       int    max_iterations,
22589+                       bool   linear_polish,
22590+                       bool   quarter_resolution,
22591+                       double scale,
22592+                       unsigned int reference_update_period,
22593+                       bool   do_motion_smoothing,
22594+                       double motion_smoothing_gain,
22595+                       int    nr_samples,
22596+                       int    chunk_size,
22597+                       int    cd_target_nr_corners,
22598+                       double cm_max_disparity,
22599+                           bool   cm_use_smaller_matching_window,
22600+                       int    cd_nr_horz_blocks,
22601+                       int    cd_nr_vert_blocks
22602+                       )
22603+{
22604+  Clean();
22605+
22606+  m_reference_update_period = reference_update_period;
22607+  m_nr_frames_processed = 0;
22608+
22609+  m_do_motion_smoothing = do_motion_smoothing;
22610+  m_motion_smoothing_gain = motion_smoothing_gain;
22611+
22612+  m_stab_smoother.setSmoothingFactor(m_motion_smoothing_gain);
22613+
22614+  m_quarter_resolution = quarter_resolution;
22615+
22616+  profile_string = new char[10240];
22617+
22618+  if (m_quarter_resolution == true)
22619+  {
22620+    width = width/2;
22621+    height = height/2;
22622+
22623+    m_horz_smooth_subsample_image = db_AllocImage_u(width,height*2,m_over_allocation);
22624+    m_quarter_res_image = db_AllocImage_u(width,height,m_over_allocation);
22625+  }
22626+
22627+  m_im_width = width;
22628+  m_im_height = height;
22629+
22630+  double temp[9];
22631+  db_Approx3DCalMat(m_K,temp,m_im_width,m_im_height);
22632+
22633+  m_homography_type = homography_type;
22634+  m_max_iterations = max_iterations;
22635+  m_scale = 2/(m_K[0]+m_K[4]);
22636+  m_nr_samples = nr_samples;
22637+  m_chunk_size = chunk_size;
22638+
22639+  double outlier_t1 = 5.0;
22640+
22641+  m_outlier_t2 = outlier_t1*outlier_t1;//*m_scale*m_scale;
22642+
22643+  m_current_is_reference = false;
22644+
22645+  m_linear_polish = linear_polish;
22646+
22647+  m_reference_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation);
22648+  m_aligned_ins_image = db_AllocImage_u(m_im_width,m_im_height,m_over_allocation);
22649+
22650+  // initialize feature detection and matching:
22651+  //m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,0.0,0.0);
22652+  m_max_nr_corners = m_cd.Init(m_im_width,m_im_height,cd_target_nr_corners,cd_nr_horz_blocks,cd_nr_vert_blocks,DB_DEFAULT_ABS_CORNER_THRESHOLD/500.0,0.0);
22653+
22654+    int use_21 = 0;
22655+  m_max_nr_matches = m_cm.Init(m_im_width,m_im_height,cm_max_disparity,m_max_nr_corners,DB_DEFAULT_NO_DISPARITY,cm_use_smaller_matching_window,use_21);
22656+
22657+  // allocate space for corner feature locations for reference and inspection images:
22658+  m_x_corners_ref = new double [m_max_nr_corners];
22659+  m_y_corners_ref = new double [m_max_nr_corners];
22660+
22661+  m_x_corners_ins = new double [m_max_nr_corners];
22662+  m_y_corners_ins = new double [m_max_nr_corners];
22663+
22664+  // allocate space for match indices:
22665+  m_match_index_ref = new int [m_max_nr_matches];
22666+  m_match_index_ins = new int [m_max_nr_matches];
22667+
22668+  m_temp_double = new double [12*DB_DEFAULT_NR_SAMPLES+10*m_max_nr_matches];
22669+  m_temp_int = new int [db_maxi(DB_DEFAULT_NR_SAMPLES,m_max_nr_matches)];
22670+
22671+  // allocate space for homogenous image points:
22672+  m_corners_ref = new double [3*m_max_nr_corners];
22673+  m_corners_ins = new double [3*m_max_nr_corners];
22674+
22675+  // allocate cost array and histogram:
22676+  m_sq_cost = new double [m_max_nr_matches];
22677+  m_cost_histogram = new int [m_nr_bins];
22678+
22679+  // reserve array:
22680+  //m_inlier_indices.reserve(m_max_nr_matches);
22681+  m_inlier_indices = new int[m_max_nr_matches];
22682+
22683+  m_initialized = true;
22684+
22685+  m_max_inlier_count = 0;
22686+}
22687+
22688+
22689+#define MB 0
22690+// Save the reference image, detect features and update the dref-to-ref transformation
22691+int db_FrameToReferenceRegistration::UpdateReference(const unsigned char * const * im, bool subsample, bool detect_corners)
22692+{
22693+  double temp[9];
22694+  db_Multiply3x3_3x3(temp,m_H_dref_to_ref,m_H_ref_to_ins);
22695+  db_Copy9(m_H_dref_to_ref,temp);
22696+
22697+  const unsigned char * const * imptr = im;
22698+
22699+  if (m_quarter_resolution && subsample)
22700+  {
22701+    GenerateQuarterResImage(im);
22702+    imptr = m_quarter_res_image;
22703+  }
22704+
22705+  // save the reference image, detect features and quit
22706+  db_CopyImage_u(m_reference_image,imptr,m_im_width,m_im_height,m_over_allocation);
22707+
22708+  if(detect_corners)
22709+  {
22710+    #if MB
22711+    m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref);
22712+    int nr = 0;
22713+    for(int k=0; k<m_nr_corners_ref; k++)
22714+    {
22715+        if(m_x_corners_ref[k]>m_im_width/3)
22716+        {
22717+            m_x_corners_ref[nr] = m_x_corners_ref[k];
22718+            m_y_corners_ref[nr] = m_y_corners_ref[k];
22719+            nr++;
22720+        }
22721+
22722+    }
22723+    m_nr_corners_ref = nr;
22724+    #else
22725+    m_cd.DetectCorners(imptr, m_x_corners_ref,m_y_corners_ref,&m_nr_corners_ref);
22726+    #endif
22727+  }
22728+  else
22729+  {
22730+    m_nr_corners_ref = m_nr_corners_ins;
22731+
22732+    for(int k=0; k<m_nr_corners_ins; k++)
22733+    {
22734+        m_x_corners_ref[k] = m_x_corners_ins[k];
22735+        m_y_corners_ref[k] = m_y_corners_ins[k];
22736+    }
22737+
22738+  }
22739+
22740+  db_Identity3x3(m_H_ref_to_ins);
22741+
22742+  m_max_inlier_count = 0;   // Reset to 0 as no inliers seen until now
22743+  m_sq_cost_computed = false;
22744+  m_reference_set = true;
22745+  m_current_is_reference = true;
22746+  return 1;
22747+}
22748+
22749+void db_FrameToReferenceRegistration::Get_H_dref_to_ref(double H[9])
22750+{
22751+  db_Copy9(H,m_H_dref_to_ref);
22752+}
22753+
22754+void db_FrameToReferenceRegistration::Get_H_dref_to_ins(double H[9])
22755+{
22756+  db_Multiply3x3_3x3(H,m_H_dref_to_ref,m_H_ref_to_ins);
22757+}
22758+
22759+void db_FrameToReferenceRegistration::Set_H_dref_to_ins(double H[9])
22760+{
22761+    double H_ins_to_ref[9];
22762+
22763+    db_Identity3x3(H_ins_to_ref);   // Ensure it has proper values
22764+    db_InvertAffineTransform(H_ins_to_ref,m_H_ref_to_ins);  // Invert to get ins to ref
22765+    db_Multiply3x3_3x3(m_H_dref_to_ref,H,H_ins_to_ref); // Update dref to ref using the input H from dref to ins
22766+}
22767+
22768+
22769+void db_FrameToReferenceRegistration::ResetDisplayReference()
22770+{
22771+  db_Identity3x3(m_H_dref_to_ref);
22772+}
22773+
22774+bool db_FrameToReferenceRegistration::NeedReferenceUpdate()
22775+{
22776+  // If less than 50% of the starting number of inliers left, then its time to update the reference.
22777+  if(m_max_inlier_count>0 && float(m_num_inlier_indices)/float(m_max_inlier_count)<0.5)
22778+    return true;
22779+  else
22780+    return false;
22781+}
22782+
22783+int db_FrameToReferenceRegistration::AddFrame(const unsigned char * const * im, double H[9],bool force_reference,bool prewarp)
22784+{
22785+  m_current_is_reference = false;
22786+  if(!m_reference_set || force_reference)
22787+    {
22788+      db_Identity3x3(m_H_ref_to_ins);
22789+      db_Copy9(H,m_H_ref_to_ins);
22790+
22791+      UpdateReference(im,true,true);
22792+      return 0;
22793+    }
22794+
22795+  const unsigned char * const * imptr = im;
22796+
22797+  if (m_quarter_resolution)
22798+  {
22799+    if (m_quarter_res_image)
22800+    {
22801+      GenerateQuarterResImage(im);
22802+    }
22803+
22804+    imptr = (const unsigned char * const* )m_quarter_res_image;
22805+  }
22806+
22807+  double H_last[9];
22808+  db_Copy9(H_last,m_H_ref_to_ins);
22809+  db_Identity3x3(m_H_ref_to_ins);
22810+
22811+  m_sq_cost_computed = false;
22812+
22813+  // detect corners on inspection image and match to reference image features:s
22814+
22815+  // @jke - Adding code to time the functions.  TODO: Remove after test
22816+#if PROFILE
22817+  double iTimer1, iTimer2;
22818+  char str[255];
22819+  strcpy(profile_string,"\n");
22820+  sprintf(str,"[%dx%d] %p\n",m_im_width,m_im_height,im);
22821+  strcat(profile_string, str);
22822+#endif
22823+
22824+  // @jke - Adding code to time the functions.  TODO: Remove after test
22825+#if PROFILE
22826+  iTimer1 = now_ms();
22827+#endif
22828+  m_cd.DetectCorners(imptr, m_x_corners_ins,m_y_corners_ins,&m_nr_corners_ins);
22829+  // @jke - Adding code to time the functions.  TODO: Remove after test
22830+# if PROFILE
22831+  iTimer2 = now_ms();
22832+  double elapsedTimeCorner = iTimer2 - iTimer1;
22833+  sprintf(str,"Corner Detection [%d corners] = %g ms\n",m_nr_corners_ins, elapsedTimeCorner);
22834+  strcat(profile_string, str);
22835+#endif
22836+
22837+  // @jke - Adding code to time the functions.  TODO: Remove after test
22838+#if PROFILE
22839+  iTimer1 = now_ms();
22840+#endif
22841+    if(prewarp)
22842+  m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref,
22843+         m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins,
22844+         m_match_index_ref,m_match_index_ins,&m_nr_matches,H,0);
22845+    else
22846+  m_cm.Match(m_reference_image,imptr,m_x_corners_ref,m_y_corners_ref,m_nr_corners_ref,
22847+         m_x_corners_ins,m_y_corners_ins,m_nr_corners_ins,
22848+         m_match_index_ref,m_match_index_ins,&m_nr_matches);
22849+  // @jke - Adding code to time the functions.  TODO: Remove after test
22850+# if PROFILE
22851+  iTimer2 = now_ms();
22852+  double elapsedTimeMatch = iTimer2 - iTimer1;
22853+  sprintf(str,"Matching [%d] = %g ms\n",m_nr_matches,elapsedTimeMatch);
22854+  strcat(profile_string, str);
22855+#endif
22856+
22857+
22858+  // copy out matching features:
22859+  for ( int i = 0; i < m_nr_matches; ++i )
22860+    {
22861+      int offset = 3*i;
22862+      m_corners_ref[offset  ] = m_x_corners_ref[m_match_index_ref[i]];
22863+      m_corners_ref[offset+1] = m_y_corners_ref[m_match_index_ref[i]];
22864+      m_corners_ref[offset+2] = 1.0;
22865+
22866+      m_corners_ins[offset  ] = m_x_corners_ins[m_match_index_ins[i]];
22867+      m_corners_ins[offset+1] = m_y_corners_ins[m_match_index_ins[i]];
22868+      m_corners_ins[offset+2] = 1.0;
22869+    }
22870+
22871+  // @jke - Adding code to time the functions.  TODO: Remove after test
22872+#if PROFILE
22873+  iTimer1 = now_ms();
22874+#endif
22875+  // perform the alignment:
22876+  db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int,
22877+            m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale,
22878+            m_nr_samples, m_chunk_size);
22879+  // @jke - Adding code to time the functions.  TODO: Remove after test
22880+# if PROFILE
22881+  iTimer2 = now_ms();
22882+  double elapsedTimeHomography = iTimer2 - iTimer1;
22883+  sprintf(str,"Homography = %g ms\n",elapsedTimeHomography);
22884+  strcat(profile_string, str);
22885+#endif
22886+
22887+
22888+  SetOutlierThreshold();
22889+
22890+  // Compute the inliers for the db compute m_H_ref_to_ins
22891+  ComputeInliers(m_H_ref_to_ins);
22892+
22893+  // Update the max inlier count
22894+  m_max_inlier_count = (m_max_inlier_count > m_num_inlier_indices)?m_max_inlier_count:m_num_inlier_indices;
22895+
22896+  // Fit a least-squares model to just the inliers and put it in m_H_ref_to_ins
22897+  if(m_linear_polish)
22898+    Polish(m_inlier_indices, m_num_inlier_indices);
22899+
22900+  if (m_quarter_resolution)
22901+  {
22902+    m_H_ref_to_ins[2] *= 2.0;
22903+    m_H_ref_to_ins[5] *= 2.0;
22904+  }
22905+
22906+#if PROFILE
22907+  sprintf(str,"#Inliers = %d \n",m_num_inlier_indices);
22908+  strcat(profile_string, str);
22909+#endif
22910+/*
22911+  ///// CHECK IF CURRENT TRANSFORMATION GOOD OR BAD ////
22912+  ///// IF BAD, then update reference to the last correctly aligned inspection frame;
22913+  if(m_num_inlier_indices<5)//0.9*m_nr_matches || m_nr_matches < 20)
22914+  {
22915+    db_Copy9(m_H_ref_to_ins,H_last);
22916+    UpdateReference(imptr,false);
22917+//  UpdateReference(m_aligned_ins_image,false);
22918+  }
22919+  else
22920+  {
22921+  ///// IF GOOD, then update the last correctly aligned inspection frame to be this;
22922+  //db_CopyImage_u(m_aligned_ins_image,imptr,m_im_width,m_im_height,m_over_allocation);
22923+*/
22924+  if(m_do_motion_smoothing)
22925+    SmoothMotion();
22926+
22927+   // Disable debug printing
22928+   // db_PrintDoubleMatrix(m_H_ref_to_ins,3,3);
22929+
22930+  db_Copy9(H, m_H_ref_to_ins);
22931+
22932+  m_nr_frames_processed++;
22933+{
22934+  if ( (m_nr_frames_processed % m_reference_update_period) == 0 )
22935+  {
22936+    //UpdateReference(imptr,false, false);
22937+
22938+    #if MB
22939+    UpdateReference(imptr,false, true);
22940+    #else
22941+    UpdateReference(imptr,false, false);
22942+    #endif
22943+  }
22944+
22945+
22946+  }
22947+
22948+
22949+
22950+  return 1;
22951+}
22952+
22953+//void db_FrameToReferenceRegistration::ComputeInliers(double H[9],std::vector<int> &inlier_indices)
22954+void db_FrameToReferenceRegistration::ComputeInliers(double H[9])
22955+{
22956+  double totnummatches = m_nr_matches;
22957+  int inliercount=0;
22958+
22959+  m_num_inlier_indices = 0;
22960+//  inlier_indices.clear();
22961+
22962+  for(int c=0; c < totnummatches; c++ )
22963+    {
22964+      if (m_sq_cost[c] <= m_outlier_t2)
22965+    {
22966+      m_inlier_indices[inliercount] = c;
22967+      inliercount++;
22968+    }
22969+    }
22970+
22971+  m_num_inlier_indices = inliercount;
22972+}
22973+
22974+//void db_FrameToReferenceRegistration::Polish(std::vector<int> &inlier_indices)
22975+void db_FrameToReferenceRegistration::Polish(int *inlier_indices, int &num_inlier_indices)
22976+{
22977+  db_Zero(m_polish_C,36);
22978+  db_Zero(m_polish_D,6);
22979+  for (int i=0;i<num_inlier_indices;i++)
22980+    {
22981+      int j = 3*inlier_indices[i];
22982+      m_polish_C[0]+=m_corners_ref[j]*m_corners_ref[j];
22983+      m_polish_C[1]+=m_corners_ref[j]*m_corners_ref[j+1];
22984+      m_polish_C[2]+=m_corners_ref[j];
22985+      m_polish_C[7]+=m_corners_ref[j+1]*m_corners_ref[j+1];
22986+      m_polish_C[8]+=m_corners_ref[j+1];
22987+      m_polish_C[14]+=1;
22988+      m_polish_D[0]+=m_corners_ref[j]*m_corners_ins[j];
22989+      m_polish_D[1]+=m_corners_ref[j+1]*m_corners_ins[j];
22990+      m_polish_D[2]+=m_corners_ins[j];
22991+      m_polish_D[3]+=m_corners_ref[j]*m_corners_ins[j+1];
22992+      m_polish_D[4]+=m_corners_ref[j+1]*m_corners_ins[j+1];
22993+      m_polish_D[5]+=m_corners_ins[j+1];
22994+    }
22995+
22996+  double a=db_maxd(m_polish_C[0],m_polish_C[7]);
22997+  m_polish_C[0]/=a; m_polish_C[1]/=a;   m_polish_C[2]/=a;
22998+  m_polish_C[7]/=a; m_polish_C[8]/=a; m_polish_C[14]/=a;
22999+
23000+  m_polish_D[0]/=a; m_polish_D[1]/=a;   m_polish_D[2]/=a;
23001+  m_polish_D[3]/=a; m_polish_D[4]/=a;   m_polish_D[5]/=a;
23002+
23003+
23004+  m_polish_C[6]=m_polish_C[1];
23005+  m_polish_C[12]=m_polish_C[2];
23006+  m_polish_C[13]=m_polish_C[8];
23007+
23008+  m_polish_C[21]=m_polish_C[0]; m_polish_C[22]=m_polish_C[1]; m_polish_C[23]=m_polish_C[2];
23009+  m_polish_C[28]=m_polish_C[7]; m_polish_C[29]=m_polish_C[8];
23010+  m_polish_C[35]=m_polish_C[14];
23011+
23012+
23013+  double d[6];
23014+  db_CholeskyDecomp6x6(m_polish_C,d);
23015+  db_CholeskyBacksub6x6(m_H_ref_to_ins,m_polish_C,d,m_polish_D);
23016+}
23017+
23018+void db_FrameToReferenceRegistration::EstimateSecondaryModel(double H[9])
23019+{
23020+  /*      if ( m_current_is_reference )
23021+      {
23022+      db_Identity3x3(H);
23023+      return;
23024+      }
23025+  */
23026+
23027+  // select the outliers of the current model:
23028+  SelectOutliers();
23029+
23030+  // perform the alignment:
23031+  db_RobImageHomography(m_H_ref_to_ins, m_corners_ref, m_corners_ins, m_nr_matches, m_K, m_K, m_temp_double, m_temp_int,
23032+            m_homography_type,NULL,m_max_iterations,m_max_nr_matches,m_scale,
23033+            m_nr_samples, m_chunk_size);
23034+
23035+  db_Copy9(H,m_H_ref_to_ins);
23036+}
23037+
23038+void db_FrameToReferenceRegistration::ComputeCostArray()
23039+{
23040+  if ( m_sq_cost_computed ) return;
23041+
23042+  for( int c=0, k=0 ;c < m_nr_matches; c++, k=k+3)
23043+    {
23044+      m_sq_cost[c] = SquaredInhomogenousHomographyError(m_corners_ins+k,m_H_ref_to_ins,m_corners_ref+k);
23045+    }
23046+
23047+  m_sq_cost_computed = true;
23048+}
23049+
23050+void db_FrameToReferenceRegistration::SelectOutliers()
23051+{
23052+  int nr_outliers=0;
23053+
23054+  ComputeCostArray();
23055+
23056+  for(int c=0, k=0 ;c<m_nr_matches;c++,k=k+3)
23057+    {
23058+      if (m_sq_cost[c] > m_outlier_t2)
23059+    {
23060+      int offset = 3*nr_outliers++;
23061+      db_Copy3(m_corners_ref+offset,m_corners_ref+k);
23062+      db_Copy3(m_corners_ins+offset,m_corners_ins+k);
23063+    }
23064+    }
23065+
23066+  m_nr_matches = nr_outliers;
23067+}
23068+
23069+void db_FrameToReferenceRegistration::ComputeCostHistogram()
23070+{
23071+  ComputeCostArray();
23072+
23073+  for ( int b = 0; b < m_nr_bins; ++b )
23074+    m_cost_histogram[b] = 0;
23075+
23076+  for(int c = 0; c < m_nr_matches; c++)
23077+    {
23078+      double error = db_SafeSqrt(m_sq_cost[c]);
23079+      int bin = (int)(error/m_max_cost_pix*m_nr_bins);
23080+      if ( bin < m_nr_bins )
23081+    m_cost_histogram[bin]++;
23082+      else
23083+    m_cost_histogram[m_nr_bins-1]++;
23084+    }
23085+
23086+/*
23087+  for ( int i = 0; i < m_nr_bins; ++i )
23088+    std::cout << m_cost_histogram[i] << " ";
23089+  std::cout << std::endl;
23090+*/
23091+}
23092+
23093+void db_FrameToReferenceRegistration::SetOutlierThreshold()
23094+{
23095+  ComputeCostHistogram();
23096+
23097+  int i = 0, last=0;
23098+  for (; i < m_nr_bins-1; ++i )
23099+    {
23100+      if ( last > m_cost_histogram[i] )
23101+    break;
23102+      last = m_cost_histogram[i];
23103+    }
23104+
23105+  //std::cout << "I " <<  i << std::endl;
23106+
23107+  int max = m_cost_histogram[i];
23108+
23109+  for (; i < m_nr_bins-1; ++i )
23110+    {
23111+      if ( m_cost_histogram[i] < (int)(0.1*max) )
23112+    //if ( last < m_cost_histogram[i] )
23113+    break;
23114+      last = m_cost_histogram[i];
23115+    }
23116+  //std::cout << "J " <<  i << std::endl;
23117+
23118+  m_outlier_t2 = db_sqr(i*m_max_cost_pix/m_nr_bins);
23119+
23120+  //std::cout << "m_outlier_t2 " <<  m_outlier_t2 << std::endl;
23121+}
23122+
23123+void db_FrameToReferenceRegistration::SmoothMotion(void)
23124+{
23125+  VP_MOTION inmot,outmot;
23126+
23127+  double H[9];
23128+
23129+  Get_H_dref_to_ins(H);
23130+
23131+      MXX(inmot) = H[0];
23132+    MXY(inmot) = H[1];
23133+    MXZ(inmot) = H[2];
23134+    MXW(inmot) = 0.0;
23135+
23136+    MYX(inmot) = H[3];
23137+    MYY(inmot) = H[4];
23138+    MYZ(inmot) = H[5];
23139+    MYW(inmot) = 0.0;
23140+
23141+    MZX(inmot) = H[6];
23142+    MZY(inmot) = H[7];
23143+    MZZ(inmot) = H[8];
23144+    MZW(inmot) = 0.0;
23145+
23146+    MWX(inmot) = 0.0;
23147+    MWY(inmot) = 0.0;
23148+    MWZ(inmot) = 0.0;
23149+    MWW(inmot) = 1.0;
23150+
23151+    inmot.type = VP_MOTION_AFFINE;
23152+
23153+    int w = m_im_width;
23154+    int h = m_im_height;
23155+
23156+    if(m_quarter_resolution)
23157+    {
23158+    w = w*2;
23159+    h = h*2;
23160+    }
23161+
23162+#if 0
23163+    m_stab_smoother.smoothMotionAdaptive(w,h,&inmot,&outmot);
23164+#else
23165+    m_stab_smoother.smoothMotion(&inmot,&outmot);
23166+#endif
23167+
23168+    H[0] = MXX(outmot);
23169+    H[1] = MXY(outmot);
23170+    H[2] = MXZ(outmot);
23171+
23172+    H[3] = MYX(outmot);
23173+    H[4] = MYY(outmot);
23174+    H[5] = MYZ(outmot);
23175+
23176+    H[6] = MZX(outmot);
23177+    H[7] = MZY(outmot);
23178+    H[8] = MZZ(outmot);
23179+
23180+    Set_H_dref_to_ins(H);
23181+}
23182+
23183+void db_FrameToReferenceRegistration::GenerateQuarterResImage(const unsigned char* const* im)
23184+{
23185+  int input_h = m_im_height*2;
23186+  int input_w = m_im_width*2;
23187+
23188+  for (int j = 0; j < input_h; j++)
23189+  {
23190+    const unsigned char* in_row_ptr = im[j];
23191+    unsigned char* out_row_ptr = m_horz_smooth_subsample_image[j]+1;
23192+
23193+    for (int i = 2; i < input_w-2; i += 2)
23194+    {
23195+      int smooth_val = (
23196+            6*in_row_ptr[i] +
23197+            ((in_row_ptr[i-1]+in_row_ptr[i+1])<<2) +
23198+            in_row_ptr[i-2]+in_row_ptr[i+2]
23199+            ) >> 4;
23200+      *out_row_ptr++ = (unsigned char) smooth_val;
23201+
23202+      if ( (smooth_val < 0) || (smooth_val > 255))
23203+      {
23204+        return;
23205+      }
23206+
23207+    }
23208+  }
23209+
23210+  for (int j = 2; j < input_h-2; j+=2)
23211+  {
23212+
23213+    unsigned char* in_row_ptr = m_horz_smooth_subsample_image[j];
23214+    unsigned char* out_row_ptr = m_quarter_res_image[j/2];
23215+
23216+    for (int i = 1; i < m_im_width-1; i++)
23217+    {
23218+      int smooth_val = (
23219+            6*in_row_ptr[i] +
23220+            ((in_row_ptr[i-m_im_width]+in_row_ptr[i+m_im_width]) << 2)+
23221+            in_row_ptr[i-2*m_im_width]+in_row_ptr[i+2*m_im_width]
23222+            ) >> 4;
23223+      *out_row_ptr++ = (unsigned char)smooth_val;
23224+
23225+      if ( (smooth_val < 0) || (smooth_val > 255))
23226+      {
23227+        return;
23228+      }
23229+
23230+    }
23231+  }
23232+}
23233diff --git a/benchmark/feature_stab/src/dbreg/dbreg.h b/benchmark/feature_stab/src/dbreg/dbreg.h
23234new file mode 100644
23235index 00000000..4eb24448
23236--- /dev/null
23237+++ b/benchmark/feature_stab/src/dbreg/dbreg.h
23238@@ -0,0 +1,581 @@
23239+/*
23240+ * Copyright (C) 2011 The Android Open Source Project
23241+ *
23242+ * Licensed under the Apache License, Version 2.0 (the "License");
23243+ * you may not use this file except in compliance with the License.
23244+ * You may obtain a copy of the License at
23245+ *
23246+ *      http://www.apache.org/licenses/LICENSE-2.0
23247+ *
23248+ * Unless required by applicable law or agreed to in writing, software
23249+ * distributed under the License is distributed on an "AS IS" BASIS,
23250+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23251+ * See the License for the specific language governing permissions and
23252+ * limitations under the License.
23253+ */
23254+
23255+
23256+#pragma once
23257+
23258+#ifdef _WIN32
23259+#ifdef DBREG_EXPORTS
23260+#define DBREG_API __declspec(dllexport)
23261+#else
23262+#define DBREG_API __declspec(dllimport)
23263+#endif
23264+#else
23265+#define DBREG_API
23266+#endif
23267+
23268+// @jke - the next few lines are for extracting timing data.  TODO: Remove after test
23269+#define PROFILE 0
23270+
23271+#include "dbstabsmooth.h"
23272+
23273+#include <db_feature_detection.h>
23274+#include <db_feature_matching.h>
23275+#include <db_rob_image_homography.h>
23276+
23277+#if PROFILE
23278+    #include <sys/time.h>
23279+#endif
23280+
23281+/*! \mainpage db_FrameToReferenceRegistration
23282+
23283+ \section intro Introduction
23284+
23285+ db_FrameToReferenceRegistration provides a simple interface to a set of sophisticated algorithms for stabilizing
23286+ video sequences.  As its name suggests, the class is used to compute parameters that will allow us to warp incoming video
23287+ frames and register them with respect to a so-called <i>reference</i> frame.  The reference frame is simply the first
23288+ frame of a sequence; the registration process is that of estimating the parameters of a warp that can be applied to
23289+ subsequent frames to make those frames align with the reference.  A video made up of these warped frames will be more
23290+ stable than the input video.
23291+
23292+ For more technical information on the internal structure of the algorithms used within the db_FrameToRegistration class,
23293+ please follow this <a href="../Sarnoff image registration.docx">link</a>.
23294+
23295+ \section usage Usage
23296+ In addition to the class constructor, there are two main functions of db_FrameToReferenceRegistration that are of
23297+ interest to the programmer.  db_FrameToReferenceRegistration::Init(...) is used to initialize the parameters of the
23298+ registration algorithm. db_FrameToReferenceRegistration::AddFrame(...) is the method by which each new video frame
23299+ is introduced to the registration algorithm, and produces the estimated registration warp parameters.
23300+
23301+ The following example illustrates how the major methods of the class db_FrameToReferenceRegistration can be used together
23302+ to calculate the registration parameters for an image sequence.  In the example, the calls to the methods of
23303+ db_FrameToReferenceRegistration match those found in the API, but supporting code should be considered pseudo-code.
23304+ For a more complete example, please consult the source code for dbregtest.
23305+
23306+
23307+    \code
23308+    // feature-based image registration class:
23309+    db_FrameToReferenceRegistration reg;
23310+
23311+    // Image data
23312+    const unsigned char * const * image_storage;
23313+
23314+    // The 3x3 frame to reference registration parameters
23315+    double frame_to_ref_homography[9];
23316+
23317+    // a counter to count the number of frames processed.
23318+    unsigned long frame_counter;
23319+    // ...
23320+
23321+    // main loop - keep going while there are images to process.
23322+    while (ImagesAreAvailable)
23323+    {
23324+        // Call functions to place latest data into image_storage
23325+        // ...
23326+
23327+        // if the registration object is not yet initialized, then do so
23328+        // The arguments to this function are explained in the accompanying
23329+        // html API documentation
23330+        if (!reg.Initialized())
23331+        {
23332+            reg.Init(w,h,motion_model_type,25,linear_polish,quarter_resolution,
23333+                   DB_POINT_STANDARDDEV,reference_update_period,
23334+                   do_motion_smoothing,motion_smoothing_gain,
23335+                   DB_DEFAULT_NR_SAMPLES,DB_DEFAULT_CHUNK_SIZE,
23336+                   nr_corners,max_disparity);
23337+        }
23338+
23339+        // Present the new image data to the registration algorithm,
23340+        // with the result being stored in the frame_to_ref_homography
23341+        // variable.
23342+        reg.AddFrame(image_storage,frame_to_ref_homography);
23343+
23344+        // frame_to_ref_homography now contains the stabilizing transform
23345+        // use this to warp the latest image for display, etc.
23346+
23347+        // if this is the first frame, we need to tell the registration
23348+        // class to store the image as its reference.  Otherwise, AddFrame
23349+        // takes care of that.
23350+        if (frame_counter == 0)
23351+        {
23352+            reg.UpdateReference(image_storage);
23353+        }
23354+
23355+        // increment the frame counter
23356+        frame_counter++;
23357+    }
23358+
23359+    \endcode
23360+
23361+ */
23362+
23363+/*!
23364+ * Performs feature-based frame to reference image registration.
23365+ */
23366+class DBREG_API db_FrameToReferenceRegistration
23367+{
23368+public:
23369+    db_FrameToReferenceRegistration(void);
23370+    ~db_FrameToReferenceRegistration();
23371+
23372+    /*!
23373+     * Set parameters and allocate memory. Note: The default values of these parameters have been set to the values used for the android implementation (i.e. the demo APK).
23374+     * \param width         image width
23375+     * \param height        image height
23376+     * \param homography_type see definitions in \ref LMRobImageHomography
23377+     * \param max_iterations    max number of polishing steps
23378+     * \param linear_polish     whether to perform a linear polishing step after RANSAC
23379+     * \param quarter_resolution    whether to process input images at quarter resolution (for computational efficiency)
23380+     * \param scale         Cauchy scale coefficient (see db_ExpCauchyReprojectionError() )
23381+     * \param reference_update_period   how often to update the alignment reference (in units of number of frames)
23382+     * \param do_motion_smoothing   whether to perform display reference smoothing
23383+     * \param motion_smoothing_gain weight factor to reflect how fast the display reference must follow the current frame if motion smoothing is enabled
23384+     * \param nr_samples        number of times to compute a hypothesis
23385+     * \param chunk_size        size of cost chunks
23386+     * \param cd_target_nr_corners  target number of corners for corner detector
23387+     * \param cm_max_disparity      maximum disparity search range for corner matcher (in units of ratio of image width)
23388+     * \param cm_use_smaller_matching_window    if set to true, uses a correlation window of 5x5 instead of the default 11x11
23389+     * \param cd_nr_horz_blocks     the number of horizontal blocks for the corner detector to partition the image
23390+     * \param cd_nr_vert_blocks     the number of vertical blocks for the corner detector to partition the image
23391+    */
23392+    void Init(int width, int height,
23393+          int       homography_type = DB_HOMOGRAPHY_TYPE_DEFAULT,
23394+          int       max_iterations = DB_DEFAULT_MAX_ITERATIONS,
23395+          bool      linear_polish = false,
23396+          bool   quarter_resolution = true,
23397+          double  scale = DB_POINT_STANDARDDEV,
23398+          unsigned int reference_update_period = 3,
23399+          bool   do_motion_smoothing = false,
23400+          double motion_smoothing_gain = 0.75,
23401+          int   nr_samples = DB_DEFAULT_NR_SAMPLES,
23402+          int   chunk_size = DB_DEFAULT_CHUNK_SIZE,
23403+          int    cd_target_nr_corners = 500,
23404+          double cm_max_disparity = 0.2,
23405+          bool   cm_use_smaller_matching_window = false,
23406+          int    cd_nr_horz_blocks = 5,
23407+          int    cd_nr_vert_blocks = 5);
23408+
23409+    /*!
23410+     * Reset the transformation type that is being use to perform alignment. Use this to change the alignment type at run time.
23411+     * \param homography_type   the type of transformation to use for performing alignment (see definitions in \ref LMRobImageHomography)
23412+    */
23413+    void ResetHomographyType(int homography_type) { m_homography_type = homography_type; }
23414+
23415+    /*!
23416+     * Enable/Disable motion smoothing. Use this to turn motion smoothing on/off at run time.
23417+     * \param enable    flag indicating whether to turn the motion smoothing on or off.
23418+    */
23419+    void ResetSmoothing(bool enable) { m_do_motion_smoothing = enable; }
23420+
23421+    /*!
23422+     * Align an inspection image to an existing reference image, update the reference image if due and perform motion smoothing if enabled.
23423+     * \param im                new inspection image
23424+     * \param H             computed transformation from reference to inspection coordinate frame. Identity is returned if no reference frame was set.
23425+     * \param force_reference   make this the new reference image
23426+     */
23427+    int AddFrame(const unsigned char * const * im, double H[9], bool force_reference=false, bool prewarp=false);
23428+
23429+    /*!
23430+     * Returns true if Init() was run.
23431+     */
23432+    bool Initialized() const { return m_initialized; }
23433+
23434+    /*!
23435+     * Returns true if the current frame is being used as the alignment reference.
23436+    */
23437+    bool IsCurrentReference() const { return m_current_is_reference; }
23438+
23439+    /*!
23440+     * Returns true if we need to call UpdateReference now.
23441+     */
23442+    bool NeedReferenceUpdate();
23443+
23444+    /*!
23445+     * Returns the pointer reference to the alignment reference image data
23446+    */
23447+    unsigned char ** GetReferenceImage() { return m_reference_image; }
23448+
23449+    /*!
23450+     * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched reference image corners.
23451+    */
23452+    double * GetRefCorners() { return m_corners_ref; }
23453+    /*!
23454+     * Returns the pointer reference to the double array containing the homogeneous coordinates for the matched inspection image corners.
23455+    */
23456+    double * GetInsCorners() { return m_corners_ins; }
23457+    /*!
23458+     * Returns the number of correspondences between the reference and inspection images.
23459+    */
23460+    int GetNrMatches() { return m_nr_matches; }
23461+
23462+    /*!
23463+     * Returns the number of corners detected in the current reference image.
23464+    */
23465+    int GetNrRefCorners() { return m_nr_corners_ref; }
23466+
23467+    /*!
23468+     * Returns the pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists.
23469+    */
23470+    int* GetInliers() { return m_inlier_indices; }
23471+
23472+    /*!
23473+     * Returns the number of inliers from the RANSAC matching step.
23474+    */
23475+    int  GetNrInliers() { return m_num_inlier_indices; }
23476+
23477+    //std::vector<int>& GetInliers();
23478+    //void Polish(std::vector<int> &inlier_indices);
23479+
23480+    /*!
23481+     * Perform a linear polishing step by re-estimating the alignment transformation using the RANSAC inliers.
23482+     * \param inlier_indices    pointer to an array of indices that were found to be RANSAC inliers from the matched corner lists.
23483+     * \param num_inlier_indices    number of inliers i.e. the length of the array passed as the first argument.
23484+    */
23485+    void Polish(int *inlier_indices, int &num_inlier_indices);
23486+
23487+    /*!
23488+     * Reset the motion smoothing parameters to their initial values.
23489+    */
23490+    void ResetMotionSmoothingParameters() { m_stab_smoother.Init(); }
23491+
23492+    /*!
23493+     * Update the alignment reference image to the specified image.
23494+     * \param im    pointer to the image data to be used as the new alignment reference.
23495+     * \param subsample boolean flag to control whether the function should internally subsample the provided image to the size provided in the Init() function.
23496+    */
23497+    int UpdateReference(const unsigned char * const * im, bool subsample = true, bool detect_corners = true);
23498+
23499+    /*!
23500+     * Returns the transformation from the display reference to the alignment reference frame
23501+    */
23502+    void Get_H_dref_to_ref(double H[9]);
23503+    /*!
23504+     * Returns the transformation from the display reference to the inspection reference frame
23505+    */
23506+    void Get_H_dref_to_ins(double H[9]);
23507+    /*!
23508+     * Set the transformation from the display reference to the inspection reference frame
23509+     * \param H the transformation to set
23510+    */
23511+    void Set_H_dref_to_ins(double H[9]);
23512+
23513+    /*!
23514+     * Reset the display reference to the current frame.
23515+    */
23516+    void ResetDisplayReference();
23517+
23518+    /*!
23519+     * Estimate a secondary motion model starting from the specified transformation.
23520+     * \param H the primary motion model to start from
23521+    */
23522+    void EstimateSecondaryModel(double H[9]);
23523+
23524+    /*!
23525+     *
23526+    */
23527+    void SelectOutliers();
23528+
23529+    char *profile_string;
23530+
23531+protected:
23532+    void Clean();
23533+    void GenerateQuarterResImage(const unsigned char* const * im);
23534+
23535+    int     m_im_width;
23536+    int     m_im_height;
23537+
23538+    // RANSAC and refinement parameters:
23539+    int m_homography_type;
23540+    int     m_max_iterations;
23541+    double  m_scale;
23542+    int     m_nr_samples;
23543+    int     m_chunk_size;
23544+    double  m_outlier_t2;
23545+
23546+    // Whether to fit a linear model to just the inliers at the end
23547+    bool   m_linear_polish;
23548+    double m_polish_C[36];
23549+    double m_polish_D[6];
23550+
23551+    // local state
23552+    bool m_current_is_reference;
23553+    bool m_initialized;
23554+
23555+    // inspection to reference homography:
23556+    double m_H_ref_to_ins[9];
23557+    double m_H_dref_to_ref[9];
23558+
23559+    // feature extraction and matching:
23560+    db_CornerDetector_u m_cd;
23561+    db_Matcher_u        m_cm;
23562+
23563+    // length of corner arrays:
23564+    unsigned long m_max_nr_corners;
23565+
23566+    // corner locations of reference image features:
23567+    double * m_x_corners_ref;
23568+    double * m_y_corners_ref;
23569+    int  m_nr_corners_ref;
23570+
23571+    // corner locations of inspection image features:
23572+    double * m_x_corners_ins;
23573+    double * m_y_corners_ins;
23574+    int      m_nr_corners_ins;
23575+
23576+    // length of match index arrays:
23577+    unsigned long m_max_nr_matches;
23578+
23579+    // match indices:
23580+    int * m_match_index_ref;
23581+    int * m_match_index_ins;
23582+    int   m_nr_matches;
23583+
23584+    // pointer to internal copy of the reference image:
23585+    unsigned char ** m_reference_image;
23586+
23587+    // pointer to internal copy of last aligned inspection image:
23588+    unsigned char ** m_aligned_ins_image;
23589+
23590+    // pointer to quarter resolution image, if used.
23591+    unsigned char** m_quarter_res_image;
23592+
23593+    // temporary storage for the quarter resolution image processing
23594+    unsigned char** m_horz_smooth_subsample_image;
23595+
23596+    // temporary space for homography computation:
23597+    double * m_temp_double;
23598+    int * m_temp_int;
23599+
23600+    // homogenous image point arrays:
23601+    double * m_corners_ref;
23602+    double * m_corners_ins;
23603+
23604+    // Indices of the points within the match lists
23605+    int * m_inlier_indices;
23606+    int m_num_inlier_indices;
23607+
23608+    //void ComputeInliers(double H[9], std::vector<int> &inlier_indices);
23609+    void ComputeInliers(double H[9]);
23610+
23611+    // cost arrays:
23612+    void ComputeCostArray();
23613+    bool m_sq_cost_computed;
23614+    double * m_sq_cost;
23615+
23616+    // cost histogram:
23617+    void ComputeCostHistogram();
23618+    int *m_cost_histogram;
23619+
23620+    void SetOutlierThreshold();
23621+
23622+    // utility function for smoothing the motion parameters.
23623+    void SmoothMotion(void);
23624+
23625+private:
23626+    double m_K[9];
23627+    const int m_over_allocation;
23628+
23629+    bool m_reference_set;
23630+
23631+    // Maximum number of inliers seen until now w.r.t the current reference frame
23632+    int m_max_inlier_count;
23633+
23634+    // Number of cost histogram bins:
23635+    int m_nr_bins;
23636+    // All costs above this threshold get put into the last bin:
23637+    int m_max_cost_pix;
23638+
23639+    // whether to quarter the image resolution for processing, or not
23640+    bool m_quarter_resolution;
23641+
23642+    // the period (in number of frames) for reference update.
23643+    unsigned int m_reference_update_period;
23644+
23645+    // the number of frames processed so far.
23646+    unsigned int m_nr_frames_processed;
23647+
23648+    // smoother for motion transformations
23649+    db_StabilizationSmoother m_stab_smoother;
23650+
23651+    // boolean to control whether motion smoothing occurs (or not)
23652+    bool m_do_motion_smoothing;
23653+
23654+    // double to set the gain for motion smoothing
23655+    double m_motion_smoothing_gain;
23656+};
23657+/*!
23658+ Create look-up tables to undistort images. Only Bougeut (Matlab toolkit)
23659+ is currently supported. Can be used with db_WarpImageLut_u().
23660+ \code
23661+    xd = H*xs;
23662+    xd = xd/xd(3);
23663+ \endcode
23664+ \param lut_x   pre-allocated float image
23665+ \param lut_y   pre-allocated float image
23666+ \param w       width
23667+ \param h       height
23668+ \param H       image homography from source to destination
23669+ */
23670+inline void db_GenerateHomographyLut(float ** lut_x,float ** lut_y,int w,int h,const double H[9])
23671+{
23672+    assert(lut_x && lut_y);
23673+    double x[3] = {0.0,0.0,1.0};
23674+    double xb[3];
23675+
23676+/*
23677+    double xl[3];
23678+
23679+    // Determine the output coordinate system ROI
23680+    double Hinv[9];
23681+    db_InvertAffineTransform(Hinv,H);
23682+    db_Multiply3x3_3x1(xl, Hinv, x);
23683+    xl[0] = db_SafeDivision(xl[0],xl[2]);
23684+    xl[1] = db_SafeDivision(xl[1],xl[2]);
23685+*/
23686+
23687+    for ( int i = 0; i < w; ++i )
23688+        for ( int j = 0; j < h; ++j )
23689+        {
23690+            x[0] = double(i);
23691+            x[1] = double(j);
23692+            db_Multiply3x3_3x1(xb, H, x);
23693+            xb[0] = db_SafeDivision(xb[0],xb[2]);
23694+            xb[1] = db_SafeDivision(xb[1],xb[2]);
23695+
23696+            lut_x[j][i] = float(xb[0]);
23697+            lut_y[j][i] = float(xb[1]);
23698+        }
23699+}
23700+
23701+/*!
23702+ * Perform a look-up table warp for packed RGB ([rgbrgbrgb...]) images.
23703+ * The LUTs must be float images of the same size as source image.
23704+ * The source value x_s is determined from destination (x_d,y_d) through lut_x
23705+ * and y_s is determined from lut_y:
23706+   \code
23707+   x_s = lut_x[y_d][x_d];
23708+   y_s = lut_y[y_d][x_d];
23709+   \endcode
23710+
23711+ * \param src   source image (w*3 by h)
23712+ * \param dst   destination image (w*3 by h)
23713+ * \param w     width
23714+ * \param h     height
23715+ * \param lut_x LUT for x
23716+ * \param lut_y LUT for y
23717+ */
23718+inline void db_WarpImageLutFast_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h,
23719+                                  const float * const * lut_x, const float * const * lut_y)
23720+{
23721+    assert(src && dst);
23722+    int xd=0, yd=0;
23723+
23724+    for ( int i = 0; i < w; ++i )
23725+        for ( int j = 0; j < h; ++j )
23726+        {
23727+            xd = static_cast<unsigned int>(lut_x[j][i]);
23728+            yd = static_cast<unsigned int>(lut_y[j][i]);
23729+            if ( xd >= w || yd >= h ||
23730+                 xd < 0 || yd < 0)
23731+            {
23732+                dst[j][3*i  ] = 0;
23733+                dst[j][3*i+1] = 0;
23734+                dst[j][3*i+2] = 0;
23735+            }
23736+            else
23737+            {
23738+                dst[j][3*i  ] = src[yd][3*xd  ];
23739+                dst[j][3*i+1] = src[yd][3*xd+1];
23740+                dst[j][3*i+2] = src[yd][3*xd+2];
23741+            }
23742+        }
23743+}
23744+
23745+inline unsigned char db_BilinearInterpolationRGB(double y, double x, const unsigned char * const * v, int offset)
23746+{
23747+         int floor_x=(int) x;
23748+         int floor_y=(int) y;
23749+
23750+         int ceil_x=floor_x+1;
23751+         int ceil_y=floor_y+1;
23752+
23753+         unsigned char f00 = v[floor_y][3*floor_x+offset];
23754+         unsigned char f01 = v[floor_y][3*ceil_x+offset];
23755+         unsigned char f10 = v[ceil_y][3*floor_x+offset];
23756+         unsigned char f11 = v[ceil_y][3*ceil_x+offset];
23757+
23758+         double xl = x-floor_x;
23759+         double yl = y-floor_y;
23760+
23761+         return (unsigned char)(f00*(1-yl)*(1-xl) + f10*yl*(1-xl) + f01*(1-yl)*xl + f11*yl*xl);
23762+}
23763+
23764+inline void db_WarpImageLutBilinear_rgb(const unsigned char * const * src, unsigned char ** dst, int w, int h,
23765+                                  const float * const * lut_x, const float * const * lut_y)
23766+{
23767+    assert(src && dst);
23768+    double xd=0.0, yd=0.0;
23769+
23770+    for ( int i = 0; i < w; ++i )
23771+        for ( int j = 0; j < h; ++j )
23772+        {
23773+            xd = static_cast<double>(lut_x[j][i]);
23774+            yd = static_cast<double>(lut_y[j][i]);
23775+            if ( xd > w-2 || yd > h-2 ||
23776+                 xd < 0.0 || yd < 0.0)
23777+            {
23778+                dst[j][3*i  ] = 0;
23779+                dst[j][3*i+1] = 0;
23780+                dst[j][3*i+2] = 0;
23781+            }
23782+            else
23783+            {
23784+                dst[j][3*i  ] = db_BilinearInterpolationRGB(yd,xd,src,0);
23785+                dst[j][3*i+1] = db_BilinearInterpolationRGB(yd,xd,src,1);
23786+                dst[j][3*i+2] = db_BilinearInterpolationRGB(yd,xd,src,2);
23787+            }
23788+        }
23789+}
23790+
23791+inline double SquaredInhomogenousHomographyError(double y[3],double H[9],double x[3]){
23792+    double x0,x1,x2,mult;
23793+    double sd;
23794+
23795+    x0=H[0]*x[0]+H[1]*x[1]+H[2];
23796+    x1=H[3]*x[0]+H[4]*x[1]+H[5];
23797+    x2=H[6]*x[0]+H[7]*x[1]+H[8];
23798+    mult=1.0/((x2!=0.0)?x2:1.0);
23799+    sd=(y[0]-x0*mult)*(y[0]-x0*mult)+(y[1]-x1*mult)*(y[1]-x1*mult);
23800+
23801+    return(sd);
23802+}
23803+
23804+
23805+// functions related to profiling
23806+#if PROFILE
23807+
23808+/* return current time in milliseconds */
23809+static double
23810+now_ms(void)
23811+{
23812+    //struct timespec res;
23813+    struct timeval res;
23814+    //clock_gettime(CLOCK_REALTIME, &res);
23815+    gettimeofday(&res, NULL);
23816+    return 1000.0*res.tv_sec + (double)res.tv_usec/1e3;
23817+}
23818+
23819+#endif
23820diff --git a/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp b/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp
23821new file mode 100644
23822index 00000000..03608c69
23823--- /dev/null
23824+++ b/benchmark/feature_stab/src/dbreg/dbstabsmooth.cpp
23825@@ -0,0 +1,301 @@
23826+/*
23827+ * Copyright (C) 2011 The Android Open Source Project
23828+ *
23829+ * Licensed under the Apache License, Version 2.0 (the "License");
23830+ * you may not use this file except in compliance with the License.
23831+ * You may obtain a copy of the License at
23832+ *
23833+ *      http://www.apache.org/licenses/LICENSE-2.0
23834+ *
23835+ * Unless required by applicable law or agreed to in writing, software
23836+ * distributed under the License is distributed on an "AS IS" BASIS,
23837+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23838+ * See the License for the specific language governing permissions and
23839+ * limitations under the License.
23840+ */
23841+
23842+#include <stdlib.h>
23843+#include "dbstabsmooth.h"
23844+
23845+///// TODO TODO ////////// Replace this with the actual definition from Jayan's reply /////////////
23846+#define vp_copy_motion_no_id vp_copy_motion
23847+///////////////////////////////////////////////////////////////////////////////////////////////////
23848+
23849+db_StabilizationSmoother::db_StabilizationSmoother()
23850+{
23851+    Init();
23852+}
23853+
23854+void db_StabilizationSmoother::Init()
23855+{
23856+    f_smoothOn = true;
23857+    f_smoothReset = false;
23858+    f_smoothFactor = 1.0f;
23859+    f_minDampingFactor = 0.2f;
23860+    f_zoom = 1.0f;
23861+    VP_MOTION_ID(f_motLF);
23862+    VP_MOTION_ID(f_imotLF);
23863+    f_hsize = 0;
23864+    f_vsize = 0;
23865+
23866+    VP_MOTION_ID(f_disp_mot);
23867+    VP_MOTION_ID(f_src_mot);
23868+    VP_MOTION_ID(f_diff_avg);
23869+
23870+    for( int i = 0; i < MOTION_ARRAY-1; i++) {
23871+        VP_MOTION_ID(f_hist_mot_speed[i]);
23872+        VP_MOTION_ID(f_hist_mot[i]);
23873+        VP_MOTION_ID(f_hist_diff_mot[i]);
23874+    }
23875+    VP_MOTION_ID(f_hist_mot[MOTION_ARRAY-1]);
23876+
23877+}
23878+
23879+db_StabilizationSmoother::~db_StabilizationSmoother()
23880+{}
23881+
23882+
23883+bool db_StabilizationSmoother::smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot)
23884+{
23885+    VP_MOTION_ID(f_motLF);
23886+    VP_MOTION_ID(f_imotLF);
23887+    f_motLF.insid = inmot->refid;
23888+    f_motLF.refid = inmot->insid;
23889+
23890+    if(f_smoothOn) {
23891+        if(!f_smoothReset) {
23892+            MXX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXX(f_motLF) + (1.0-f_smoothFactor)* (double) MXX(*inmot));
23893+            MXY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXY(f_motLF) + (1.0-f_smoothFactor)* (double) MXY(*inmot));
23894+            MXZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXZ(f_motLF) + (1.0-f_smoothFactor)* (double) MXZ(*inmot));
23895+            MXW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MXW(f_motLF) + (1.0-f_smoothFactor)* (double) MXW(*inmot));
23896+
23897+            MYX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYX(f_motLF) + (1.0-f_smoothFactor)* (double) MYX(*inmot));
23898+            MYY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYY(f_motLF) + (1.0-f_smoothFactor)* (double) MYY(*inmot));
23899+            MYZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYZ(f_motLF) + (1.0-f_smoothFactor)* (double) MYZ(*inmot));
23900+            MYW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MYW(f_motLF) + (1.0-f_smoothFactor)* (double) MYW(*inmot));
23901+
23902+            MZX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZX(f_motLF) + (1.0-f_smoothFactor)* (double) MZX(*inmot));
23903+            MZY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZY(f_motLF) + (1.0-f_smoothFactor)* (double) MZY(*inmot));
23904+            MZZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZZ(f_motLF) + (1.0-f_smoothFactor)* (double) MZZ(*inmot));
23905+            MZW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MZW(f_motLF) + (1.0-f_smoothFactor)* (double) MZW(*inmot));
23906+
23907+            MWX(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWX(f_motLF) + (1.0-f_smoothFactor)* (double) MWX(*inmot));
23908+            MWY(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWY(f_motLF) + (1.0-f_smoothFactor)* (double) MWY(*inmot));
23909+            MWZ(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWZ(f_motLF) + (1.0-f_smoothFactor)* (double) MWZ(*inmot));
23910+            MWW(f_motLF) = (VP_PAR) (f_smoothFactor*(double) MWW(f_motLF) + (1.0-f_smoothFactor)* (double) MWW(*inmot));
23911+        }
23912+        else
23913+            vp_copy_motion_no_id(inmot, &f_motLF); // f_smoothFactor = 0.0
23914+
23915+        // Only allow LF motion to be compensated. Remove HF motion from
23916+        // the output transformation
23917+        if(!vp_invert_motion(&f_motLF, &f_imotLF))
23918+            return false;
23919+
23920+        if(!vp_cascade_motion(&f_imotLF, inmot, outmot))
23921+            return false;
23922+    }
23923+    else {
23924+        vp_copy_motion_no_id(inmot, outmot);
23925+    }
23926+
23927+    return true;
23928+}
23929+
23930+bool db_StabilizationSmoother::smoothMotionAdaptive(/*VP_BIMG *bimg,*/int hsize, int vsize, VP_MOTION *inmot, VP_MOTION *outmot)
23931+{
23932+    VP_MOTION tmpMotion, testMotion;
23933+    VP_PAR p1x, p2x, p3x, p4x;
23934+    VP_PAR p1y, p2y, p3y, p4y;
23935+    double smoothFactor;
23936+    double minSmoothFactor = f_minDampingFactor;
23937+
23938+//  int hsize = bimg->w;
23939+//  int vsize = bimg->h;
23940+    double border_factor = 0.01;//0.2;
23941+    double border_x = border_factor * hsize;
23942+    double border_y = border_factor * vsize;
23943+
23944+    VP_MOTION_ID(f_motLF);
23945+    VP_MOTION_ID(f_imotLF);
23946+    VP_MOTION_ID(testMotion);
23947+    VP_MOTION_ID(tmpMotion);
23948+
23949+    if (f_smoothOn) {
23950+        VP_MOTION identityMotion;
23951+        VP_MOTION_ID(identityMotion); // initialize the motion
23952+        vp_copy_motion(inmot/*in*/, &testMotion/*out*/);
23953+        VP_PAR delta = vp_motion_cornerdiff(&testMotion, &identityMotion, 0, 0,(int)hsize, (int)vsize);
23954+
23955+        smoothFactor = 0.99 - 0.0015 * delta;
23956+
23957+        if(smoothFactor < minSmoothFactor)
23958+            smoothFactor = minSmoothFactor;
23959+
23960+        // Find the amount of motion that must be compensated so that no "border" pixels are seen in the stable video
23961+        for (; smoothFactor >= minSmoothFactor; smoothFactor -= 0.01) {
23962+            // Compute the smoothed motion
23963+            if(!smoothMotion(inmot, &tmpMotion, smoothFactor))
23964+                break;
23965+
23966+            // TmpMotion, or Qsi where s is the smoothed display reference and i is the
23967+            // current image, tells us how points in the S co-ordinate system map to
23968+            // points in the I CS.  We would like to check whether the four corners of the
23969+            // warped and smoothed display reference lies entirely within the I co-ordinate
23970+            // system.  If yes, then the amount of smoothing is sufficient so that NO
23971+            // border pixels are seen at the output.  We test for f_smoothFactor terms
23972+            // between 0.9 and 1.0, in steps of 0.01, and between 0.5 ands 0.9 in steps of 0.1
23973+
23974+            (void) vp_zoom_motion2d(&tmpMotion, &testMotion, 1, hsize, vsize, (double)f_zoom); // needs to return bool
23975+
23976+            VP_WARP_POINT_2D(0, 0, testMotion, p1x, p1y);
23977+            VP_WARP_POINT_2D(hsize - 1, 0, testMotion, p2x, p2y);
23978+            VP_WARP_POINT_2D(hsize - 1, vsize - 1, testMotion, p3x, p3y);
23979+            VP_WARP_POINT_2D(0, vsize - 1, testMotion, p4x, p4y);
23980+
23981+            if (!is_point_in_rect((double)p1x,(double)p1y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) {
23982+                continue;
23983+            }
23984+            if (!is_point_in_rect((double)p2x, (double)p2y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) {
23985+                continue;
23986+            }
23987+            if (!is_point_in_rect((double)p3x,(double)p3y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) {
23988+                continue;
23989+            }
23990+            if (!is_point_in_rect((double)p4x, (double)p4y,-border_x,-border_y,(double)(hsize+2.0*border_x),(double)(vsize+2.0*border_y))) {
23991+                continue;
23992+            }
23993+
23994+            // If we get here, then all the points are in the rectangle.
23995+            // Therefore, break out of this loop
23996+            break;
23997+        }
23998+
23999+        // if we get here and f_smoothFactor <= fMinDampingFactor, reset the stab reference
24000+        if (smoothFactor < f_minDampingFactor)
24001+            smoothFactor = f_minDampingFactor;
24002+
24003+        // use the smoothed motion for stabilization
24004+        vp_copy_motion_no_id(&tmpMotion/*in*/, outmot/*out*/);
24005+    }
24006+    else
24007+    {
24008+        vp_copy_motion_no_id(inmot, outmot);
24009+    }
24010+
24011+    return true;
24012+}
24013+
24014+bool db_StabilizationSmoother::smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot, double smooth_factor)
24015+{
24016+    f_motLF.insid = inmot->refid;
24017+    f_motLF.refid = inmot->insid;
24018+
24019+    if(f_smoothOn) {
24020+        if(!f_smoothReset) {
24021+            MXX(f_motLF) = (VP_PAR) (smooth_factor*(double) MXX(f_motLF) + (1.0-smooth_factor)* (double) MXX(*inmot));
24022+            MXY(f_motLF) = (VP_PAR) (smooth_factor*(double) MXY(f_motLF) + (1.0-smooth_factor)* (double) MXY(*inmot));
24023+            MXZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MXZ(f_motLF) + (1.0-smooth_factor)* (double) MXZ(*inmot));
24024+            MXW(f_motLF) = (VP_PAR) (smooth_factor*(double) MXW(f_motLF) + (1.0-smooth_factor)* (double) MXW(*inmot));
24025+
24026+            MYX(f_motLF) = (VP_PAR) (smooth_factor*(double) MYX(f_motLF) + (1.0-smooth_factor)* (double) MYX(*inmot));
24027+            MYY(f_motLF) = (VP_PAR) (smooth_factor*(double) MYY(f_motLF) + (1.0-smooth_factor)* (double) MYY(*inmot));
24028+            MYZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MYZ(f_motLF) + (1.0-smooth_factor)* (double) MYZ(*inmot));
24029+            MYW(f_motLF) = (VP_PAR) (smooth_factor*(double) MYW(f_motLF) + (1.0-smooth_factor)* (double) MYW(*inmot));
24030+
24031+            MZX(f_motLF) = (VP_PAR) (smooth_factor*(double) MZX(f_motLF) + (1.0-smooth_factor)* (double) MZX(*inmot));
24032+            MZY(f_motLF) = (VP_PAR) (smooth_factor*(double) MZY(f_motLF) + (1.0-smooth_factor)* (double) MZY(*inmot));
24033+            MZZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MZZ(f_motLF) + (1.0-smooth_factor)* (double) MZZ(*inmot));
24034+            MZW(f_motLF) = (VP_PAR) (smooth_factor*(double) MZW(f_motLF) + (1.0-smooth_factor)* (double) MZW(*inmot));
24035+
24036+            MWX(f_motLF) = (VP_PAR) (smooth_factor*(double) MWX(f_motLF) + (1.0-smooth_factor)* (double) MWX(*inmot));
24037+            MWY(f_motLF) = (VP_PAR) (smooth_factor*(double) MWY(f_motLF) + (1.0-smooth_factor)* (double) MWY(*inmot));
24038+            MWZ(f_motLF) = (VP_PAR) (smooth_factor*(double) MWZ(f_motLF) + (1.0-smooth_factor)* (double) MWZ(*inmot));
24039+            MWW(f_motLF) = (VP_PAR) (smooth_factor*(double) MWW(f_motLF) + (1.0-smooth_factor)* (double) MWW(*inmot));
24040+        }
24041+        else
24042+            vp_copy_motion_no_id(inmot, &f_motLF); // smooth_factor = 0.0
24043+
24044+        // Only allow LF motion to be compensated. Remove HF motion from
24045+        // the output transformation
24046+        if(!vp_invert_motion(&f_motLF, &f_imotLF))
24047+            return false;
24048+
24049+        if(!vp_cascade_motion(&f_imotLF, inmot, outmot))
24050+            return false;
24051+    }
24052+    else {
24053+        vp_copy_motion_no_id(inmot, outmot);
24054+    }
24055+
24056+    return true;
24057+}
24058+
24059+//! Overloaded smoother function that takes in user-specidied smoothing factor
24060+bool
24061+db_StabilizationSmoother::smoothMotion1(VP_MOTION *inmot, VP_MOTION *outmot, VP_MOTION *motLF, VP_MOTION *imotLF, double factor)
24062+{
24063+
24064+    if(!f_smoothOn) {
24065+        vp_copy_motion(inmot, outmot);
24066+        return true;
24067+    }
24068+    else {
24069+        if(!f_smoothReset) {
24070+            MXX(*motLF) = (VP_PAR) (factor*(double) MXX(*motLF) + (1.0-factor)* (double) MXX(*inmot));
24071+            MXY(*motLF) = (VP_PAR) (factor*(double) MXY(*motLF) + (1.0-factor)* (double) MXY(*inmot));
24072+            MXZ(*motLF) = (VP_PAR) (factor*(double) MXZ(*motLF) + (1.0-factor)* (double) MXZ(*inmot));
24073+            MXW(*motLF) = (VP_PAR) (factor*(double) MXW(*motLF) + (1.0-factor)* (double) MXW(*inmot));
24074+
24075+            MYX(*motLF) = (VP_PAR) (factor*(double) MYX(*motLF) + (1.0-factor)* (double) MYX(*inmot));
24076+            MYY(*motLF) = (VP_PAR) (factor*(double) MYY(*motLF) + (1.0-factor)* (double) MYY(*inmot));
24077+            MYZ(*motLF) = (VP_PAR) (factor*(double) MYZ(*motLF) + (1.0-factor)* (double) MYZ(*inmot));
24078+            MYW(*motLF) = (VP_PAR) (factor*(double) MYW(*motLF) + (1.0-factor)* (double) MYW(*inmot));
24079+
24080+            MZX(*motLF) = (VP_PAR) (factor*(double) MZX(*motLF) + (1.0-factor)* (double) MZX(*inmot));
24081+            MZY(*motLF) = (VP_PAR) (factor*(double) MZY(*motLF) + (1.0-factor)* (double) MZY(*inmot));
24082+            MZZ(*motLF) = (VP_PAR) (factor*(double) MZZ(*motLF) + (1.0-factor)* (double) MZZ(*inmot));
24083+            MZW(*motLF) = (VP_PAR) (factor*(double) MZW(*motLF) + (1.0-factor)* (double) MZW(*inmot));
24084+
24085+            MWX(*motLF) = (VP_PAR) (factor*(double) MWX(*motLF) + (1.0-factor)* (double) MWX(*inmot));
24086+            MWY(*motLF) = (VP_PAR) (factor*(double) MWY(*motLF) + (1.0-factor)* (double) MWY(*inmot));
24087+            MWZ(*motLF) = (VP_PAR) (factor*(double) MWZ(*motLF) + (1.0-factor)* (double) MWZ(*inmot));
24088+            MWW(*motLF) = (VP_PAR) (factor*(double) MWW(*motLF) + (1.0-factor)* (double) MWW(*inmot));
24089+        }
24090+        else {
24091+            vp_copy_motion(inmot, motLF);
24092+        }
24093+        // Only allow LF motion to be compensated. Remove HF motion from the output transformation
24094+        if(!vp_invert_motion(motLF, imotLF)) {
24095+#if DEBUG_PRINT
24096+            printfOS("Invert failed \n");
24097+#endif
24098+            return false;
24099+        }
24100+        if(!vp_cascade_motion(imotLF, inmot, outmot)) {
24101+#if DEBUG_PRINT
24102+            printfOS("cascade failed \n");
24103+#endif
24104+            return false;
24105+        }
24106+    }
24107+    return true;
24108+}
24109+
24110+
24111+
24112+
24113+bool db_StabilizationSmoother::is_point_in_rect(double px, double py, double rx, double ry, double w, double h)
24114+{
24115+    if (px < rx)
24116+        return(false);
24117+    if (px >= rx + w)
24118+        return(false);
24119+    if (py < ry)
24120+        return(false);
24121+    if (py >= ry + h)
24122+        return(false);
24123+
24124+    return(true);
24125+}
24126+
24127diff --git a/benchmark/feature_stab/src/dbreg/dbstabsmooth.h b/benchmark/feature_stab/src/dbreg/dbstabsmooth.h
24128new file mode 100644
24129index 00000000..f03546ef
24130--- /dev/null
24131+++ b/benchmark/feature_stab/src/dbreg/dbstabsmooth.h
24132@@ -0,0 +1,157 @@
24133+/*
24134+ * Copyright (C) 2011 The Android Open Source Project
24135+ *
24136+ * Licensed under the Apache License, Version 2.0 (the "License");
24137+ * you may not use this file except in compliance with the License.
24138+ * You may obtain a copy of the License at
24139+ *
24140+ *      http://www.apache.org/licenses/LICENSE-2.0
24141+ *
24142+ * Unless required by applicable law or agreed to in writing, software
24143+ * distributed under the License is distributed on an "AS IS" BASIS,
24144+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24145+ * See the License for the specific language governing permissions and
24146+ * limitations under the License.
24147+ */
24148+
24149+#pragma once
24150+
24151+
24152+#ifdef _WIN32
24153+#ifdef DBREG_EXPORTS
24154+#define DBREG_API __declspec(dllexport)
24155+#else
24156+#define DBREG_API __declspec(dllimport)
24157+#endif
24158+#else
24159+#define DBREG_API
24160+#endif
24161+
24162+extern "C" {
24163+#include "vp_motionmodel.h"
24164+}
24165+
24166+#define MOTION_ARRAY 5
24167+
24168+
24169+/*!
24170+ * Performs smoothing on the motion estimate from feature_stab.
24171+ */
24172+class DBREG_API db_StabilizationSmoother
24173+{
24174+public:
24175+    db_StabilizationSmoother();
24176+    ~db_StabilizationSmoother();
24177+
24178+    /*!
24179+     * Initialize parameters for stab-smoother.
24180+    */
24181+    void Init();
24182+
24183+    //! Smothing type
24184+    typedef enum {
24185+        SimpleSmooth = 0, //!< simple smooth
24186+        AdaptSmooth  = 1, //!< adaptive smooth
24187+        PanSmooth    = 2  //!< pan motion smooth
24188+    } SmoothType;
24189+
24190+    /*!
24191+     * Smooth-motion is to do a weight-average between the current affine and
24192+     * motLF. The way to change the affine is only for the display purpose.
24193+     * It removes the high frequency motion and keep the low frequency motion
24194+     * to the display. IIR implmentation.
24195+     * \param inmot input motion parameters
24196+     * \param outmot smoothed output motion parameters
24197+    */
24198+    bool smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot);
24199+
24200+    /*!
24201+     * The adaptive smoothing version of the above fixed smoothing function.
24202+     * \param hsize width of the image being aligned
24203+     * \param vsize height of the image being aligned
24204+     * \param inmot input motion parameters
24205+     * \param outmot    smoothed output motion parameters
24206+    */
24207+    bool smoothMotionAdaptive(/*VP_BIMG *bimg,*/int hsize, int vsize, VP_MOTION *inmot, VP_MOTION *outmot);
24208+    bool smoothPanMotion_1(VP_MOTION *inmot, VP_MOTION *outmot);
24209+    bool smoothPanMotion_2(VP_MOTION *inmot, VP_MOTION *outmot);
24210+
24211+    /*!
24212+    * Set the smoothing factor for the stab-smoother.
24213+    * \param factor the factor value to set
24214+    */
24215+    inline void setSmoothingFactor(float factor) { f_smoothFactor = factor; }
24216+
24217+    /*!
24218+     * Reset smoothing
24219+    */
24220+    inline void resetSmoothing(bool flag) { f_smoothReset = flag; }
24221+    /*!
24222+     * Set the zoom factor value.
24223+     * \param zoom  the value to set to
24224+    */
24225+    inline void setZoomFactor(float zoom) { f_zoom = zoom; }
24226+    /*!
24227+     * Set the minimum damping factor value.
24228+     * \param factor    the value to set to
24229+    */
24230+    inline void setminDampingFactor(float factor) { f_minDampingFactor = factor; }
24231+
24232+    /*!
24233+     * Returns the current smoothing factor.
24234+    */
24235+    inline float getSmoothingFactor(void) { return f_smoothFactor; }
24236+    /*!
24237+     * Returns the current zoom factor.
24238+    */
24239+    inline float getZoomFactor(void) { return f_zoom; }
24240+    /*!
24241+     * Returns the current minimum damping factor.
24242+    */
24243+    inline float getminDampingFactor(void) { return f_minDampingFactor; }
24244+    /*!
24245+     * Returns the current state of the smoothing reset flag.
24246+    */
24247+    inline bool  getSmoothReset(void) { return f_smoothReset; }
24248+    /*!
24249+     * Returns the current low frequency motion parameters.
24250+    */
24251+    inline VP_MOTION getMotLF(void) { return f_motLF; }
24252+    /*!
24253+     * Returns the inverse of the current low frequency motion parameters.
24254+    */
24255+    inline VP_MOTION getImotLF(void) { return f_imotLF; }
24256+    /*!
24257+     * Set the dimensions of the alignment image.
24258+     * \param hsize width of the image
24259+     * \param vsize height of the image
24260+    */
24261+    inline void setSize(int hsize, int vsize) { f_hsize = hsize; f_vsize = vsize; }
24262+
24263+protected:
24264+
24265+    bool smoothMotion(VP_MOTION *inmot, VP_MOTION *outmot, double smooth_factor);
24266+    bool smoothMotion1(VP_MOTION *inmot, VP_MOTION *outmot, VP_MOTION *motLF, VP_MOTION *imotLF, double smooth_factor);
24267+    void iterativeSmooth(VP_MOTION *input, VP_MOTION *output, double border_factor);
24268+    bool is_point_in_rect(double px, double py, double rx, double ry, double w, double h);
24269+
24270+
24271+private:
24272+    int f_hsize;
24273+    int f_vsize;
24274+    bool f_smoothOn;
24275+    bool f_smoothReset;
24276+    float f_smoothFactor;
24277+    float f_minDampingFactor;
24278+    float f_zoom;
24279+    VP_MOTION f_motLF;
24280+    VP_MOTION f_imotLF;
24281+    VP_MOTION f_hist_mot[MOTION_ARRAY];
24282+    VP_MOTION f_hist_mot_speed[MOTION_ARRAY-1];
24283+    VP_MOTION f_hist_diff_mot[MOTION_ARRAY-1];
24284+    VP_MOTION f_disp_mot;
24285+    VP_MOTION f_src_mot;
24286+    VP_MOTION f_diff_avg;
24287+
24288+};
24289+
24290diff --git a/benchmark/feature_stab/src/dbreg/targetver.h b/benchmark/feature_stab/src/dbreg/targetver.h
24291new file mode 100644
24292index 00000000..3ca3e879
24293--- /dev/null
24294+++ b/benchmark/feature_stab/src/dbreg/targetver.h
24295@@ -0,0 +1,40 @@
24296+/*
24297+ * Copyright (C) 2011 The Android Open Source Project
24298+ *
24299+ * Licensed under the Apache License, Version 2.0 (the "License");
24300+ * you may not use this file except in compliance with the License.
24301+ * You may obtain a copy of the License at
24302+ *
24303+ *      http://www.apache.org/licenses/LICENSE-2.0
24304+ *
24305+ * Unless required by applicable law or agreed to in writing, software
24306+ * distributed under the License is distributed on an "AS IS" BASIS,
24307+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24308+ * See the License for the specific language governing permissions and
24309+ * limitations under the License.
24310+ */
24311+
24312+#pragma once
24313+
24314+// The following macros define the minimum required platform.  The minimum required platform
24315+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
24316+// your application.  The macros work by enabling all features available on platform versions up to and
24317+// including the version specified.
24318+
24319+// Modify the following defines if you have to target a platform prior to the ones specified below.
24320+// Refer to MSDN for the latest info on corresponding values for different platforms.
24321+#ifndef WINVER                          // Specifies that the minimum required platform is Windows Vista.
24322+#define WINVER 0x0600           // Change this to the appropriate value to target other versions of Windows.
24323+#endif
24324+
24325+#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
24326+#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
24327+#endif
24328+
24329+#ifndef _WIN32_WINDOWS          // Specifies that the minimum required platform is Windows 98.
24330+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
24331+#endif
24332+
24333+#ifndef _WIN32_IE                       // Specifies that the minimum required platform is Internet Explorer 7.0.
24334+#define _WIN32_IE 0x0700        // Change this to the appropriate value to target other versions of IE.
24335+#endif
24336diff --git a/benchmark/feature_stab/src/dbreg/vp_motionmodel.c b/benchmark/feature_stab/src/dbreg/vp_motionmodel.c
24337new file mode 100644
24338index 00000000..1f6af15b
24339--- /dev/null
24340+++ b/benchmark/feature_stab/src/dbreg/vp_motionmodel.c
24341@@ -0,0 +1,377 @@
24342+/*
24343+ * Copyright (C) 2011 The Android Open Source Project
24344+ *
24345+ * Licensed under the Apache License, Version 2.0 (the "License");
24346+ * you may not use this file except in compliance with the License.
24347+ * You may obtain a copy of the License at
24348+ *
24349+ *      http://www.apache.org/licenses/LICENSE-2.0
24350+ *
24351+ * Unless required by applicable law or agreed to in writing, software
24352+ * distributed under the License is distributed on an "AS IS" BASIS,
24353+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24354+ * See the License for the specific language governing permissions and
24355+ * limitations under the License.
24356+ */
24357+
24358+/*
24359+#sourcefile  vpmotion/vp_motionmodel.c
24360+#category    motion-model
24361+*
24362+* Copyright 1998 Sarnoff Corporation
24363+* All Rights Reserved
24364+*
24365+* Modification History
24366+*      Date: 02/14/98
24367+*      Author: supuns
24368+*      Shop Order: 17xxx
24369+*              @(#) $Id: vp_motionmodel.c,v 1.4 2011/06/17 14:04:33 mbansal Exp $
24370+*/
24371+
24372+/*
24373+* ===================================================================
24374+* Include Files
24375+*/
24376+
24377+#include <string.h> /* memmove */
24378+#include <math.h>
24379+#include "vp_motionmodel.h"
24380+
24381+/* Static Functions */
24382+static
24383+double Det3(double m[3][3])
24384+{
24385+  double result;
24386+
24387+  result =
24388+    m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] +
24389+    m[0][2]*m[1][0]*m[2][1] - m[0][2]*m[1][1]*m[2][0] -
24390+    m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2];
24391+
24392+  return(result);
24393+}
24394+
24395+typedef double MATRIX[4][4];
24396+
24397+static
24398+double Det4(MATRIX m)
24399+{
24400+    /* ==> This is a poor implementation of determinant.
24401+       Writing the formula out in closed form is unnecessarily complicated
24402+       and mistakes are easy to make. */
24403+  double result;
24404+
24405+  result=
24406+    m[0][3] *m[1][2] *m[2][1] *m[3][0] - m[0][2] *m[1][3] *m[2][1] *m[3][0] - m[0][3] *m[1][1] *m[2][2] *m[3][0] +
24407+    m[0][1] *m[1][3] *m[2][2] *m[3][0] + m[0][2] *m[1][1] *m[2][3] *m[3][0] - m[0][1] *m[1][2] *m[2][3] *m[3][0] - m[0][3] *m[1][2] *m[2][0] *m[3][1] +
24408+    m[0][2] *m[1][3] *m[2][0] *m[3][1] + m[0][3] *m[1][0] *m[2][2] *m[3][1] - m[0][0] *m[1][3] *m[2][2] *m[3][1] - m[0][2] *m[1][0] *m[2][3] *m[3][1] +
24409+    m[0][0] *m[1][2] *m[2][3] *m[3][1] + m[0][3] *m[1][1] *m[2][0] *m[3][2] - m[0][1] *m[1][3] *m[2][0] *m[3][2] - m[0][3] *m[1][0] *m[2][1] *m[3][2] +
24410+    m[0][0] *m[1][3] *m[2][1] *m[3][2] + m[0][1] *m[1][0] *m[2][3] *m[3][2] - m[0][0] *m[1][1] *m[2][3] *m[3][2] - m[0][2] *m[1][1] *m[2][0] *m[3][3] +
24411+    m[0][1] *m[1][2] *m[2][0] *m[3][3] + m[0][2] *m[1][0] *m[2][1] *m[3][3] - m[0][0] *m[1][2] *m[2][1] *m[3][3] - m[0][1] *m[1][0] *m[2][2] *m[3][3] +
24412+    m[0][0] *m[1][1] *m[2][2] *m[3][3];
24413+  /*
24414+    m[0][0]*m[1][1]*m[2][2]*m[3][3]-m[0][1]*m[1][0]*m[2][2]*m[3][3]+
24415+    m[0][1]*m[1][2]*m[2][0]*m[3][3]-m[0][2]*m[1][1]*m[2][0]*m[3][3]+
24416+    m[0][2]*m[1][0]*m[2][1]*m[3][3]-m[0][0]*m[1][2]*m[2][1]*m[3][3]+
24417+    m[0][0]*m[1][2]*m[2][3]*m[3][1]-m[0][2]*m[1][0]*m[2][3]*m[3][1]+
24418+    m[0][2]*m[1][3]*m[2][0]*m[3][1]-m[0][3]*m[1][2]*m[2][0]*m[3][1]+
24419+    m[0][3]*m[1][0]*m[2][2]*m[3][1]-m[0][0]*m[1][3]*m[2][2]*m[3][1]+
24420+    m[0][0]*m[1][3]*m[2][1]*m[3][2]-m[0][3]*m[1][0]*m[2][3]*m[3][2]+
24421+    m[0][1]*m[1][0]*m[2][3]*m[3][2]-m[0][0]*m[1][1]*m[2][0]*m[3][2]+
24422+    m[0][3]*m[1][1]*m[2][0]*m[3][2]-m[0][1]*m[1][3]*m[2][1]*m[3][2]+
24423+    m[0][1]*m[1][3]*m[2][2]*m[3][0]-m[0][3]*m[1][1]*m[2][2]*m[3][0]+
24424+    m[0][2]*m[1][1]*m[2][3]*m[3][0]-m[0][1]*m[1][2]*m[2][3]*m[3][0]+
24425+    m[0][3]*m[1][2]*m[2][1]*m[3][0]-m[0][2]*m[1][3]*m[2][1]*m[3][0];
24426+    */
24427+  return(result);
24428+}
24429+
24430+static
24431+int inv4Mat(const VP_MOTION* in, VP_MOTION* out)
24432+{
24433+    /* ==> This is a poor implementation of inversion.  The determinant
24434+       method is O(N^4), i.e. unnecessarily slow, and not numerically accurate.
24435+       The real complexity of inversion is O(N^3), and is best done using
24436+       LU decomposition. */
24437+
24438+  MATRIX inmat,outmat;
24439+  int i, j, k, l, m, n,ntemp;
24440+  double mat[3][3], indet, temp;
24441+
24442+  /* check for non-empty structures structure */
24443+  if (((VP_MOTION *) NULL == in) || ((VP_MOTION *) NULL == out)) {
24444+    return 1;
24445+  }
24446+
24447+  for(k=0,i=0;i<4;i++)
24448+    for(j=0;j<4;j++,k++)
24449+      inmat[i][j]=(double)in->par[k];
24450+
24451+  indet = Det4(inmat);
24452+  if (indet==0) return(-1);
24453+
24454+  for (i=0;i<4;i++) {
24455+    for (j=0;j<4;j++) {
24456+      m = 0;
24457+      for (k=0;k<4;k++) {
24458+    if (i != k) {
24459+      n = 0;
24460+      for (l=0;l<4;l++)
24461+        if (j != l) {
24462+          mat[m][n] = inmat[k][l];
24463+          n++;
24464+        }
24465+      m++;
24466+    }
24467+      }
24468+
24469+      temp = -1.;
24470+      ntemp = (i +j ) %2;
24471+      if( ntemp == 0)  temp = 1.;
24472+
24473+      outmat[j][i] = temp * Det3(mat)/indet;
24474+    }
24475+  }
24476+
24477+  for(k=0,i=0;i<4;i++)
24478+    for(j=0;j<4;j++,k++)
24479+      out->par[k]=(VP_PAR)outmat[i][j]; /*lint !e771*/
24480+
24481+  return(0);
24482+}
24483+
24484+/*
24485+* ===================================================================
24486+* Public Functions
24487+#htmlstart
24488+*/
24489+
24490+/*
24491+ * ===================================================================
24492+#fn vp_invert_motion
24493+#ft invert a motion
24494+#fd DEFINITION
24495+       Bool
24496+       vp_invert_motion(const VP_MOTION* in,VP_MOTION* out)
24497+#fd PURPOSE
24498+       This inverts the motion given in 'in'.
24499+       All motion models upto VP_MOTION_SEMI_PROJ_3D are supported.
24500+       It is assumed that the all 16 parameters are properly
24501+       initialized although you may not be using them. You could
24502+       use the VP_KEEP_ macro's defined in vp_motionmodel.h to set
24503+       the un-initialized parameters. This uses a 4x4 matrix invertion
24504+       function internally.
24505+       It is SAFE to pass the same pointer as both the 'in' and 'out'
24506+       parameters.
24507+#fd INPUTS
24508+       in  - input motion
24509+#fd OUTPUTS
24510+       out - output inverted motion. If singular matrix uninitialized.
24511+             if MWW(in) is non-zero it is also normalized.
24512+#fd RETURNS
24513+       FALSE - matrix is singular or motion model not supported
24514+       TRUE  - otherwise
24515+#fd SIDE EFFECTS
24516+       None
24517+#endfn
24518+*/
24519+
24520+int vp_invert_motion(const VP_MOTION* in,VP_MOTION* out)
24521+{
24522+  int refid;
24523+
24524+  /* check for non-empty structures structure */
24525+  if (((VP_MOTION *) NULL == in) || ((VP_MOTION *) NULL == out)) {
24526+    return FALSE;
24527+  }
24528+
24529+  if (in->type>VP_MOTION_SEMI_PROJ_3D) {
24530+    return FALSE;
24531+  }
24532+
24533+  if (inv4Mat(in,out)<0)
24534+    return FALSE;
24535+
24536+  /*VP_NORMALIZE(*out);*/
24537+  out->type = in->type;
24538+  refid=in->refid;
24539+  out->refid=in->insid;
24540+  out->insid=refid;
24541+  return TRUE;
24542+}
24543+
24544+/*
24545+* ===================================================================
24546+#fn vp_cascade_motion
24547+#ft Cascade two motion transforms
24548+#fd DEFINITION
24549+      Bool
24550+      vp_cascade_motion(const VP_MOTION* InAB,const VP_MOTION* InBC,VP_MOTION* OutAC)
24551+#fd PURPOSE
24552+      Given Motion Transforms A->B and B->C, this function will
24553+      generate a New Motion that describes the transformation
24554+      from A->C.
24555+      More specifically, OutAC = InBC * InAC.
24556+      This function works ok if InAB,InBC and OutAC are the same pointer.
24557+#fd INPUTS
24558+      InAB - First Motion Transform
24559+      InBC - Second Motion Tranform
24560+#fd OUTPUTS
24561+      OutAC - Cascaded Motion
24562+#fd RETURNS
24563+      FALSE - motion model not supported
24564+      TRUE  - otherwise
24565+#fd SIDE EFFECTS
24566+      None
24567+#endfn
24568+*/
24569+
24570+int vp_cascade_motion(const VP_MOTION* InA, const VP_MOTION* InB,VP_MOTION* Out)
24571+{
24572+    /* ==> This is a poor implementation of matrix multiplication.
24573+       Writing the formula out in closed form is unnecessarily complicated
24574+       and mistakes are easy to make. */
24575+  VP_PAR mxx,mxy,mxz,mxw;
24576+  VP_PAR myx,myy,myz,myw;
24577+  VP_PAR mzx,mzy,mzz,mzw;
24578+  VP_PAR mwx,mwy,mwz,mww;
24579+
24580+  /* check for non-empty structures structure */
24581+  if (((VP_MOTION *) NULL == InA) || ((VP_MOTION *) NULL == InB) ||
24582+      ((VP_MOTION *) NULL == Out)) {
24583+    return FALSE;
24584+  }
24585+
24586+  if (InA->type>VP_MOTION_PROJ_3D) {
24587+    return FALSE;
24588+  }
24589+
24590+  if (InB->type>VP_MOTION_PROJ_3D) {
24591+    return FALSE;
24592+  }
24593+
24594+  mxx = MXX(*InB)*MXX(*InA)+MXY(*InB)*MYX(*InA)+MXZ(*InB)*MZX(*InA)+MXW(*InB)*MWX(*InA);
24595+  mxy = MXX(*InB)*MXY(*InA)+MXY(*InB)*MYY(*InA)+MXZ(*InB)*MZY(*InA)+MXW(*InB)*MWY(*InA);
24596+  mxz = MXX(*InB)*MXZ(*InA)+MXY(*InB)*MYZ(*InA)+MXZ(*InB)*MZZ(*InA)+MXW(*InB)*MWZ(*InA);
24597+  mxw = MXX(*InB)*MXW(*InA)+MXY(*InB)*MYW(*InA)+MXZ(*InB)*MZW(*InA)+MXW(*InB)*MWW(*InA);
24598+  myx = MYX(*InB)*MXX(*InA)+MYY(*InB)*MYX(*InA)+MYZ(*InB)*MZX(*InA)+MYW(*InB)*MWX(*InA);
24599+  myy = MYX(*InB)*MXY(*InA)+MYY(*InB)*MYY(*InA)+MYZ(*InB)*MZY(*InA)+MYW(*InB)*MWY(*InA);
24600+  myz = MYX(*InB)*MXZ(*InA)+MYY(*InB)*MYZ(*InA)+MYZ(*InB)*MZZ(*InA)+MYW(*InB)*MWZ(*InA);
24601+  myw = MYX(*InB)*MXW(*InA)+MYY(*InB)*MYW(*InA)+MYZ(*InB)*MZW(*InA)+MYW(*InB)*MWW(*InA);
24602+  mzx = MZX(*InB)*MXX(*InA)+MZY(*InB)*MYX(*InA)+MZZ(*InB)*MZX(*InA)+MZW(*InB)*MWX(*InA);
24603+  mzy = MZX(*InB)*MXY(*InA)+MZY(*InB)*MYY(*InA)+MZZ(*InB)*MZY(*InA)+MZW(*InB)*MWY(*InA);
24604+  mzz = MZX(*InB)*MXZ(*InA)+MZY(*InB)*MYZ(*InA)+MZZ(*InB)*MZZ(*InA)+MZW(*InB)*MWZ(*InA);
24605+  mzw = MZX(*InB)*MXW(*InA)+MZY(*InB)*MYW(*InA)+MZZ(*InB)*MZW(*InA)+MZW(*InB)*MWW(*InA);
24606+  mwx = MWX(*InB)*MXX(*InA)+MWY(*InB)*MYX(*InA)+MWZ(*InB)*MZX(*InA)+MWW(*InB)*MWX(*InA);
24607+  mwy = MWX(*InB)*MXY(*InA)+MWY(*InB)*MYY(*InA)+MWZ(*InB)*MZY(*InA)+MWW(*InB)*MWY(*InA);
24608+  mwz = MWX(*InB)*MXZ(*InA)+MWY(*InB)*MYZ(*InA)+MWZ(*InB)*MZZ(*InA)+MWW(*InB)*MWZ(*InA);
24609+  mww = MWX(*InB)*MXW(*InA)+MWY(*InB)*MYW(*InA)+MWZ(*InB)*MZW(*InA)+MWW(*InB)*MWW(*InA);
24610+
24611+  MXX(*Out)=mxx; MXY(*Out)=mxy; MXZ(*Out)=mxz; MXW(*Out)=mxw;
24612+  MYX(*Out)=myx; MYY(*Out)=myy; MYZ(*Out)=myz; MYW(*Out)=myw;
24613+  MZX(*Out)=mzx; MZY(*Out)=mzy; MZZ(*Out)=mzz; MZW(*Out)=mzw;
24614+  MWX(*Out)=mwx; MWY(*Out)=mwy; MWZ(*Out)=mwz; MWW(*Out)=mww;
24615+  /* VP_NORMALIZE(*Out); */
24616+  Out->type= (InA->type > InB->type) ? InA->type : InB->type;
24617+  Out->refid=InA->refid;
24618+  Out->insid=InB->insid;
24619+
24620+  return TRUE;
24621+}
24622+
24623+/*
24624+* ===================================================================
24625+#fn vp_copy_motion
24626+#ft Copies the source motion to the destination motion.
24627+#fd DEFINITION
24628+    void
24629+    vp_copy_motion  (const VP_MOTION *src, VP_MOTION *dst)
24630+#fd PURPOSE
24631+    Copies the source motion to the destination motion.
24632+        It is OK if src == dst.
24633+    NOTE THAT THE SOURCE IS THE FIRST ARGUMENT.
24634+    This is different from some of the other VP
24635+    copy functions.
24636+#fd INPUTS
24637+    src is the source motion
24638+    dst is the destination motion
24639+#fd RETURNS
24640+    void
24641+#endfn
24642+*/
24643+void vp_copy_motion  (const VP_MOTION *src, VP_MOTION *dst)
24644+{
24645+  /* Use memmove rather than memcpy because it handles overlapping memory
24646+     OK. */
24647+  memmove(dst, src, sizeof(VP_MOTION));
24648+  return;
24649+} /* vp_copy_motion() */
24650+
24651+#define VP_SQR(x)   ( (x)*(x) )
24652+double vp_motion_cornerdiff(const VP_MOTION *mot_a, const VP_MOTION *mot_b,
24653+                     int xo, int yo, int w, int h)
24654+{
24655+  double ax1, ay1, ax2, ay2, ax3, ay3, ax4, ay4;
24656+  double bx1, by1, bx2, by2, bx3, by3, bx4, by4;
24657+  double err;
24658+
24659+  /*lint -e639 -e632 -e633 */
24660+  VP_WARP_POINT_2D(xo, yo,         *mot_a, ax1, ay1);
24661+  VP_WARP_POINT_2D(xo+w-1, yo,     *mot_a, ax2, ay2);
24662+  VP_WARP_POINT_2D(xo+w-1, yo+h-1, *mot_a, ax3, ay3);
24663+  VP_WARP_POINT_2D(xo, yo+h-1,     *mot_a, ax4, ay4);
24664+  VP_WARP_POINT_2D(xo, yo,         *mot_b, bx1, by1);
24665+  VP_WARP_POINT_2D(xo+w-1, yo,     *mot_b, bx2, by2);
24666+  VP_WARP_POINT_2D(xo+w-1, yo+h-1, *mot_b, bx3, by3);
24667+  VP_WARP_POINT_2D(xo, yo+h-1,     *mot_b, bx4, by4);
24668+  /*lint +e639 +e632 +e633 */
24669+
24670+  err = 0;
24671+  err += (VP_SQR(ax1 - bx1) + VP_SQR(ay1 - by1));
24672+  err += (VP_SQR(ax2 - bx2) + VP_SQR(ay2 - by2));
24673+  err += (VP_SQR(ax3 - bx3) + VP_SQR(ay3 - by3));
24674+  err += (VP_SQR(ax4 - bx4) + VP_SQR(ay4 - by4));
24675+
24676+  return(sqrt(err));
24677+}
24678+
24679+int vp_zoom_motion2d(VP_MOTION* in, VP_MOTION* out,
24680+                 int n, int w, int h, double zoom)
24681+{
24682+  int ii;
24683+  VP_PAR inv_zoom;
24684+  VP_PAR cx, cy;
24685+  VP_MOTION R2r,R2f;
24686+  VP_MOTION *res;
24687+
24688+  /* check for non-empty structures structure */
24689+  if (((VP_MOTION *) NULL == in)||(zoom <= 0.0)||(w <= 0)||(h <= 0)) {
24690+    return FALSE;
24691+  }
24692+
24693+  /* ==> Not sure why the special case of out=NULL is necessary.  Why couldn't
24694+     the caller just pass the same pointer for both in and out? */
24695+  res = ((VP_MOTION *) NULL == out)?in:out;
24696+
24697+  cx = (VP_PAR) (w/2.0);
24698+  cy = (VP_PAR) (h/2.0);
24699+
24700+  VP_MOTION_ID(R2r);
24701+  inv_zoom = (VP_PAR)(1.0/zoom);
24702+  MXX(R2r) = inv_zoom;
24703+  MYY(R2r) = inv_zoom;
24704+  MXW(R2r)=cx*(((VP_PAR)1.0) - inv_zoom);
24705+  MYW(R2r)=cy*(((VP_PAR)1.0) - inv_zoom);
24706+
24707+  VP_KEEP_AFFINE_2D(R2r);
24708+
24709+  for(ii=0;ii<n;ii++) {
24710+    (void) vp_cascade_motion(&R2r,in+ii,&R2f);
24711+    res[ii]=R2f;
24712+  }
24713+
24714+  return TRUE;
24715+} /* vp_zoom_motion2d() */
24716+
24717+/* =================================================================== */
24718+/* end vp_motionmodel.c */
24719diff --git a/benchmark/feature_stab/src/dbreg/vp_motionmodel.h b/benchmark/feature_stab/src/dbreg/vp_motionmodel.h
24720new file mode 100644
24721index 00000000..a63ac001
24722--- /dev/null
24723+++ b/benchmark/feature_stab/src/dbreg/vp_motionmodel.h
24724@@ -0,0 +1,282 @@
24725+/*
24726+ * Copyright (C) 2011 The Android Open Source Project
24727+ *
24728+ * Licensed under the Apache License, Version 2.0 (the "License");
24729+ * you may not use this file except in compliance with the License.
24730+ * You may obtain a copy of the License at
24731+ *
24732+ *      http://www.apache.org/licenses/LICENSE-2.0
24733+ *
24734+ * Unless required by applicable law or agreed to in writing, software
24735+ * distributed under the License is distributed on an "AS IS" BASIS,
24736+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24737+ * See the License for the specific language governing permissions and
24738+ * limitations under the License.
24739+ */
24740+
24741+/*
24742+#sourcefile  vp_motionmodel.h
24743+#category    warp
24744+#description general motion model for tranlation/affine/projective
24745+#title       motion-model
24746+#parentlink  hindex.html
24747+*
24748+* Copyright 1998 Sarnoff Corporation
24749+* All Rights Reserved
24750+*
24751+* Modification History
24752+*      Date: 02/13/98
24753+*      Author: supuns
24754+*      Shop Order: 15491 001
24755+*              @(#) $Id: vp_motionmodel.h,v 1.4 2011/06/17 14:04:33 mbansal Exp $
24756+*/
24757+
24758+#ifndef VP_MOTIONMODEL_H
24759+#define VP_MOTIONMODEL_H
24760+#include <stdio.h>
24761+
24762+#define         FALSE           0
24763+#define         TRUE            1
24764+
24765+#if 0 /* Moved mottomat.c and mattomot_d.c from vpmotion.h to vpcompat.h
24766+     in order to remove otherwise unnecessary dependency of vpmotion,
24767+     vpwarp, and newvpio on vpmath */
24768+#ifndef VPMATH_H
24769+#include "vpmath.h"
24770+#endif
24771+#endif
24772+
24773+#if 0
24774+#ifndef VP_WARP_H
24775+#include "vp_warp.h"
24776+#endif
24777+#endif
24778+/*
24779+
24780+#htmlstart
24781+# ===================================================================
24782+#h 1 Introduction
24783+
24784+  This defines a motion model that can describe translation,
24785+  affine, and projective projective 3d and 3d view transforms.
24786+
24787+  The main structure VP_MOTION contains a 16 parameter array (That
24788+  can be considered as elements of a 4x4 matrix) and a type field
24789+  which can be one of VP_MOTION_NONE,VP_MOTION_TRANSLATION,
24790+  VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE,VP_MOTION_PROJ_3D or
24791+  VP_MOTION_VIEW_3D. (These are defined using enums with gaps of 10
24792+  so that subsets of these motions that are still consistant can be
24793+  added in between. Motion models that are inconsistant with this set
24794+  should be added at the end so the routines can hadle them
24795+  independently.
24796+
24797+  The transformation VP_MOTION_NONE,VP_MOTION_TRANSLATION,
24798+  VP_MOTION_AFFINE, VP_MOTION_PROJECTIVE, VP_MOTION_PROJ_3D and
24799+  VP_MOTION_SEMI_PROJ_3D would map a point P={x,y,z,w} to a new point
24800+  P'={x',y',z',w'} using a motion model M such that P'= M.par * P.
24801+  Where M.par is thought of as  elements of a 4x4 matrix ordered row
24802+  by row. The interpretation of all models except VP_MOTION_SEMI_PROJ_3D
24803+  is taken to be mapping of a 3d point P"={x",y",z"} which is obtained
24804+  from the normalization {x'/w',y'/w',z'/w'}. In the VP_MOTION_SEMI_PROJ_3D
24805+  the mapping to a point P"={x",y",z"} is obtained from the normalization
24806+  {x'/w',y'/w',z'}. All these motion models have the property that they
24807+  can be inverted using 4x4 matrices. Except for the VP_MOTION_SEMI_PROJ_3D all
24808+  other types can also be cascaded using 4x4 matrices.
24809+
24810+  Specific macros and functions have been provided to handle 2d instances
24811+  of these functions. As the parameter interpretations can change when adding
24812+  new motion models it is HIGHLY RECOMMENDED that you use the macros MXX,MXY..
24813+  ect. to interpret each motion component.
24814+#pre
24815+*/
24816+
24817+/*
24818+#endpre
24819+# ===================================================================
24820+#h 1 Typedef and Struct Declarations
24821+#pre
24822+*/
24823+
24824+#define VP_MAX_MOTION_PAR 16
24825+
24826+typedef double VP_PAR;
24827+typedef VP_PAR VP_TRS[VP_MAX_MOTION_PAR];
24828+
24829+/* Do not add any motion models before VP_MOTION_PROJECTIVE */
24830+/* The order is assumed in vp functions */
24831+enum VP_MOTION_MODEL {
24832+  VP_MOTION_NONE=0,
24833+  VP_MOTION_TRANSLATION=10,
24834+  VP_MOTION_SCALE=11,
24835+  VP_MOTION_ROTATE=12,
24836+  VP_MOTION_X_SHEAR=13,
24837+  VP_MOTION_Y_SHEAR=14,
24838+  VP_MOTION_SIMILARITY=15,
24839+  VP_MOTION_AFFINE=20,
24840+  VP_MOTION_PROJECTIVE=30,
24841+  VP_MOTION_PROJ_3D=40,
24842+  VP_MOTION_SEMI_PROJ_3D=80,
24843+  VP_SIMILARITY=100,
24844+  VP_VFE_AFFINE=120
24845+};
24846+
24847+#define VP_REFID -1   /* Default ID used for reference frame */
24848+
24849+typedef struct {
24850+  VP_TRS par;            /* Contains the motion paramerers.
24851+                For the standard motion types this is
24852+                represented as 16 number that refer
24853+                to a 4x4 matrix */
24854+  enum VP_MOTION_MODEL type;
24855+  int refid;            /* Reference frame ( takes a point in refid frame
24856+               and moves it by the par to get a point in insid
24857+               frame ) */
24858+  int insid;            /* Inspection frame */
24859+} VP_MOTION;
24860+
24861+//typedef VP_LIST VP_MOTION_LIST;
24862+/*
24863+#endpre
24864+# ===================================================================
24865+#h 1 Constant Declarations
24866+*/
24867+
24868+/* Macros related to the 4x4 matrix parameters */
24869+#define MXX(m) (m).par[0]
24870+#define MXY(m) (m).par[1]
24871+#define MXZ(m) (m).par[2]
24872+#define MXW(m) (m).par[3]
24873+#define MYX(m) (m).par[4]
24874+#define MYY(m) (m).par[5]
24875+#define MYZ(m) (m).par[6]
24876+#define MYW(m) (m).par[7]
24877+#define MZX(m) (m).par[8]
24878+#define MZY(m) (m).par[9]
24879+#define MZZ(m) (m).par[10]
24880+#define MZW(m) (m).par[11]
24881+#define MWX(m) (m).par[12]
24882+#define MWY(m) (m).par[13]
24883+#define MWZ(m) (m).par[14]
24884+#define MWW(m) (m).par[15]
24885+
24886+/* The do {...} while (0) technique creates a statement that can be used legally
24887+   in an if-else statement.  See "Swallowing the semicolon",
24888+   http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC23 */
24889+/* Initialize the Motion to be Identity */
24890+#define VP_MOTION_ID(m) do {\
24891+  MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \
24892+  MXY(m)=MXZ(m)=MXW(m)=(VP_PAR)0.0; \
24893+  MYX(m)=MYZ(m)=MYW(m)=(VP_PAR)0.0; \
24894+  MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \
24895+  MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \
24896+(m).type = VP_MOTION_TRANSLATION; } while (0)
24897+
24898+/* Initialize without altering the translation components */
24899+#define VP_KEEP_TRANSLATION_3D(m) do {\
24900+  MXX(m)=MYY(m)=MZZ(m)=MWW(m)=(VP_PAR)1.0; \
24901+  MXY(m)=MXZ(m)=(VP_PAR)0.0; \
24902+  MYX(m)=MYZ(m)=(VP_PAR)0.0; \
24903+  MZX(m)=MZY(m)=(VP_PAR)0.0; \
24904+  MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; \
24905+  (m).type = VP_MOTION_PROJ_3D; } while (0)
24906+
24907+/* Initialize without altering the 2d translation components */
24908+#define VP_KEEP_TRANSLATION_2D(m) do {\
24909+  VP_KEEP_TRANSLATION_3D(m); MZW(m)=(VP_PAR)0.0; (m).type= VP_MOTION_TRANSLATION;} while (0)
24910+
24911+/* Initialize without altering the affine & translation components */
24912+#define VP_KEEP_AFFINE_3D(m) do {\
24913+  MWX(m)=MWY(m)=MWZ(m)=(VP_PAR)0.0; MWW(m)=(VP_PAR)1.0; \
24914+  (m).type = VP_MOTION_PROJ_3D; } while (0)
24915+
24916+/* Initialize without altering the 2d affine & translation components */
24917+#define VP_KEEP_AFFINE_2D(m) do {\
24918+  VP_KEEP_AFFINE_3D(m); \
24919+  MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \
24920+  MZX(m)=MZY(m)=MZW(m)=(VP_PAR)0.0; \
24921+  (m).type = VP_MOTION_AFFINE; } while (0)
24922+
24923+/* Initialize without altering the 2d projective parameters */
24924+#define VP_KEEP_PROJECTIVE_2D(m) do {\
24925+  MXZ(m)=MYZ(m)=(VP_PAR)0.0; MZZ(m)=(VP_PAR)1.0; \
24926+  MZX(m)=MZY(m)=MZW(m)=MWZ(m)=(VP_PAR)0.0; \
24927+  (m).type = VP_MOTION_PROJECTIVE; } while (0)
24928+
24929+/* Warp a 2d point (assuming the z component is zero) */
24930+#define VP_WARP_POINT_2D(inx,iny,m,outx,outy) do {\
24931+  VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWW(m); \
24932+  outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXW(m))/vpTmpWarpPnt___; \
24933+  outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYW(m))/vpTmpWarpPnt___; } while (0)
24934+
24935+/* Warp a 3d point */
24936+#define VP_WARP_POINT_3D(inx,iny,inz,m,outx,outy,outz) do {\
24937+  VP_PAR vpTmpWarpPnt___= MWX(m)*(inx)+MWY(m)*(iny)+MWZ(m)*((VP_PAR)inz)+MWW(m); \
24938+  outx = (MXX(m)*((VP_PAR)inx)+MXY(m)*((VP_PAR)iny)+MXZ(m)*((VP_PAR)inz)+MXW(m))/vpTmpWarpPnt___; \
24939+  outy = (MYX(m)*((VP_PAR)inx)+MYY(m)*((VP_PAR)iny)+MYZ(m)*((VP_PAR)inz)+MYW(m))/vpTmpWarpPnt___; \
24940+  outz = MZX(m)*((VP_PAR)inx)+MZY(m)*((VP_PAR)iny)+MZZ(m)*((VP_PAR)inz)+MZW(m); \
24941+  if ((m).type==VP_MOTION_PROJ_3D) outz/=vpTmpWarpPnt___; } while (0)
24942+
24943+/* Projections of each component */
24944+#define VP_PROJW_3D(m,x,y,z,f)   ( MWX(m)*(x)+MWY(m)*(y)+MWZ(m)*(z)+MWW(m) )
24945+#define VP_PROJX_3D(m,x,y,z,f,w) ((MXX(m)*(x)+MXY(m)*(y)+MXZ(m)*(z)+MXW(m))/(w))
24946+#define VP_PROJY_3D(m,x,y,z,f,w) ((MYX(m)*(x)+MYY(m)*(y)+MYZ(m)*(z)+MYW(m))/(w))
24947+#define VP_PROJZ_3D(m,x,y,z,f,w) ((MZX(m)*(x)+MZY(m)*(y)+MZZ(m)*(z)+MZW(m))/(w))
24948+
24949+/* Scale Down a matrix by Sfactor */
24950+#define VP_SCALEDOWN(m,Sfactor) do { \
24951+  MXW(m) /= (VP_PAR)Sfactor; MWX(m) *= (VP_PAR)Sfactor; \
24952+  MYW(m) /= (VP_PAR)Sfactor; MWY(m) *= (VP_PAR)Sfactor; \
24953+  MZW(m) /= (VP_PAR)Sfactor; MWZ(m) *= (VP_PAR)Sfactor; } while (0)
24954+
24955+/* Scale Up a matrix by Sfactor */
24956+#define VP_SCALEUP(m,Sfactor) do { \
24957+  MXW(m) *= (VP_PAR)Sfactor; MWX(m) /= (VP_PAR)Sfactor; \
24958+  MYW(m) *= (VP_PAR)Sfactor; MWY(m) /= (VP_PAR)Sfactor; \
24959+  MZW(m) *= (VP_PAR)Sfactor; MWZ(m) /= (VP_PAR)Sfactor; } while (0)
24960+
24961+/* Normalize the transformation matrix so that MWW is 1 */
24962+#define VP_NORMALIZE(m) if (MWW(m)!=(VP_PAR)0.0) do { \
24963+  MXX(m)/=MWW(m); MXY(m)/=MWW(m); MXZ(m)/=MWW(m); MXW(m)/= MWW(m); \
24964+  MYX(m)/=MWW(m); MYY(m)/=MWW(m); MYZ(m)/=MWW(m); MYW(m)/= MWW(m); \
24965+  MZX(m)/=MWW(m); MZY(m)/=MWW(m); MZZ(m)/=MWW(m); MZW(m)/= MWW(m); \
24966+  MWX(m)/=MWW(m); MWY(m)/=MWW(m); MWZ(m)/=MWW(m); MWW(m) = (VP_PAR)1.0; } while (0)
24967+
24968+#define VP_PRINT_TRANS(msg,b) do { \
24969+  fprintf(stderr, \
24970+      "%s\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n%f %f %f %f\n", \
24971+      msg, \
24972+      MXX(b),MXY(b),MXZ(b),MXW(b),  \
24973+      MYX(b),MYY(b),MYZ(b),MYW(b),  \
24974+      MZX(b),MZY(b),MZZ(b),MZW(b),  \
24975+      MWX(b),MWY(b),MWZ(b),MWW(b)); \
24976+} while (0)
24977+
24978+/* w' projection given a point x,y,0,f */
24979+#define VP_PROJZ(m,x,y,f) ( \
24980+    MWX(m)*((VP_PAR)x)+MWY(m)*((VP_PAR)y)+MWW(m)*((VP_PAR)f))
24981+
24982+/* X Projection given a point x,y,0,f and w' */
24983+#define VP_PROJX(m,x,y,w,f) (\
24984+   (MXX(m)*((VP_PAR)x)+MXY(m)*((VP_PAR)y)+MXW(m)*((VP_PAR)f))/((VP_PAR)w))
24985+
24986+/* Y Projection given a point x,y,0,f and the w' */
24987+#define VP_PROJY(m,x,y,w,f) (\
24988+  (MYX(m)*((VP_PAR)x)+MYY(m)*((VP_PAR)y)+MYW(m)*((VP_PAR)f))/((VP_PAR)w))
24989+
24990+/* Set the reference id for a motion */
24991+#define VP_SET_REFID(m,id) do { (m).refid=id; } while (0)
24992+
24993+/* Set the inspection id for a motion */
24994+#define VP_SET_INSID(m,id) do { (m).insid=id; } while (0)
24995+
24996+void vp_copy_motion  (const VP_MOTION *src, VP_MOTION *dst);
24997+int vp_invert_motion(const VP_MOTION* in,VP_MOTION* out);
24998+int vp_cascade_motion(const VP_MOTION* InAB, const VP_MOTION* InBC,VP_MOTION* OutAC);
24999+int vp_zoom_motion2d(VP_MOTION* in, VP_MOTION* out,
25000+              int n, int w, int h, double zoom);
25001+double vp_motion_cornerdiff(const VP_MOTION *mot_a, const VP_MOTION *mot_b,
25002+                     int xo, int yo, int w, int h);
25003+
25004+#endif /* VP_MOTIONMODEL_H */
25005+/* =================================================================== */
25006+/* end vp_motionmodel.h */
25007diff --git a/benchmark/feature_stab/src/dbregtest/PgmImage.cpp b/benchmark/feature_stab/src/dbregtest/PgmImage.cpp
25008new file mode 100644
25009index 00000000..0891cfda
25010--- /dev/null
25011+++ b/benchmark/feature_stab/src/dbregtest/PgmImage.cpp
25012@@ -0,0 +1,260 @@
25013+/*
25014+ * Copyright (C) 2011 The Android Open Source Project
25015+ *
25016+ * Licensed under the Apache License, Version 2.0 (the "License");
25017+ * you may not use this file except in compliance with the License.
25018+ * You may obtain a copy of the License at
25019+ *
25020+ *      http://www.apache.org/licenses/LICENSE-2.0
25021+ *
25022+ * Unless required by applicable law or agreed to in writing, software
25023+ * distributed under the License is distributed on an "AS IS" BASIS,
25024+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25025+ * See the License for the specific language governing permissions and
25026+ * limitations under the License.
25027+ */
25028+
25029+#include "PgmImage.h"
25030+#include <cassert>
25031+
25032+using namespace std;
25033+
25034+PgmImage::PgmImage(std::string filename) :
25035+m_w(0),m_h(0),m_colors(255),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256)
25036+{
25037+    if ( !ReadPGM(filename) )
25038+        return;
25039+}
25040+
25041+PgmImage::PgmImage(int w, int h, int format) :
25042+m_colors(255),m_w(w),m_h(h),m_format(format),m_over_allocation(256)
25043+{
25044+    SetFormat(format);
25045+}
25046+
25047+PgmImage::PgmImage(unsigned char *data, int w, int h) :
25048+m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256)
25049+{
25050+    SetData(data);
25051+}
25052+
25053+PgmImage::PgmImage(std::vector<unsigned char> &data, int w, int h) :
25054+m_colors(255),m_w(w),m_h(h),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256)
25055+{
25056+    if ( data.size() == w*h )
25057+        SetData(&data[0]);
25058+    else
25059+        //throw (std::exception("Size of data is not w*h."));
25060+        throw (std::exception());
25061+}
25062+
25063+PgmImage::PgmImage(const PgmImage &im) :
25064+m_colors(255),m_w(0),m_h(0),m_format(PGM_BINARY_GRAYMAP),m_over_allocation(256)
25065+{
25066+    DeepCopy(im, *this);
25067+}
25068+
25069+PgmImage& PgmImage::operator= (const PgmImage &im)
25070+{
25071+    if (this == &im) return *this;
25072+    DeepCopy(im, *this);
25073+    return *this;
25074+}
25075+
25076+void PgmImage::DeepCopy(const PgmImage& src, PgmImage& dst)
25077+{
25078+    dst.m_data = src.m_data;
25079+
25080+    // PGM data
25081+    dst.m_w = src.m_w;
25082+    dst.m_h = src.m_h;
25083+    dst.m_format = src.m_format;
25084+    dst.m_colors = src.m_colors;
25085+
25086+    dst.m_comment = src.m_comment;
25087+    SetupRowPointers();
25088+}
25089+
25090+PgmImage::~PgmImage()
25091+{
25092+
25093+}
25094+
25095+void PgmImage::SetFormat(int format)
25096+{
25097+    m_format = format;
25098+
25099+    switch (format)
25100+    {
25101+    case PGM_BINARY_GRAYMAP:
25102+        m_data.resize(m_w*m_h+m_over_allocation);
25103+        break;
25104+    case PGM_BINARY_PIXMAP:
25105+        m_data.resize(m_w*m_h*3+m_over_allocation);
25106+        break;
25107+    default:
25108+        return;
25109+        break;
25110+    }
25111+    SetupRowPointers();
25112+}
25113+
25114+void PgmImage::SetData(const unsigned char * data)
25115+{
25116+    m_data.resize(m_w*m_h+m_over_allocation);
25117+    memcpy(&m_data[0],data,m_w*m_h);
25118+    SetupRowPointers();
25119+}
25120+
25121+bool PgmImage::ReadPGM(const std::string filename)
25122+{
25123+    ifstream in(filename.c_str(),std::ios::in | std::ios::binary);
25124+    if ( !in.is_open() )
25125+        return false;
25126+
25127+    // read the header:
25128+    string format_header,size_header,colors_header;
25129+
25130+    getline(in,format_header);
25131+    stringstream s;
25132+    s << format_header;
25133+
25134+    s >> format_header >> m_w >> m_h >> m_colors;
25135+    s.clear();
25136+
25137+    if ( m_w == 0 )
25138+    {
25139+        while ( in.peek() == '#' )
25140+            getline(in,m_comment);
25141+
25142+        getline(in,size_header);
25143+
25144+        while ( in.peek() == '#' )
25145+            getline(in,m_comment);
25146+
25147+            m_colors = 0;
25148+
25149+        // parse header
25150+        s << size_header;
25151+        s >> m_w >> m_h >> m_colors;
25152+        s.clear();
25153+
25154+        if ( m_colors == 0 )
25155+        {
25156+            getline(in,colors_header);
25157+            s << colors_header;
25158+            s >> m_colors;
25159+        }
25160+    }
25161+
25162+    if ( format_header == "P5" )
25163+        m_format = PGM_BINARY_GRAYMAP;
25164+    else if (format_header == "P6" )
25165+        m_format = PGM_BINARY_PIXMAP;
25166+    else
25167+        m_format = PGM_FORMAT_INVALID;
25168+
25169+    switch(m_format)
25170+    {
25171+    case(PGM_BINARY_GRAYMAP):
25172+        m_data.resize(m_w*m_h+m_over_allocation);
25173+        in.read((char *)(&m_data[0]),m_data.size());
25174+        break;
25175+    case(PGM_BINARY_PIXMAP):
25176+        m_data.resize(m_w*m_h*3+m_over_allocation);
25177+        in.read((char *)(&m_data[0]),m_data.size());
25178+        break;
25179+    default:
25180+        return false;
25181+        break;
25182+    }
25183+    in.close();
25184+
25185+    SetupRowPointers();
25186+
25187+    return true;
25188+}
25189+
25190+bool PgmImage::WritePGM(const std::string filename, const std::string comment)
25191+{
25192+    string format_header;
25193+
25194+    switch(m_format)
25195+    {
25196+    case PGM_BINARY_GRAYMAP:
25197+        format_header = "P5\n";
25198+        break;
25199+    case PGM_BINARY_PIXMAP:
25200+        format_header = "P6\n";
25201+        break;
25202+    default:
25203+        return false;
25204+        break;
25205+    }
25206+
25207+    ofstream out(filename.c_str(),std::ios::out |ios::binary);
25208+    out << format_header << "# " << comment << '\n' << m_w << " " << m_h << '\n' << m_colors << '\n';
25209+
25210+    out.write((char *)(&m_data[0]), m_data.size());
25211+
25212+    out.close();
25213+
25214+    return true;
25215+}
25216+
25217+void PgmImage::SetupRowPointers()
25218+{
25219+    int i;
25220+    m_rows.resize(m_h);
25221+
25222+    switch (m_format)
25223+    {
25224+    case PGM_BINARY_GRAYMAP:
25225+        for(i=0;i<m_h;i++)
25226+        {
25227+            m_rows[i]=&m_data[m_w*i];
25228+        }
25229+        break;
25230+    case PGM_BINARY_PIXMAP:
25231+        for(i=0;i<m_h;i++)
25232+        {
25233+            m_rows[i]=&m_data[(m_w*3)*i];
25234+        }
25235+        break;
25236+    }
25237+}
25238+
25239+void PgmImage::ConvertToGray()
25240+{
25241+    if ( m_format != PGM_BINARY_PIXMAP ) return;
25242+
25243+    // Y = 0.3*R + 0.59*G + 0.11*B;
25244+    for ( int i = 0; i < m_w*m_h; ++i )
25245+        m_data[i] = (unsigned char)(0.3*m_data[3*i]+0.59*m_data[3*i+1]+0.11*m_data[3*i+2]);
25246+
25247+    m_data.resize(m_w*m_h+m_over_allocation);
25248+    m_format = PGM_BINARY_GRAYMAP;
25249+
25250+    SetupRowPointers();
25251+}
25252+
25253+std::ostream& operator<< (std::ostream& o, const PgmImage& im)
25254+{
25255+    o << "PGM Image Info:\n";
25256+    o << "Size: " << im.m_w << " x " << im.m_h << "\n";
25257+    o << "Comment: " << im.m_comment << "\n";
25258+    switch (im.m_format)
25259+    {
25260+    case PgmImage::PGM_BINARY_PIXMAP:
25261+        o << "Format: RGB binary pixmap";
25262+        break;
25263+    case PgmImage::PGM_BINARY_GRAYMAP:
25264+        o << "Format: PPM binary graymap";
25265+        break;
25266+    default:
25267+        o << "Format: Invalid";
25268+        break;
25269+    }
25270+    o << endl;
25271+    return o;
25272+}
25273diff --git a/benchmark/feature_stab/src/dbregtest/PgmImage.h b/benchmark/feature_stab/src/dbregtest/PgmImage.h
25274new file mode 100644
25275index 00000000..d4d1eebe
25276--- /dev/null
25277+++ b/benchmark/feature_stab/src/dbregtest/PgmImage.h
25278@@ -0,0 +1,95 @@
25279+/*
25280+ * Copyright (C) 2011 The Android Open Source Project
25281+ *
25282+ * Licensed under the Apache License, Version 2.0 (the "License");
25283+ * you may not use this file except in compliance with the License.
25284+ * You may obtain a copy of the License at
25285+ *
25286+ *      http://www.apache.org/licenses/LICENSE-2.0
25287+ *
25288+ * Unless required by applicable law or agreed to in writing, software
25289+ * distributed under the License is distributed on an "AS IS" BASIS,
25290+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25291+ * See the License for the specific language governing permissions and
25292+ * limitations under the License.
25293+ */
25294+
25295+#pragma once
25296+
25297+#include <vector>
25298+#include <iostream>
25299+#include <fstream>
25300+#include <sstream>
25301+#include <memory.h>
25302+
25303+/*!
25304+ * Simple class to manipulate PGM/PPM images. Not suitable for heavy lifting.
25305+ */
25306+class PgmImage
25307+{
25308+    friend std::ostream& operator<< (std::ostream& o, const PgmImage& im);
25309+public:
25310+    enum {PGM_BINARY_GRAYMAP,PGM_BINARY_PIXMAP,PGM_FORMAT_INVALID};
25311+    /*!
25312+    * Constructor from a PGM file name.
25313+    */
25314+    PgmImage(std::string filename);
25315+    /*!
25316+    * Constructor to allocate an image of given size and type.
25317+    */
25318+    PgmImage(int w, int h, int format = PGM_BINARY_GRAYMAP);
25319+    /*!
25320+    * Constructor to allocate an image of given size and copy the data in.
25321+    */
25322+    PgmImage(unsigned char *data, int w, int h);
25323+    /*!
25324+    * Constructor to allocate an image of given size and copy the data in.
25325+    */
25326+    PgmImage(std::vector<unsigned char> &data, int w, int h);
25327+
25328+    PgmImage(const PgmImage &im);
25329+
25330+    PgmImage& operator= (const PgmImage &im);
25331+    ~PgmImage();
25332+
25333+    int GetHeight() const { return m_h; }
25334+    int GetWidth() const { return m_w; }
25335+
25336+    //! Copy pixels from data pointer
25337+    void SetData(const unsigned char * data);
25338+
25339+    //! Get a data pointer to unaligned memory area
25340+    unsigned char * GetDataPointer() { if ( m_data.size() > 0 ) return &m_data[0]; else return NULL; }
25341+    unsigned char ** GetRowPointers() { if ( m_rows.size() == m_h ) return &m_rows[0]; else return NULL; }
25342+
25343+    //! Read a PGM file from disk
25344+    bool ReadPGM(const std::string filename);
25345+    //! Write a PGM file to disk
25346+    bool WritePGM(const std::string filename, const std::string comment="");
25347+
25348+    //! Get image format (returns PGM_BINARY_GRAYMAP, PGM_BINARY_PIXMAP or PGM_FORMAT_INVALID)
25349+    int GetFormat() const { return m_format; }
25350+
25351+    //! Set image format (returns PGM_BINARY_GRAYMAP, PGM_BINARY_PIXMAP). Image data becomes invalid.
25352+    void SetFormat(int format);
25353+
25354+    //! If the image is PGM_BINARY_PIXMAP, convert it to PGM_BINARY_GRAYMAP via Y = 0.3*R + 0.59*G + 0.11*B.
25355+    void ConvertToGray();
25356+protected:
25357+    // Generic functions:
25358+    void DeepCopy(const PgmImage& src, PgmImage& dst);
25359+    void SetupRowPointers();
25360+
25361+    // PGM data
25362+    int m_w;
25363+    int m_h;
25364+    int m_format;
25365+    int m_colors;
25366+    int m_over_allocation;
25367+    std::vector<unsigned char> m_data;
25368+    std::string m_comment;
25369+
25370+    std::vector<unsigned char *> m_rows;
25371+};
25372+
25373+std::ostream& operator<< (std::ostream& o, const PgmImage& im);
25374diff --git a/benchmark/feature_stab/src/dbregtest/dbregtest.cpp b/benchmark/feature_stab/src/dbregtest/dbregtest.cpp
25375new file mode 100644
25376index 00000000..50873621
25377--- /dev/null
25378+++ b/benchmark/feature_stab/src/dbregtest/dbregtest.cpp
25379@@ -0,0 +1,399 @@
25380+/*
25381+ * Copyright (C) 2011 The Android Open Source Project
25382+ *
25383+ * Licensed under the Apache License, Version 2.0 (the "License");
25384+ * you may not use this file except in compliance with the License.
25385+ * You may obtain a copy of the License at
25386+ *
25387+ *      http://www.apache.org/licenses/LICENSE-2.0
25388+ *
25389+ * Unless required by applicable law or agreed to in writing, software
25390+ * distributed under the License is distributed on an "AS IS" BASIS,
25391+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25392+ * See the License for the specific language governing permissions and
25393+ * limitations under the License.
25394+ */
25395+
25396+// $Id: dbregtest.cpp,v 1.24 2011/06/17 14:04:33 mbansal Exp $
25397+#include "stdafx.h"
25398+#include "PgmImage.h"
25399+#include "../dbreg/dbreg.h"
25400+#include "../dbreg/dbstabsmooth.h"
25401+#include <db_utilities_camera.h>
25402+
25403+#include <iostream>
25404+#include <iomanip>
25405+
25406+#if PROFILE
25407+    #include <sys/time.h>
25408+#endif
25409+
25410+
25411+using namespace std;
25412+
25413+const int DEFAULT_NR_CORNERS=500;
25414+const double DEFAULT_MAX_DISPARITY=0.2;
25415+const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_AFFINE;
25416+//const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_R_T;
25417+//const int DEFAULT_MOTION_MODEL=DB_HOMOGRAPHY_TYPE_TRANSLATION;
25418+const bool DEFAULT_QUARTER_RESOLUTION=false;
25419+const unsigned int DEFAULT_REFERENCE_UPDATE_PERIOD=3;
25420+const bool DEFAULT_DO_MOTION_SMOOTHING = false;
25421+const double DEFAULT_MOTION_SMOOTHING_GAIN = 0.75;
25422+const bool DEFAULT_LINEAR_POLISH = false;
25423+const int DEFAULT_MAX_ITERATIONS = 10;
25424+
25425+void usage(string name) {
25426+
25427+  const char *helpmsg[] = {
25428+    "Function: point-based frame to reference registration.",
25429+    "  -m [rt,a,p]  : motion model, rt = rotation+translation, a = affine (default = affine).",
25430+    "  -c <int>   : number of corners (default 1000).",
25431+    "  -d <double>: search disparity as portion of image size (default 0.1).",
25432+    "  -q         : quarter the image resolution (i.e. half of each dimension) (default on)",
25433+    "  -r <int>   : the period (in nr of frames) for reference frame updates (default = 5)",
25434+    "  -s <0/1>   : motion smoothing (1 activates motion smoothing, 0 turns it off - default value = 1)",
25435+    "  -g <double>: motion smoothing gain, only used if smoothing is on (default value =0.75)",
25436+    NULL
25437+  };
25438+
25439+  cerr << "Usage: " << name << " [options] image_list.txt" << endl;
25440+
25441+  const char **p = helpmsg;
25442+
25443+  while (*p)
25444+  {
25445+    cerr << *p++ << endl;
25446+  }
25447+}
25448+
25449+void parse_cmd_line(stringstream& cmdline,
25450+            const int argc,
25451+            const string& progname,
25452+            string& image_list_file_name,
25453+            int& nr_corners,
25454+            double& max_disparity,
25455+            int& motion_model_type,
25456+            bool& quarter_resolution,
25457+            unsigned int& reference_update_period,
25458+            bool& do_motion_smoothing,
25459+            double& motion_smoothing_gain
25460+            );
25461+
25462+int main(int argc, char* argv[])
25463+{
25464+  int    nr_corners = DEFAULT_NR_CORNERS;
25465+  double max_disparity = DEFAULT_MAX_DISPARITY;
25466+  int    motion_model_type = DEFAULT_MOTION_MODEL;
25467+  bool   quarter_resolution = DEFAULT_QUARTER_RESOLUTION;
25468+
25469+  unsigned int reference_update_period = DEFAULT_REFERENCE_UPDATE_PERIOD;
25470+
25471+  bool   do_motion_smoothing = DEFAULT_DO_MOTION_SMOOTHING;
25472+  double motion_smoothing_gain = DEFAULT_MOTION_SMOOTHING_GAIN;
25473+  const bool DEFAULT_USE_SMALLER_MATCHING_WINDOW = true;
25474+
25475+  int default_nr_samples = DB_DEFAULT_NR_SAMPLES/5;
25476+
25477+  bool   use_smaller_matching_window = DEFAULT_USE_SMALLER_MATCHING_WINDOW;
25478+
25479+
25480+  bool   linear_polish = DEFAULT_LINEAR_POLISH;
25481+
25482+  if (argc < 2) {
25483+    usage(argv[0]);
25484+    exit(1);
25485+  }
25486+
25487+  stringstream cmdline;
25488+  string progname(argv[0]);
25489+  string image_list_file_name;
25490+
25491+#if PROFILE
25492+  timeval ts1, ts2, ts3, ts4;
25493+#endif
25494+
25495+  // put the options and image list file name into the cmdline stringstream
25496+  for (int c = 1; c < argc; c++)
25497+  {
25498+    cmdline << argv[c] << " ";
25499+  }
25500+
25501+  parse_cmd_line(cmdline, argc, progname, image_list_file_name, nr_corners, max_disparity, motion_model_type,quarter_resolution,reference_update_period,do_motion_smoothing,motion_smoothing_gain);
25502+
25503+  ifstream in(image_list_file_name.c_str(),ios::in);
25504+
25505+  if ( !in.is_open() )
25506+  {
25507+    cerr << "Could not open file " << image_list_file_name << ".  Exiting" << endl;
25508+
25509+    return false;
25510+  }
25511+
25512+  // feature-based image registration class:
25513+  db_FrameToReferenceRegistration reg;
25514+//  db_StabilizationSmoother stab_smoother;
25515+
25516+  // input file name:
25517+  string file_name;
25518+
25519+  // look-up tables for image warping:
25520+  float ** lut_x = NULL, **lut_y = NULL;
25521+
25522+  // if the images are color, the input is saved in color_ref:
25523+  PgmImage color_ref(0,0);
25524+
25525+  // image width, height:
25526+  int w,h;
25527+
25528+  int frame_number = 0;
25529+
25530+  while ( !in.eof() )
25531+  {
25532+    getline(in,file_name);
25533+
25534+    PgmImage ref(file_name);
25535+
25536+    if ( ref.GetDataPointer() == NULL )
25537+    {
25538+      cerr << "Could not open image" << file_name << ". Exiting." << endl;
25539+      return -1;
25540+    }
25541+
25542+    cout << ref << endl;
25543+
25544+    // color format:
25545+    int format = ref.GetFormat();
25546+
25547+    // is the input image color?:
25548+    bool color = format == PgmImage::PGM_BINARY_PIXMAP;
25549+
25550+    w = ref.GetWidth();
25551+    h = ref.GetHeight();
25552+
25553+    if ( !reg.Initialized() )
25554+    {
25555+      reg.Init(w,h,motion_model_type,DEFAULT_MAX_ITERATIONS,linear_polish,quarter_resolution,DB_POINT_STANDARDDEV,reference_update_period,do_motion_smoothing,motion_smoothing_gain,default_nr_samples,DB_DEFAULT_CHUNK_SIZE,nr_corners,max_disparity,use_smaller_matching_window);
25556+      lut_x = db_AllocImage_f(w,h);
25557+      lut_y = db_AllocImage_f(w,h);
25558+
25559+    }
25560+
25561+    if ( color )
25562+    {
25563+      // save the color image:
25564+      color_ref = ref;
25565+    }
25566+
25567+    // make a grayscale image:
25568+    ref.ConvertToGray();
25569+
25570+    // compute the homography:
25571+    double H[9],Hinv[9];
25572+    db_Identity3x3(Hinv);
25573+    db_Identity3x3(H);
25574+
25575+    bool force_reference = false;
25576+
25577+#if PROFILE
25578+    gettimeofday(&ts1, NULL);
25579+#endif
25580+
25581+    reg.AddFrame(ref.GetRowPointers(),H,false,false);
25582+    cout << reg.profile_string << std::endl;
25583+
25584+#if PROFILE
25585+    gettimeofday(&ts2, NULL);
25586+
25587+    double elapsedTime = (ts2.tv_sec - ts1.tv_sec)*1000.0; // sec to ms
25588+    elapsedTime += (ts2.tv_usec - ts1.tv_usec)/1000.0; // us to ms
25589+    cout <<"\nelapsedTime for Reg<< "<<elapsedTime<<" ms >>>>>>>>>>>>>\n";
25590+#endif
25591+
25592+    if (frame_number == 0)
25593+    {
25594+      reg.UpdateReference(ref.GetRowPointers());
25595+    }
25596+
25597+
25598+    //std::vector<int> &inlier_indices = reg.GetInliers();
25599+    int *inlier_indices = reg.GetInliers();
25600+    int num_inlier_indices = reg.GetNrInliers();
25601+    printf("[%d] #Inliers = %d\n",frame_number,num_inlier_indices);
25602+
25603+    reg.Get_H_dref_to_ins(H);
25604+
25605+    db_GenerateHomographyLut(lut_x,lut_y,w,h,H);
25606+
25607+    // create a new image and warp:
25608+    PgmImage warped(w,h,format);
25609+
25610+#if PROFILE
25611+    gettimeofday(&ts3, NULL);
25612+#endif
25613+
25614+    if ( color )
25615+      db_WarpImageLutBilinear_rgb(color_ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y);
25616+    else
25617+      db_WarpImageLut_u(ref.GetRowPointers(),warped.GetRowPointers(),w,h,lut_x,lut_y,DB_WARP_FAST);
25618+
25619+#if PROFILE
25620+    gettimeofday(&ts4, NULL);
25621+    elapsedTime = (ts4.tv_sec - ts3.tv_sec)*1000.0; // sec to ms
25622+    elapsedTime += (ts4.tv_usec - ts3.tv_usec)/1000.0;     // us to ms
25623+    cout <<"\nelapsedTime for Warp <<"<<elapsedTime<<" ms >>>>>>>>>>>>>\n";
25624+#endif
25625+
25626+    // write aligned image: name is aligned_<corresponding input file name>
25627+    stringstream s;
25628+    s << "aligned_" << file_name;
25629+    warped.WritePGM(s.str());
25630+
25631+    /*
25632+    // Get the reference and inspection corners to write to file
25633+    double *ref_corners = reg.GetRefCorners();
25634+    double *ins_corners = reg.GetInsCorners();
25635+
25636+    // get the image file name (without extension), so we
25637+    // can generate the corresponding filenames for matches
25638+    // and inliers
25639+    string file_name_root(file_name.substr(0,file_name.rfind(".")));
25640+
25641+    // write matches to file
25642+    s.str(string(""));
25643+    s << "Matches_" << file_name_root << ".txt";
25644+
25645+    ofstream  match_file(s.str().c_str());
25646+
25647+    for (int i = 0; i < reg.GetNrMatches(); i++)
25648+    {
25649+      match_file << ref_corners[3*i] << " " << ref_corners[3*i+1] << " " << ins_corners[3*i] << " " << ins_corners[3*i+1] << endl;
25650+    }
25651+
25652+    match_file.close();
25653+
25654+    // write the inlier matches to file
25655+    s.str(string(""));
25656+    s << "InlierMatches_" << file_name_root << ".txt";
25657+
25658+    ofstream inlier_match_file(s.str().c_str());
25659+
25660+    for(int i=0; i<num_inlier_indices; i++)
25661+    {
25662+      int k = inlier_indices[i];
25663+      inlier_match_file << ref_corners[3*k] << " "
25664+            << ref_corners[3*k+1] << " "
25665+            << ins_corners[3*k] << " "
25666+            << ins_corners[3*k+1] << endl;
25667+    }
25668+    inlier_match_file.close();
25669+    */
25670+
25671+    frame_number++;
25672+  }
25673+
25674+  if ( reg.Initialized() )
25675+  {
25676+    db_FreeImage_f(lut_x,h);
25677+    db_FreeImage_f(lut_y,h);
25678+  }
25679+
25680+  return 0;
25681+}
25682+
25683+void parse_cmd_line(stringstream& cmdline,
25684+            const int argc,
25685+            const string& progname,
25686+            string& image_list_file_name,
25687+            int& nr_corners,
25688+            double& max_disparity,
25689+            int& motion_model_type,
25690+            bool& quarter_resolution,
25691+            unsigned int& reference_update_period,
25692+            bool& do_motion_smoothing,
25693+            double& motion_smoothing_gain)
25694+{
25695+  // for counting down the parsed arguments.
25696+  int c = argc;
25697+
25698+  // a holder
25699+  string token;
25700+
25701+  while (cmdline >> token)
25702+  {
25703+    --c;
25704+
25705+    int pos = token.find("-");
25706+
25707+    if (pos == 0)
25708+    {
25709+      switch (token[1])
25710+      {
25711+      case 'm':
25712+    --c; cmdline >> token;
25713+    if (token.compare("rt") == 0)
25714+    {
25715+      motion_model_type = DB_HOMOGRAPHY_TYPE_R_T;
25716+    }
25717+    else if (token.compare("a") == 0)
25718+    {
25719+      motion_model_type = DB_HOMOGRAPHY_TYPE_AFFINE;
25720+    }
25721+    else if (token.compare("p") == 0)
25722+    {
25723+      motion_model_type = DB_HOMOGRAPHY_TYPE_PROJECTIVE;
25724+    }
25725+    else
25726+    {
25727+      usage(progname);
25728+      exit(1);
25729+    }
25730+    break;
25731+      case 'c':
25732+    --c; cmdline >> nr_corners;
25733+    break;
25734+      case 'd':
25735+    --c; cmdline >> max_disparity;
25736+    break;
25737+      case 'q':
25738+    quarter_resolution = true;
25739+    break;
25740+      case 'r':
25741+    --c; cmdline >> reference_update_period;
25742+    break;
25743+      case 's':
25744+    --c; cmdline >> do_motion_smoothing;
25745+    break;
25746+      case 'g':
25747+    --c; cmdline >> motion_smoothing_gain;
25748+    break;
25749+      default:
25750+    cerr << progname << "illegal option " << token << endl;
25751+      case 'h':
25752+    usage(progname);
25753+    exit(1);
25754+    break;
25755+      }
25756+    }
25757+    else
25758+    {
25759+      if (c != 1)
25760+      {
25761+    usage(progname);
25762+    exit(1);
25763+      }
25764+      else
25765+      {
25766+    --c;
25767+    image_list_file_name = token;
25768+      }
25769+    }
25770+  }
25771+
25772+  if (c != 0)
25773+  {
25774+    usage(progname);
25775+    exit(1);
25776+  }
25777+}
25778+
25779diff --git a/benchmark/feature_stab/src/dbregtest/stdafx.cpp b/benchmark/feature_stab/src/dbregtest/stdafx.cpp
25780new file mode 100644
25781index 00000000..0c703e2d
25782--- /dev/null
25783+++ b/benchmark/feature_stab/src/dbregtest/stdafx.cpp
25784@@ -0,0 +1,24 @@
25785+/*
25786+ * Copyright (C) 2011 The Android Open Source Project
25787+ *
25788+ * Licensed under the Apache License, Version 2.0 (the "License");
25789+ * you may not use this file except in compliance with the License.
25790+ * You may obtain a copy of the License at
25791+ *
25792+ *      http://www.apache.org/licenses/LICENSE-2.0
25793+ *
25794+ * Unless required by applicable law or agreed to in writing, software
25795+ * distributed under the License is distributed on an "AS IS" BASIS,
25796+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25797+ * See the License for the specific language governing permissions and
25798+ * limitations under the License.
25799+ */
25800+
25801+// stdafx.cpp : source file that includes just the standard includes
25802+// dbregtest.pch will be the pre-compiled header
25803+// stdafx.obj will contain the pre-compiled type information
25804+
25805+#include "stdafx.h"
25806+
25807+// TODO: reference any additional headers you need in STDAFX.H
25808+// and not in this file
25809diff --git a/benchmark/feature_stab/src/dbregtest/stdafx.h b/benchmark/feature_stab/src/dbregtest/stdafx.h
25810new file mode 100644
25811index 00000000..9bc06ea0
25812--- /dev/null
25813+++ b/benchmark/feature_stab/src/dbregtest/stdafx.h
25814@@ -0,0 +1,28 @@
25815+/*
25816+ * Copyright (C) 2011 The Android Open Source Project
25817+ *
25818+ * Licensed under the Apache License, Version 2.0 (the "License");
25819+ * you may not use this file except in compliance with the License.
25820+ * You may obtain a copy of the License at
25821+ *
25822+ *      http://www.apache.org/licenses/LICENSE-2.0
25823+ *
25824+ * Unless required by applicable law or agreed to in writing, software
25825+ * distributed under the License is distributed on an "AS IS" BASIS,
25826+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25827+ * See the License for the specific language governing permissions and
25828+ * limitations under the License.
25829+ */
25830+
25831+// stdafx.h : include file for standard system include files,
25832+// or project specific include files that are used frequently, but
25833+// are changed infrequently
25834+//
25835+
25836+#pragma once
25837+
25838+#include "targetver.h"
25839+
25840+#include <stdio.h>
25841+
25842+// TODO: reference additional headers your program requires here
25843diff --git a/benchmark/feature_stab/src/dbregtest/targetver.h b/benchmark/feature_stab/src/dbregtest/targetver.h
25844new file mode 100644
25845index 00000000..9272b0d6
25846--- /dev/null
25847+++ b/benchmark/feature_stab/src/dbregtest/targetver.h
25848@@ -0,0 +1,29 @@
25849+/*
25850+ * Copyright (C) 2011 The Android Open Source Project
25851+ *
25852+ * Licensed under the Apache License, Version 2.0 (the "License");
25853+ * you may not use this file except in compliance with the License.
25854+ * You may obtain a copy of the License at
25855+ *
25856+ *      http://www.apache.org/licenses/LICENSE-2.0
25857+ *
25858+ * Unless required by applicable law or agreed to in writing, software
25859+ * distributed under the License is distributed on an "AS IS" BASIS,
25860+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25861+ * See the License for the specific language governing permissions and
25862+ * limitations under the License.
25863+ */
25864+
25865+#pragma once
25866+
25867+// The following macros define the minimum required platform.  The minimum required platform
25868+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
25869+// your application.  The macros work by enabling all features available on platform versions up to and
25870+// including the version specified.
25871+
25872+// Modify the following defines if you have to target a platform prior to the ones specified below.
25873+// Refer to MSDN for the latest info on corresponding values for different platforms.
25874+#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
25875+#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
25876+#endif
25877+
25878diff --git a/benchmark/mosaic_renderer_jni.cpp b/benchmark/mosaic_renderer_jni.cpp
25879new file mode 100644
25880index 00000000..bb01e7fc
25881--- /dev/null
25882+++ b/benchmark/mosaic_renderer_jni.cpp
25883@@ -0,0 +1,762 @@
25884+/*
25885+ * Copyright (C) 2011 The Android Open Source Project
25886+ *
25887+ * Licensed under the Apache License, Version 2.0 (the "License");
25888+ * you may not use this file except in compliance with the License.
25889+ * You may obtain a copy of the License at
25890+ *
25891+ *      http://www.apache.org/licenses/LICENSE-2.0
25892+ *
25893+ * Unless required by applicable law or agreed to in writing, software
25894+ * distributed under the License is distributed on an "AS IS" BASIS,
25895+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25896+ * See the License for the specific language governing permissions and
25897+ * limitations under the License.
25898+ */
25899+
25900+#include <GLES2/gl2.h>
25901+#include <GLES2/gl2ext.h>
25902+#include <jni.h>
25903+#include <math.h>
25904+#include <stdio.h>
25905+#include <stdlib.h>
25906+#include "db_utilities_camera.h"
25907+#include "mosaic/ImageUtils.h"
25908+#include "mosaic_renderer/FrameBuffer.h"
25909+#include "mosaic_renderer/WarpRenderer.h"
25910+#include "mosaic_renderer/SurfaceTextureRenderer.h"
25911+#include "mosaic_renderer/YVURenderer.h"
25912+
25913+#include "mosaic/Log.h"
25914+#define LOG_TAG "MosaicRenderer"
25915+
25916+#include "mosaic_renderer_jni.h"
25917+
25918+// Texture handle
25919+GLuint gSurfaceTextureID[1];
25920+
25921+bool gWarpImage = true;
25922+
25923+// Low-Res input image frame in YUVA format for preview rendering and processing
25924+// and high-res YUVA input image for processing.
25925+unsigned char* gPreviewImage[NR];
25926+// Low-Res & high-res preview image width
25927+int gPreviewImageWidth[NR];
25928+// Low-Res & high-res preview image height
25929+int gPreviewImageHeight[NR];
25930+
25931+// Semaphore to protect simultaneous read/writes from gPreviewImage
25932+sem_t gPreviewImage_semaphore;
25933+
25934+// Off-screen preview FBO width (large enough to store the entire
25935+// preview mosaic).
25936+int gPreviewFBOWidth;
25937+// Off-screen preview FBO height (large enough to store the entire
25938+// preview mosaic).
25939+int gPreviewFBOHeight;
25940+
25941+// gK is the transformation to map the canonical {-1,1} vertex coordinate system
25942+// to the {0,gPreviewImageWidth[LR]} input image frame coordinate system before
25943+// applying the given affine transformation trs. gKm is the corresponding
25944+// transformation for going to the {0,gPreviewFBOWidth}.
25945+double gK[9];
25946+double gKinv[9];
25947+double gKm[9];
25948+double gKminv[9];
25949+
25950+// Shader to copy input SurfaceTexture into and RGBA FBO. The two shaders
25951+// render to the textures with dimensions corresponding to the low-res and
25952+// high-res image frames.
25953+SurfaceTextureRenderer gSurfTexRenderer[NR];
25954+// Off-screen FBOs to store the low-res and high-res RGBA copied out from
25955+// the SurfaceTexture by the gSurfTexRenderers.
25956+FrameBuffer gBufferInput[NR];
25957+
25958+// Shader to convert RGBA textures into YVU textures for processing
25959+YVURenderer gYVURenderer[NR];
25960+// Off-screen FBOs to store the low-res and high-res YVU textures for processing
25961+FrameBuffer gBufferInputYVU[NR];
25962+
25963+// Shader to translate the flip-flop FBO - gBuffer[1-current] -> gBuffer[current]
25964+WarpRenderer gWarper1;
25965+// Shader to add warped current frame to the flip-flop FBO - gBuffer[current]
25966+WarpRenderer gWarper2;
25967+// Off-screen FBOs (flip-flop) to store the result of gWarper1 & gWarper2
25968+FrameBuffer gBuffer[2];
25969+
25970+// Shader to warp and render the preview FBO to the screen
25971+WarpRenderer gPreview;
25972+
25973+// Index of the gBuffer FBO gWarper1 is going to write into
25974+int gCurrentFBOIndex = 0;
25975+
25976+// 3x3 Matrices holding the transformation of this frame (gThisH1t) and of
25977+// the last frame (gLastH1t) w.r.t the first frame.
25978+double gThisH1t[9];
25979+double gLastH1t[9];
25980+
25981+// Variables to represent the fixed position of the top-left corner of the
25982+// current frame in the previewFBO
25983+double gCenterOffsetX = 0.0f;
25984+double gCenterOffsetY = 0.0f;
25985+
25986+// X-Offset of the viewfinder (current frame) w.r.t
25987+// (gCenterOffsetX, gCenterOffsetY). This offset varies with time and is
25988+// used to pan the viewfinder across the UI layout.
25989+double gPanOffset = 0.0f;
25990+
25991+// Variables tracking the translation value for the current frame and the
25992+// last frame (both w.r.t the first frame). The difference between these
25993+// values is used to control the panning speed of the viewfinder display
25994+// on the UI screen.
25995+double gThisTx = 0.0f;
25996+double gLastTx = 0.0f;
25997+
25998+// These are the scale factors used by the gPreview shader to ensure that
25999+// the image frame is correctly scaled to the full UI layout height while
26000+// maintaining its aspect ratio
26001+double gUILayoutScalingX = 1.0f;
26002+double gUILayoutScalingY = 1.0f;
26003+
26004+// Whether the view that we will render preview FBO onto is in landscape or portrait
26005+// orientation.
26006+bool gIsLandscapeOrientation = true;
26007+
26008+// State of the viewfinder. Set to false when the viewfinder hits the UI edge.
26009+bool gPanViewfinder = true;
26010+
26011+// Affine transformation in GL 4x4 format (column-major) to warp the
26012+// last frame mosaic into the current frame coordinate system.
26013+GLfloat g_dAffinetransGL[16];
26014+double g_dAffinetrans[16];
26015+
26016+// Affine transformation in GL 4x4 format (column-major) to translate the
26017+// preview FBO across the screen (viewfinder panning).
26018+GLfloat g_dAffinetransPanGL[16];
26019+double g_dAffinetransPan[16];
26020+
26021+// XY translation in GL 4x4 format (column-major) to center the current
26022+// preview mosaic in the preview FBO
26023+GLfloat g_dTranslationToFBOCenterGL[16];
26024+double g_dTranslationToFBOCenter[16];
26025+
26026+// GL 4x4 Identity transformation
26027+GLfloat g_dAffinetransIdentGL[] = {
26028+    1., 0., 0., 0.,
26029+    0., 1., 0., 0.,
26030+    0., 0., 1., 0.,
26031+    0., 0., 0., 1.};
26032+
26033+// GL 4x4 Rotation transformation (column-majored): 90 degree
26034+GLfloat g_dAffinetransRotation90GL[] = {
26035+    0., 1., 0., 0.,
26036+    -1., 0., 0., 0.,
26037+    0., 0., 1., 0.,
26038+    0., 0., 0., 1.};
26039+
26040+// 3x3 Rotation transformation (row-majored): 90 degree
26041+double gRotation90[] = {
26042+    0., -1., 0.,
26043+    1., 0., 0.,
26044+    0., 0., 1.,};
26045+
26046+
26047+float g_dIdent3x3[] = {
26048+    1.0, 0.0, 0.0,
26049+    0.0, 1.0, 0.0,
26050+    0.0, 0.0, 1.0};
26051+
26052+const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65;
26053+
26054+static void printGLString(const char *name, GLenum s) {
26055+    const char *v = (const char *) glGetString(s);
26056+    LOGI("GL %s = %s", name, v);
26057+}
26058+
26059+// @return false if there was an error
26060+bool checkGlError(const char* op) {
26061+    GLint error = glGetError();
26062+    if (error != 0) {
26063+        LOGE("after %s() glError (0x%x)", op, error);
26064+        return false;
26065+    }
26066+    return true;
26067+}
26068+
26069+void bindSurfaceTexture(GLuint texId)
26070+{
26071+    glBindTexture(GL_TEXTURE_EXTERNAL_OES_ENUM, texId);
26072+
26073+    // Can't do mipmapping with camera source
26074+    glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MIN_FILTER,
26075+            GL_LINEAR);
26076+    glTexParameterf(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_MAG_FILTER,
26077+            GL_LINEAR);
26078+    // Clamp to edge is the only option
26079+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_S,
26080+            GL_CLAMP_TO_EDGE);
26081+    glTexParameteri(GL_TEXTURE_EXTERNAL_OES_ENUM, GL_TEXTURE_WRAP_T,
26082+            GL_CLAMP_TO_EDGE);
26083+}
26084+
26085+void ClearPreviewImage(int mID)
26086+{
26087+    unsigned char* ptr = gPreviewImage[mID];
26088+    for(int j = 0, i = 0;
26089+            j < gPreviewImageWidth[mID] * gPreviewImageHeight[mID] * 4;
26090+            j += 4)
26091+    {
26092+            ptr[i++] = 0;
26093+            ptr[i++] = 0;
26094+            ptr[i++] = 0;
26095+            ptr[i++] = 255;
26096+    }
26097+
26098+}
26099+
26100+void ConvertAffine3x3toGL4x4(double *matGL44, double *mat33)
26101+{
26102+    matGL44[0] = mat33[0];
26103+    matGL44[1] = mat33[3];
26104+    matGL44[2] = 0.0;
26105+    matGL44[3] = mat33[6];
26106+
26107+    matGL44[4] = mat33[1];
26108+    matGL44[5] = mat33[4];
26109+    matGL44[6] = 0.0;
26110+    matGL44[7] = mat33[7];
26111+
26112+    matGL44[8] = 0;
26113+    matGL44[9] = 0;
26114+    matGL44[10] = 1.0;
26115+    matGL44[11] = 0.0;
26116+
26117+    matGL44[12] = mat33[2];
26118+    matGL44[13] = mat33[5];
26119+    matGL44[14] = 0.0;
26120+    matGL44[15] = mat33[8];
26121+}
26122+
26123+bool continuePanningFBO(double panOffset) {
26124+    double normalizedScreenLimitLeft = -1.0 + VIEWPORT_BORDER_FACTOR_HORZ * 2.0;
26125+    double normalizedScreenLimitRight = 1.0 - VIEWPORT_BORDER_FACTOR_HORZ * 2.0;
26126+    double normalizedXPositionOnScreenLeft;
26127+    double normalizedXPositionOnScreenRight;
26128+
26129+    // Compute the position of the current frame in the screen coordinate system
26130+    if (gIsLandscapeOrientation) {
26131+        normalizedXPositionOnScreenLeft = (2.0 *
26132+            (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) *
26133+            gUILayoutScalingX;
26134+        normalizedXPositionOnScreenRight = (2.0 *
26135+            ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) /
26136+            gPreviewFBOWidth - 1.0) * gUILayoutScalingX;
26137+    } else {
26138+        normalizedXPositionOnScreenLeft = (2.0 *
26139+            (gCenterOffsetX + panOffset) / gPreviewFBOWidth - 1.0) *
26140+            gUILayoutScalingY;
26141+        normalizedXPositionOnScreenRight = (2.0 *
26142+            ((gCenterOffsetX + panOffset) + gPreviewImageWidth[HR]) /
26143+            gPreviewFBOWidth - 1.0) * gUILayoutScalingY;
26144+    }
26145+
26146+    // Stop the viewfinder panning if we hit the maximum border allowed for
26147+    // this UI layout
26148+    if (normalizedXPositionOnScreenRight > normalizedScreenLimitRight ||
26149+            normalizedXPositionOnScreenLeft < normalizedScreenLimitLeft) {
26150+        return false;
26151+    } else {
26152+        return true;
26153+    }
26154+}
26155+
26156+// This function computes fills the 4x4 matrices g_dAffinetrans,
26157+// and g_dAffinetransPan using the specified 3x3 affine
26158+// transformation between the first captured frame and the current frame.
26159+// The computed g_dAffinetrans is such that it warps the preview mosaic in
26160+// the last frame's coordinate system into the coordinate system of the
26161+// current frame. Thus, applying this transformation will create the current
26162+// frame mosaic but with the current frame missing. This frame will then be
26163+// pasted in by gWarper2 after translating it by g_dTranslationToFBOCenter.
26164+// The computed g_dAffinetransPan is such that it offsets the computed preview
26165+// mosaic horizontally to make the viewfinder pan within the UI layout.
26166+void UpdateWarpTransformation(float *trs)
26167+{
26168+    double H[9], Hp[9], Htemp1[9], Htemp2[9], T[9];
26169+
26170+    for(int i = 0; i < 9; i++)
26171+    {
26172+        gThisH1t[i] = trs[i];
26173+    }
26174+
26175+    // Alignment is done based on low-res data.
26176+    // To render the preview mosaic, the translation of the high-res mosaic is estimated to
26177+    // H2L_FACTOR x low-res-based tranlation.
26178+    gThisH1t[2] *= H2L_FACTOR;
26179+    gThisH1t[5] *= H2L_FACTOR;
26180+
26181+    db_Identity3x3(T);
26182+    T[2] = -gCenterOffsetX;
26183+    T[5] = -gCenterOffsetY;
26184+
26185+    // H = ( inv(gThisH1t) * gLastH1t ) * T
26186+    db_Identity3x3(Htemp1);
26187+    db_Identity3x3(Htemp2);
26188+    db_Identity3x3(H);
26189+    db_InvertAffineTransform(Htemp1, gThisH1t);
26190+    db_Multiply3x3_3x3(Htemp2, Htemp1, gLastH1t);
26191+    db_Multiply3x3_3x3(H, Htemp2, T);
26192+
26193+    for(int i = 0; i < 9; i++)
26194+    {
26195+        gLastH1t[i] = gThisH1t[i];
26196+    }
26197+
26198+    // Move the origin such that the frame is centered in the previewFBO
26199+    // i.e. H = inv(T) * H
26200+    H[2] += gCenterOffsetX;
26201+    H[5] += gCenterOffsetY;
26202+
26203+    // Hp = inv(Km) * H * Km
26204+    // Km moves the coordinate system from openGL to image pixels so
26205+    // that the alignment transform H can be applied to them.
26206+    // inv(Km) moves the coordinate system back to openGL normalized
26207+    // coordinates so that the shader can correctly render it.
26208+    db_Identity3x3(Htemp1);
26209+    db_Multiply3x3_3x3(Htemp1, H, gKm);
26210+    db_Multiply3x3_3x3(Hp, gKminv, Htemp1);
26211+
26212+    ConvertAffine3x3toGL4x4(g_dAffinetrans, Hp);
26213+
26214+    ////////////////////////////////////////////////
26215+    ////// Compute g_dAffinetransPan now...   //////
26216+    ////////////////////////////////////////////////
26217+
26218+    gThisTx = trs[2];
26219+
26220+    if(gPanViewfinder)
26221+    {
26222+        gPanOffset += (gThisTx - gLastTx) * VIEWFINDER_PAN_FACTOR_HORZ;
26223+    }
26224+
26225+    gLastTx = gThisTx;
26226+    gPanViewfinder = continuePanningFBO(gPanOffset);
26227+
26228+    db_Identity3x3(H);
26229+    H[2] = gPanOffset;
26230+
26231+    // Hp = inv(Km) * H * Km
26232+    db_Identity3x3(Htemp1);
26233+    db_Multiply3x3_3x3(Htemp1, H, gKm);
26234+    db_Multiply3x3_3x3(Hp, gKminv, Htemp1);
26235+
26236+    if (gIsLandscapeOrientation) {
26237+        ConvertAffine3x3toGL4x4(g_dAffinetransPan, Hp);
26238+    } else {
26239+        // rotate Hp by 90 degress.
26240+        db_Multiply3x3_3x3(Htemp1, gRotation90, Hp);
26241+        ConvertAffine3x3toGL4x4(g_dAffinetransPan, Htemp1);
26242+    }
26243+}
26244+
26245+void AllocateTextureMemory(int widthHR, int heightHR, int widthLR, int heightLR)
26246+{
26247+    gPreviewImageWidth[HR] = widthHR;
26248+    gPreviewImageHeight[HR] = heightHR;
26249+
26250+    gPreviewImageWidth[LR] = widthLR;
26251+    gPreviewImageHeight[LR] = heightLR;
26252+
26253+    sem_init(&gPreviewImage_semaphore, 0, 1);
26254+
26255+    sem_wait(&gPreviewImage_semaphore);
26256+    gPreviewImage[LR] = ImageUtils::allocateImage(gPreviewImageWidth[LR],
26257+            gPreviewImageHeight[LR], 4);
26258+    ClearPreviewImage(LR);
26259+    gPreviewImage[HR] = ImageUtils::allocateImage(gPreviewImageWidth[HR],
26260+            gPreviewImageHeight[HR], 4);
26261+    ClearPreviewImage(HR);
26262+    sem_post(&gPreviewImage_semaphore);
26263+
26264+    gPreviewFBOWidth = PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[HR];
26265+    gPreviewFBOHeight = PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[HR];
26266+
26267+    // The origin is such that the current frame will sit with its center
26268+    // at the center of the previewFBO
26269+    gCenterOffsetX = (gPreviewFBOWidth / 2 - gPreviewImageWidth[HR] / 2);
26270+    gCenterOffsetY = (gPreviewFBOHeight / 2 - gPreviewImageHeight[HR] / 2);
26271+
26272+    gPanOffset = 0.0f;
26273+
26274+    db_Identity3x3(gThisH1t);
26275+    db_Identity3x3(gLastH1t);
26276+
26277+    gPanViewfinder = true;
26278+
26279+    int w = gPreviewImageWidth[HR];
26280+    int h = gPreviewImageHeight[HR];
26281+
26282+    int wm = gPreviewFBOWidth;
26283+    int hm = gPreviewFBOHeight;
26284+
26285+    // K is the transformation to map the canonical [-1,1] vertex coordinate
26286+    // system to the [0,w] image coordinate system before applying the given
26287+    // affine transformation trs.
26288+    gKm[0] = wm / 2.0 - 0.5;
26289+    gKm[1] = 0.0;
26290+    gKm[2] = wm / 2.0 - 0.5;
26291+    gKm[3] = 0.0;
26292+    gKm[4] = hm / 2.0 - 0.5;
26293+    gKm[5] = hm / 2.0 - 0.5;
26294+    gKm[6] = 0.0;
26295+    gKm[7] = 0.0;
26296+    gKm[8] = 1.0;
26297+
26298+    gK[0] = w / 2.0 - 0.5;
26299+    gK[1] = 0.0;
26300+    gK[2] = w / 2.0 - 0.5;
26301+    gK[3] = 0.0;
26302+    gK[4] = h / 2.0 - 0.5;
26303+    gK[5] = h / 2.0 - 0.5;
26304+    gK[6] = 0.0;
26305+    gK[7] = 0.0;
26306+    gK[8] = 1.0;
26307+
26308+    db_Identity3x3(gKinv);
26309+    db_InvertCalibrationMatrix(gKinv, gK);
26310+
26311+    db_Identity3x3(gKminv);
26312+    db_InvertCalibrationMatrix(gKminv, gKm);
26313+
26314+    //////////////////////////////////////////
26315+    ////// Compute g_Translation now... //////
26316+    //////////////////////////////////////////
26317+    double T[9], Tp[9], Ttemp[9];
26318+
26319+    db_Identity3x3(T);
26320+    T[2] = gCenterOffsetX;
26321+    T[5] = gCenterOffsetY;
26322+
26323+    // Tp = inv(K) * T * K
26324+    db_Identity3x3(Ttemp);
26325+    db_Multiply3x3_3x3(Ttemp, T, gK);
26326+    db_Multiply3x3_3x3(Tp, gKinv, Ttemp);
26327+
26328+    ConvertAffine3x3toGL4x4(g_dTranslationToFBOCenter, Tp);
26329+
26330+    UpdateWarpTransformation(g_dIdent3x3);
26331+}
26332+
26333+void FreeTextureMemory()
26334+{
26335+    sem_wait(&gPreviewImage_semaphore);
26336+    ImageUtils::freeImage(gPreviewImage[LR]);
26337+    ImageUtils::freeImage(gPreviewImage[HR]);
26338+    sem_post(&gPreviewImage_semaphore);
26339+
26340+    sem_destroy(&gPreviewImage_semaphore);
26341+}
26342+
26343+extern "C"
26344+{
26345+    JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init(
26346+            JNIEnv * env, jobject obj);
26347+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset(
26348+            JNIEnv * env, jobject obj,  jint width, jint height,
26349+            jboolean isLandscapeOrientation);
26350+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess(
26351+            JNIEnv * env, jobject obj, jfloatArray stMatrix);
26352+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU(
26353+            JNIEnv * env, jobject obj);
26354+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step(
26355+            JNIEnv * env, jobject obj);
26356+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready(
26357+            JNIEnv * env, jobject obj);
26358+    JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping(
26359+            JNIEnv * env, jobject obj, jboolean flag);
26360+};
26361+
26362+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_MosaicRenderer_init(
26363+        JNIEnv * env, jobject obj)
26364+{
26365+    gSurfTexRenderer[LR].InitializeGLProgram();
26366+    gSurfTexRenderer[HR].InitializeGLProgram();
26367+    gYVURenderer[LR].InitializeGLProgram();
26368+    gYVURenderer[HR].InitializeGLProgram();
26369+    gWarper1.InitializeGLProgram();
26370+    gWarper2.InitializeGLProgram();
26371+    gPreview.InitializeGLProgram();
26372+    gBuffer[0].InitializeGLContext();
26373+    gBuffer[1].InitializeGLContext();
26374+    gBufferInput[LR].InitializeGLContext();
26375+    gBufferInput[HR].InitializeGLContext();
26376+    gBufferInputYVU[LR].InitializeGLContext();
26377+    gBufferInputYVU[HR].InitializeGLContext();
26378+
26379+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
26380+
26381+    glGenTextures(1, gSurfaceTextureID);
26382+    // bind the surface texture
26383+    bindSurfaceTexture(gSurfaceTextureID[0]);
26384+
26385+    return (jint) gSurfaceTextureID[0];
26386+}
26387+
26388+
26389+void calculateUILayoutScaling(int width, int height, bool isLandscape) {
26390+    if (isLandscape) {
26391+        //  __________        ______
26392+        // |__________|  =>  |______|
26393+        // (Preview FBO)      (View)
26394+        //
26395+        // Scale the preview FBO's height to the height of view and
26396+        // maintain the aspect ratio of the current frame on the screen.
26397+        gUILayoutScalingY = PREVIEW_FBO_HEIGHT_SCALE;
26398+
26399+        // Note that OpenGL scales a texture to view's width and height automatically.
26400+        // The "width / height" inverts the scaling, so as to maintain the aspect ratio
26401+        // of the current frame.
26402+        gUILayoutScalingX = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR])
26403+                / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) *  PREVIEW_FBO_HEIGHT_SCALE)
26404+                / ((float) width / height);
26405+    } else {
26406+        //                     __
26407+        //  __________        |  |
26408+        // |__________|  =>   |  |
26409+        // (Preview FBO)      |  |
26410+        //                    |__|
26411+        //                   (View)
26412+        // Scale the preview FBO's height to the width of view and
26413+        // maintain the aspect ratio of the current frame on the screen.
26414+        gUILayoutScalingX = PREVIEW_FBO_HEIGHT_SCALE;
26415+
26416+        // Note that OpenGL scales a texture to view's width and height automatically.
26417+        // The "height / width" inverts the scaling, so as to maintain the aspect ratio
26418+        // of the current frame.
26419+        gUILayoutScalingY = ((float) (PREVIEW_FBO_WIDTH_SCALE * gPreviewImageWidth[LR])
26420+                / (PREVIEW_FBO_HEIGHT_SCALE * gPreviewImageHeight[LR]) *  PREVIEW_FBO_HEIGHT_SCALE)
26421+                / ((float) height / width);
26422+
26423+    }
26424+}
26425+
26426+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_reset(
26427+        JNIEnv * env, jobject obj,  jint width, jint height, jboolean isLandscapeOrientation)
26428+{
26429+    gIsLandscapeOrientation = isLandscapeOrientation;
26430+    calculateUILayoutScaling(width, height, gIsLandscapeOrientation);
26431+
26432+    gBuffer[0].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA);
26433+    gBuffer[1].Init(gPreviewFBOWidth, gPreviewFBOHeight, GL_RGBA);
26434+
26435+    gBufferInput[LR].Init(gPreviewImageWidth[LR],
26436+            gPreviewImageHeight[LR], GL_RGBA);
26437+
26438+    gBufferInput[HR].Init(gPreviewImageWidth[HR],
26439+            gPreviewImageHeight[HR], GL_RGBA);
26440+
26441+    gBufferInputYVU[LR].Init(gPreviewImageWidth[LR],
26442+            gPreviewImageHeight[LR], GL_RGBA);
26443+
26444+    gBufferInputYVU[HR].Init(gPreviewImageWidth[HR],
26445+            gPreviewImageHeight[HR], GL_RGBA);
26446+
26447+    sem_wait(&gPreviewImage_semaphore);
26448+    ClearPreviewImage(LR);
26449+    ClearPreviewImage(HR);
26450+    sem_post(&gPreviewImage_semaphore);
26451+
26452+    // bind the surface texture
26453+    bindSurfaceTexture(gSurfaceTextureID[0]);
26454+
26455+    gSurfTexRenderer[LR].SetupGraphics(&gBufferInput[LR]);
26456+    gSurfTexRenderer[LR].Clear(0.0, 0.0, 0.0, 1.0);
26457+    gSurfTexRenderer[LR].SetViewportMatrix(1, 1, 1, 1);
26458+    gSurfTexRenderer[LR].SetScalingMatrix(1.0f, -1.0f);
26459+    gSurfTexRenderer[LR].SetInputTextureName(gSurfaceTextureID[0]);
26460+    gSurfTexRenderer[LR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM);
26461+
26462+    gSurfTexRenderer[HR].SetupGraphics(&gBufferInput[HR]);
26463+    gSurfTexRenderer[HR].Clear(0.0, 0.0, 0.0, 1.0);
26464+    gSurfTexRenderer[HR].SetViewportMatrix(1, 1, 1, 1);
26465+    gSurfTexRenderer[HR].SetScalingMatrix(1.0f, -1.0f);
26466+    gSurfTexRenderer[HR].SetInputTextureName(gSurfaceTextureID[0]);
26467+    gSurfTexRenderer[HR].SetInputTextureType(GL_TEXTURE_EXTERNAL_OES_ENUM);
26468+
26469+    gYVURenderer[LR].SetupGraphics(&gBufferInputYVU[LR]);
26470+    gYVURenderer[LR].Clear(0.0, 0.0, 0.0, 1.0);
26471+    gYVURenderer[LR].SetInputTextureName(gBufferInput[LR].GetTextureName());
26472+    gYVURenderer[LR].SetInputTextureType(GL_TEXTURE_2D);
26473+
26474+    gYVURenderer[HR].SetupGraphics(&gBufferInputYVU[HR]);
26475+    gYVURenderer[HR].Clear(0.0, 0.0, 0.0, 1.0);
26476+    gYVURenderer[HR].SetInputTextureName(gBufferInput[HR].GetTextureName());
26477+    gYVURenderer[HR].SetInputTextureType(GL_TEXTURE_2D);
26478+
26479+    // gBuffer[1-gCurrentFBOIndex] --> gWarper1 --> gBuffer[gCurrentFBOIndex]
26480+    gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
26481+    gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
26482+    gWarper1.SetViewportMatrix(1, 1, 1, 1);
26483+    gWarper1.SetScalingMatrix(1.0f, 1.0f);
26484+    gWarper1.SetInputTextureName(gBuffer[1 - gCurrentFBOIndex].GetTextureName());
26485+    gWarper1.SetInputTextureType(GL_TEXTURE_2D);
26486+
26487+    // gBufferInput[HR] --> gWarper2 --> gBuffer[gCurrentFBOIndex]
26488+    gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
26489+    gWarper2.Clear(0.0, 0.0, 0.0, 1.0);
26490+    gWarper2.SetViewportMatrix(gPreviewImageWidth[HR],
26491+            gPreviewImageHeight[HR], gBuffer[gCurrentFBOIndex].GetWidth(),
26492+            gBuffer[gCurrentFBOIndex].GetHeight());
26493+    gWarper2.SetScalingMatrix(1.0f, 1.0f);
26494+    gWarper2.SetInputTextureName(gBufferInput[HR].GetTextureName());
26495+    gWarper2.SetInputTextureType(GL_TEXTURE_2D);
26496+
26497+    gPreview.SetupGraphics(width, height);
26498+    gPreview.Clear(0.0, 0.0, 0.0, 1.0);
26499+    gPreview.SetViewportMatrix(1, 1, 1, 1);
26500+
26501+    // Scale the previewFBO so that the viewfinder window fills the layout height
26502+    // while maintaining the image aspect ratio
26503+    gPreview.SetScalingMatrix(gUILayoutScalingX, -1.0f * gUILayoutScalingY);
26504+    gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
26505+    gPreview.SetInputTextureType(GL_TEXTURE_2D);
26506+}
26507+
26508+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_preprocess(
26509+        JNIEnv * env, jobject obj, jfloatArray stMatrix)
26510+{
26511+    jfloat *stmat = env->GetFloatArrayElements(stMatrix, 0);
26512+
26513+    gSurfTexRenderer[LR].SetSTMatrix((float*) stmat);
26514+    gSurfTexRenderer[HR].SetSTMatrix((float*) stmat);
26515+
26516+    env->ReleaseFloatArrayElements(stMatrix, stmat, 0);
26517+
26518+    gSurfTexRenderer[LR].DrawTexture(g_dAffinetransIdentGL);
26519+    gSurfTexRenderer[HR].DrawTexture(g_dAffinetransIdentGL);
26520+}
26521+
26522+#ifndef now_ms
26523+#include <time.h>
26524+static double
26525+now_ms(void)
26526+{
26527+    //struct timespec res;
26528+    struct timeval res;
26529+    //clock_gettime(CLOCK_REALTIME, &res);
26530+    gettimeofday(&res, NULL);
26531+    return 1000.0*res.tv_sec + (double)res.tv_usec/1e3;
26532+}
26533+#endif
26534+
26535+
26536+
26537+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_transferGPUtoCPU(
26538+        JNIEnv * env, jobject obj)
26539+{
26540+    double t0, t1, time_c;
26541+
26542+    gYVURenderer[LR].DrawTexture();
26543+    gYVURenderer[HR].DrawTexture();
26544+
26545+    sem_wait(&gPreviewImage_semaphore);
26546+    // Bind to the input LR FBO and read the Low-Res data from there...
26547+    glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[LR].GetFrameBufferName());
26548+    t0 = now_ms();
26549+    glReadPixels(0,
26550+                 0,
26551+                 gBufferInput[LR].GetWidth(),
26552+                 gBufferInput[LR].GetHeight(),
26553+                 GL_RGBA,
26554+                 GL_UNSIGNED_BYTE,
26555+                 gPreviewImage[LR]);
26556+
26557+    checkGlError("glReadPixels LR");
26558+
26559+    // Bind to the input HR FBO and read the high-res data from there...
26560+    glBindFramebuffer(GL_FRAMEBUFFER, gBufferInputYVU[HR].GetFrameBufferName());
26561+    t0 = now_ms();
26562+    glReadPixels(0,
26563+                 0,
26564+                 gBufferInput[HR].GetWidth(),
26565+                 gBufferInput[HR].GetHeight(),
26566+                 GL_RGBA,
26567+                 GL_UNSIGNED_BYTE,
26568+                 gPreviewImage[HR]);
26569+
26570+    checkGlError("glReadPixels HR");
26571+
26572+    sem_post(&gPreviewImage_semaphore);
26573+}
26574+
26575+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_step(
26576+        JNIEnv * env, jobject obj)
26577+{
26578+    if(!gWarpImage) // ViewFinder
26579+    {
26580+        gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
26581+        gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
26582+
26583+        gWarper2.DrawTexture(g_dTranslationToFBOCenterGL);
26584+
26585+        if (gIsLandscapeOrientation) {
26586+            gPreview.DrawTexture(g_dAffinetransIdentGL);
26587+        } else {
26588+            gPreview.DrawTexture(g_dAffinetransRotation90GL);
26589+        }
26590+    }
26591+    else
26592+    {
26593+        gWarper1.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
26594+        // Clear the destination so that we can paint on it afresh
26595+        gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
26596+        gWarper1.SetInputTextureName(
26597+                gBuffer[1 - gCurrentFBOIndex].GetTextureName());
26598+        gWarper2.SetupGraphics(&gBuffer[gCurrentFBOIndex]);
26599+        gPreview.SetInputTextureName(gBuffer[gCurrentFBOIndex].GetTextureName());
26600+
26601+        gWarper1.DrawTexture(g_dAffinetransGL);
26602+        gWarper2.DrawTexture(g_dTranslationToFBOCenterGL);
26603+        gPreview.DrawTexture(g_dAffinetransPanGL);
26604+
26605+        gCurrentFBOIndex = 1 - gCurrentFBOIndex;
26606+    }
26607+}
26608+
26609+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_setWarping(
26610+        JNIEnv * env, jobject obj, jboolean flag)
26611+{
26612+    // TODO: Review this logic
26613+    if(gWarpImage != (bool) flag) //switching from viewfinder to capture or vice-versa
26614+    {
26615+        // Clear gBuffer[0]
26616+        gWarper1.SetupGraphics(&gBuffer[0]);
26617+        gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
26618+        // Clear gBuffer[1]
26619+        gWarper1.SetupGraphics(&gBuffer[1]);
26620+        gWarper1.Clear(0.0, 0.0, 0.0, 1.0);
26621+        // Clear the screen to black.
26622+        gPreview.Clear(0.0, 0.0, 0.0, 1.0);
26623+
26624+        gLastTx = 0.0f;
26625+        gPanOffset = 0.0f;
26626+        gPanViewfinder = true;
26627+
26628+        db_Identity3x3(gThisH1t);
26629+        db_Identity3x3(gLastH1t);
26630+    }
26631+
26632+    gWarpImage = (bool)flag;
26633+}
26634+
26635+
26636+JNIEXPORT void JNICALL Java_com_android_camera_panorama_MosaicRenderer_ready(
26637+        JNIEnv * env, jobject obj)
26638+{
26639+    for(int i=0; i<16; i++)
26640+    {
26641+        g_dAffinetransGL[i] = g_dAffinetrans[i];
26642+        g_dAffinetransPanGL[i] = g_dAffinetransPan[i];
26643+        g_dTranslationToFBOCenterGL[i] = g_dTranslationToFBOCenter[i];
26644+    }
26645+}
26646diff --git a/benchmark/mosaic_renderer_jni.h b/benchmark/mosaic_renderer_jni.h
26647new file mode 100644
26648index 00000000..f9b85df8
26649--- /dev/null
26650+++ b/benchmark/mosaic_renderer_jni.h
26651@@ -0,0 +1,35 @@
26652+#pragma once
26653+#include <semaphore.h>
26654+
26655+// The Preview FBO dimensions are determined from the high-res
26656+// frame dimensions (gPreviewImageWidth, gPreviewImageHeight)
26657+// using the scale factors below.
26658+const int PREVIEW_FBO_WIDTH_SCALE = 2;
26659+const int PREVIEW_FBO_HEIGHT_SCALE = 1;
26660+
26661+// The factor below determines the (horizontal) speed at which the viewfinder
26662+// will pan across the UI during capture. A value of 0.0 will keep the viewfinder
26663+// static in the center of the screen and 1.0f will make it pan at the
26664+// same speed as the device.
26665+const float VIEWFINDER_PAN_FACTOR_HORZ = 0.3f;
26666+
26667+// What fraction of the screen viewport width has been allocated to show the
26668+// arrows on the direction of motion side.
26669+const float VIEWPORT_BORDER_FACTOR_HORZ = 0.1f;
26670+
26671+const int LR = 0; // Low-resolution mode
26672+const int HR = 1; // High-resolution mode
26673+const int NR = 2; // Number of resolution modes
26674+
26675+const int H2L_FACTOR = 4; // Can be 2
26676+
26677+extern "C" void AllocateTextureMemory(int widthHR, int heightHR,
26678+        int widthLR, int heightLR);
26679+extern "C" void FreeTextureMemory();
26680+extern "C" void UpdateWarpTransformation(float *trs);
26681+
26682+extern unsigned char* gPreviewImage[NR];
26683+extern int gPreviewImageWidth[NR];
26684+extern int gPreviewImageHeight[NR];
26685+
26686+extern sem_t gPreviewImage_semaphore;
26687