diff --git a/CALIBRATION/CALIBRATION.xcodeproj/project.pbxproj b/CALIBRATION/CALIBRATION.xcodeproj/project.pbxproj new file mode 100644 index 0000000..598c76e --- /dev/null +++ b/CALIBRATION/CALIBRATION.xcodeproj/project.pbxproj @@ -0,0 +1,6013 @@ + + + + archiveVersion + 1 + classes + + objectVersion + 46 + objects + + F905D46EF2AE96B79CEF0609 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxSecondWindow.h + path + ../../../addons/ofxSecondWindow/src/ofxSecondWindow.h + sourceTree + SOURCE_ROOT + + 4373A30F72067F000063CFF4 + + children + + F6CD5194C7EEB1B621758398 + F905D46EF2AE96B79CEF0609 + + isa + PBXGroup + name + src + sourceTree + <group> + + EDD1D727C7914867117F6F92 + + children + + 4373A30F72067F000063CFF4 + + isa + PBXGroup + name + ofxSecondWindow + sourceTree + <group> + + 87B479F55285F413D96B5A45 + + fileRef + F6CD5194C7EEB1B621758398 + isa + PBXBuildFile + + F6CD5194C7EEB1B621758398 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxSecondWindow.cpp + path + ../../../addons/ofxSecondWindow/src/ofxSecondWindow.cpp + sourceTree + SOURCE_ROOT + + B2B3CC2C074F2E95CED241D8 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + windows_magic.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/windows_magic.h + sourceTree + SOURCE_ROOT + + 200174BB50406AD149EF230B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode.h + sourceTree + SOURCE_ROOT + + E3AF3027D049D507AB40880B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode_abstract.h + sourceTree + SOURCE_ROOT + + 5AE0D7789D08AD70EB9107D7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode.h + sourceTree + SOURCE_ROOT + + CC9A07986E7E8BC4F67FE001 + + children + + 751648C5D0FFBBB967F90216 + 5AE0D7789D08AD70EB9107D7 + E3AF3027D049D507AB40880B + + isa + PBXGroup + name + unicode + sourceTree + <group> + + A81AF6FC4B1FD63D16781582 + + fileRef + 751648C5D0FFBBB967F90216 + isa + PBXBuildFile + + 751648C5D0FFBBB967F90216 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + unicode.cpp + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode.cpp + sourceTree + SOURCE_ROOT + + 655EE8DEB5C4ECB817FB91AD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + uintn.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/uintn.h + sourceTree + SOURCE_ROOT + + 99D85B9D9ECE68D0ED8DC29E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + stack_trace.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/stack_trace.h + sourceTree + SOURCE_ROOT + + 08B6312D910A25F3FAB2DE34 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + serialize.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/serialize.h + sourceTree + SOURCE_ROOT + + 3A6E2829D76CBA6C2B41AEA9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + platform.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/platform.h + sourceTree + SOURCE_ROOT + + 24CA650B26E1CFA470686366 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + noncopyable.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/noncopyable.h + sourceTree + SOURCE_ROOT + + 23B8C23107F8B07C891E7D8A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + sourceTree + SOURCE_ROOT + + 87B8D031E975EB9A76234A5E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_2.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h + sourceTree + SOURCE_ROOT + + BAD4B18F907F95EE926231A6 + + children + + 49AFD4ACDBD0960C4B2F895D + 87B8D031E975EB9A76234A5E + 23B8C23107F8B07C891E7D8A + + isa + PBXGroup + name + memory_manager_stateless + sourceTree + <group> + + 49AFD4ACDBD0960C4B2F895D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_1.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h + sourceTree + SOURCE_ROOT + + C29D31730FB0B5CB905B9128 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix.h + sourceTree + SOURCE_ROOT + + 5CDB5539437B7BFA07BB4835 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + symmetric_matrix_cache_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/symmetric_matrix_cache_abstract.h + sourceTree + SOURCE_ROOT + + 25E5B701EB5BDC165F2DF194 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + symmetric_matrix_cache.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/symmetric_matrix_cache.h + sourceTree + SOURCE_ROOT + + 4B671ACA3983B56A2E1E6C49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_utilities_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_utilities_abstract.h + sourceTree + SOURCE_ROOT + + D40B7CB04EFCB56793A9154D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_utilities.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_utilities.h + sourceTree + SOURCE_ROOT + + E7D2991201D3040FCC343C33 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_trsm.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_trsm.h + sourceTree + SOURCE_ROOT + + AEE4A28F87338E2B366F3943 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_subexp_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_subexp_abstract.h + sourceTree + SOURCE_ROOT + + 275CF29F9F6E302EA3CC39C0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_subexp.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_subexp.h + sourceTree + SOURCE_ROOT + + 87F49A85F9C4184CC5CC65B2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_qr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_qr.h + sourceTree + SOURCE_ROOT + + 1CCB66E5BD14D4CDDBF86AAD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_op.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_op.h + sourceTree + SOURCE_ROOT + + 31ABEE1C91CCD3B8FA515C8C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_math_functions_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_math_functions_abstract.h + sourceTree + SOURCE_ROOT + + 67C70CF980A994969612E66B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_math_functions.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_math_functions.h + sourceTree + SOURCE_ROOT + + E49C95D2F3306510F1D76F5C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_lu.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_lu.h + sourceTree + SOURCE_ROOT + + 59521FEC8B9141FA87A36CC2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_la_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_la_abstract.h + sourceTree + SOURCE_ROOT + + 17F61530DDA2B8B681979EBA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_la.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_la.h + sourceTree + SOURCE_ROOT + + 39F9A5CDDB000E39DDB17368 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_fwd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_fwd.h + sourceTree + SOURCE_ROOT + + 3191CF6F09B2AB0EB02BD884 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_expressions.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_expressions.h + sourceTree + SOURCE_ROOT + + C0A0EF9E9FF190AC8CFC4F4A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_exp_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_exp_abstract.h + sourceTree + SOURCE_ROOT + + 7BE8671BE7DE0BB5832C9A72 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_exp.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_exp.h + sourceTree + SOURCE_ROOT + + F1D431FD749CADB0CAC492F9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_eigenvalue.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_eigenvalue.h + sourceTree + SOURCE_ROOT + + 36C3CDBDC3158A31596788EF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_default_mul.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_default_mul.h + sourceTree + SOURCE_ROOT + + EB21EA3ADDC311649BF059E5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_data_layout_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_data_layout_abstract.h + sourceTree + SOURCE_ROOT + + 2DFB2730898955BDD89EC4CE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_data_layout.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_data_layout.h + sourceTree + SOURCE_ROOT + + B5E6B871EEE8436AD0DF95DA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conv_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conv_abstract.h + sourceTree + SOURCE_ROOT + + A87F18347AF88C7D4AE5696B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conv.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conv.h + sourceTree + SOURCE_ROOT + + AF32EEE2A36AAAD543E5D3E3 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conj_trans.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conj_trans.h + sourceTree + SOURCE_ROOT + + 7EE951C9C80AD0DCDB1B48C1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_cholesky.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_cholesky.h + sourceTree + SOURCE_ROOT + + 10473BD60FE76A2833294872 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_blas_bindings.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_blas_bindings.h + sourceTree + SOURCE_ROOT + + F1206CCDEB0A39D50DB4A31A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_assign_fwd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_assign_fwd.h + sourceTree + SOURCE_ROOT + + B1E998B893F7E4148F66A475 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_assign.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_assign.h + sourceTree + SOURCE_ROOT + + EC93B468EB46C8FDA8C94EDC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_abstract.h + sourceTree + SOURCE_ROOT + + AD381357C0335B99D24BE481 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix.h + sourceTree + SOURCE_ROOT + + 0933A20B994E518CFA2790E6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + syevr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/syevr.h + sourceTree + SOURCE_ROOT + + 45BCB7612D9FBB60AB94D519 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + syev.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/syev.h + sourceTree + SOURCE_ROOT + + C7A2C9F2FBB7CBBF11409562 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + potrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/potrf.h + sourceTree + SOURCE_ROOT + + 0B7EBA8894558B7945CA4A09 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ormqr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/ormqr.h + sourceTree + SOURCE_ROOT + + E41AEAD9D228B75F62D974F5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + getrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/getrf.h + sourceTree + SOURCE_ROOT + + 71B0FD4BF94BEFED75CFAA84 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gesvd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gesvd.h + sourceTree + SOURCE_ROOT + + ECD39DA0412513D625786668 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gesdd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gesdd.h + sourceTree + SOURCE_ROOT + + 9F302AC7E036FE8648A7CC79 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + geqrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/geqrf.h + sourceTree + SOURCE_ROOT + + A098A96B509DA9C5F88CE89E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + geev.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/geev.h + sourceTree + SOURCE_ROOT + + 460BFED3116BE472629E249A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gees.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gees.h + sourceTree + SOURCE_ROOT + + 5DBA52B926F1A58092156EE8 + + children + + 478FC1C0EF37E878F11135E0 + 460BFED3116BE472629E249A + A098A96B509DA9C5F88CE89E + 9F302AC7E036FE8648A7CC79 + ECD39DA0412513D625786668 + 71B0FD4BF94BEFED75CFAA84 + E41AEAD9D228B75F62D974F5 + 0B7EBA8894558B7945CA4A09 + C7A2C9F2FBB7CBBF11409562 + 45BCB7612D9FBB60AB94D519 + 0933A20B994E518CFA2790E6 + + isa + PBXGroup + name + lapack + sourceTree + <group> + + 478FC1C0EF37E878F11135E0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + fortran_id.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/fortran_id.h + sourceTree + SOURCE_ROOT + + 44C2B72920E6B50F102F7269 + + children + + 01BB0905E394E835585A82AE + 5DBA52B926F1A58092156EE8 + AD381357C0335B99D24BE481 + EC93B468EB46C8FDA8C94EDC + B1E998B893F7E4148F66A475 + F1206CCDEB0A39D50DB4A31A + 10473BD60FE76A2833294872 + 7EE951C9C80AD0DCDB1B48C1 + AF32EEE2A36AAAD543E5D3E3 + A87F18347AF88C7D4AE5696B + B5E6B871EEE8436AD0DF95DA + 2DFB2730898955BDD89EC4CE + EB21EA3ADDC311649BF059E5 + 36C3CDBDC3158A31596788EF + F1D431FD749CADB0CAC492F9 + 7BE8671BE7DE0BB5832C9A72 + C0A0EF9E9FF190AC8CFC4F4A + 3191CF6F09B2AB0EB02BD884 + 39F9A5CDDB000E39DDB17368 + 17F61530DDA2B8B681979EBA + 59521FEC8B9141FA87A36CC2 + E49C95D2F3306510F1D76F5C + 67C70CF980A994969612E66B + 31ABEE1C91CCD3B8FA515C8C + 1CCB66E5BD14D4CDDBF86AAD + 87F49A85F9C4184CC5CC65B2 + 275CF29F9F6E302EA3CC39C0 + AEE4A28F87338E2B366F3943 + E7D2991201D3040FCC343C33 + D40B7CB04EFCB56793A9154D + 4B671ACA3983B56A2E1E6C49 + 25E5B701EB5BDC165F2DF194 + 5CDB5539437B7BFA07BB4835 + + isa + PBXGroup + name + matrix + sourceTree + <group> + + 01BB0905E394E835585A82AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cblas_constants.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/cblas_constants.h + sourceTree + SOURCE_ROOT + + 9EBA5A473DF6602B55ED5A24 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + is_kind.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/is_kind.h + sourceTree + SOURCE_ROOT + + B7FFF828FB3FC4CB1D215EE2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + remover.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/remover.h + sourceTree + SOURCE_ROOT + + 66E7E760DDF064D6668F45A4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + map_pair.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/map_pair.h + sourceTree + SOURCE_ROOT + + 6288E24AAE815FD4E7BB801D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + enumerable.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/enumerable.h + sourceTree + SOURCE_ROOT + + D921FCCC63B1E4FAFFCFE868 + + children + + 4E498923F62DF3BC70DDDEB2 + 6288E24AAE815FD4E7BB801D + 66E7E760DDF064D6668F45A4 + B7FFF828FB3FC4CB1D215EE2 + + isa + PBXGroup + name + interfaces + sourceTree + <group> + + 4E498923F62DF3BC70DDDEB2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cmd_line_parser_option.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/cmd_line_parser_option.h + sourceTree + SOURCE_ROOT + + 480C8EC00BA4CE29EF81DCBD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + vector_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/vector_abstract.h + sourceTree + SOURCE_ROOT + + 4CE94487715FC9258E27F263 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + vector.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/vector.h + sourceTree + SOURCE_ROOT + + 4770FCC900806FF4A318B9DD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + rectangle_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/rectangle_abstract.h + sourceTree + SOURCE_ROOT + + EFE7CF779199FC56C99C8301 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + rectangle.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/rectangle.h + sourceTree + SOURCE_ROOT + + 34854DEA54B6E271DDB3EC88 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + border_enumerator_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/border_enumerator_abstract.h + sourceTree + SOURCE_ROOT + + 1024DC0F73E42400BEA1BED5 + + children + + AA589AAECC2B11C988C51CD0 + 34854DEA54B6E271DDB3EC88 + EFE7CF779199FC56C99C8301 + 4770FCC900806FF4A318B9DD + 4CE94487715FC9258E27F263 + 480C8EC00BA4CE29EF81DCBD + + isa + PBXGroup + name + geometry + sourceTree + <group> + + AA589AAECC2B11C988C51CD0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + border_enumerator.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/border_enumerator.h + sourceTree + SOURCE_ROOT + + 0483F8A1ACA86368FB1BF327 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + error.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/error.h + sourceTree + SOURCE_ROOT + + A1A95627959627BD1FD18E13 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + enable_if.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/enable_if.h + sourceTree + SOURCE_ROOT + + BB0839801B8ED36BF6A65A49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dassert.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/dassert.h + sourceTree + SOURCE_ROOT + + 14C7E0F55968225EA9BFE780 + + children + + 47E8718ACC3E212F1F9C4E2D + BB0839801B8ED36BF6A65A49 + A1A95627959627BD1FD18E13 + 0483F8A1ACA86368FB1BF327 + 1024DC0F73E42400BEA1BED5 + D921FCCC63B1E4FAFFCFE868 + 9EBA5A473DF6602B55ED5A24 + 44C2B72920E6B50F102F7269 + C29D31730FB0B5CB905B9128 + BAD4B18F907F95EE926231A6 + 24CA650B26E1CFA470686366 + 3A6E2829D76CBA6C2B41AEA9 + 08B6312D910A25F3FAB2DE34 + 99D85B9D9ECE68D0ED8DC29E + 655EE8DEB5C4ECB817FB91AD + CC9A07986E7E8BC4F67FE001 + 200174BB50406AD149EF230B + B2B3CC2C074F2E95CED241D8 + + isa + PBXGroup + name + dlib + sourceTree + <group> + + D485F5AC132675EC9F9B3690 + + children + + 14C7E0F55968225EA9BFE780 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 47E8718ACC3E212F1F9C4E2D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + algs.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/algs.h + sourceTree + SOURCE_ROOT + + 44F1E3614D38B396A22DD7E7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectProjectorToolkit.h + path + ../../../addons/ofxKinectProjectorToolkit/src/ofxKinectProjectorToolkit.h + sourceTree + SOURCE_ROOT + + 3803B3BFF0E596F8697B9DCE + + children + + B9F41088D07970B50DBA136F + 44F1E3614D38B396A22DD7E7 + + isa + PBXGroup + name + src + sourceTree + <group> + + FD702F29E90B58DEC499A265 + + children + + 3803B3BFF0E596F8697B9DCE + D485F5AC132675EC9F9B3690 + + isa + PBXGroup + name + ofxKinectProjectorToolkit + sourceTree + <group> + + 12898A2212C6B1397854D45E + + fileRef + B9F41088D07970B50DBA136F + isa + PBXBuildFile + + B9F41088D07970B50DBA136F + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectProjectorToolkit.cpp + path + ../../../addons/ofxKinectProjectorToolkit/src/ofxKinectProjectorToolkit.cpp + sourceTree + SOURCE_ROOT + + DBCB84A37F9AECC254870D79 + + fileRef + D347FB65D19015303863922A + isa + PBXBuildFile + + D347FB65D19015303863922A + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Wrappers.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Wrappers.cpp + sourceTree + SOURCE_ROOT + + A6668C5B1272D7FCD5B5A16F + + fileRef + 6CEC50DB3D06414010233963 + isa + PBXBuildFile + + 6CEC50DB3D06414010233963 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Utilities.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Utilities.cpp + sourceTree + SOURCE_ROOT + + 10B69DE456AED1288FC9316B + + fileRef + A810DF70319A10353588F5DB + isa + PBXBuildFile + + A810DF70319A10353588F5DB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Tracker.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Tracker.cpp + sourceTree + SOURCE_ROOT + + 7CDAD32BE4FA46701E3552C7 + + fileRef + 5CBF6AED6A17AC0C17F63CC4 + isa + PBXBuildFile + + 5CBF6AED6A17AC0C17F63CC4 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + RunningBackground.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/RunningBackground.cpp + sourceTree + SOURCE_ROOT + + C602002DE761F9B52DB4400A + + fileRef + AE75A3FBA2C2D87D14F06FE6 + isa + PBXBuildFile + + AE75A3FBA2C2D87D14F06FE6 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ObjectFinder.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/ObjectFinder.cpp + sourceTree + SOURCE_ROOT + + 2023EF517ED2D8B397511D4B + + fileRef + B9076967F8C54A04362C04AA + isa + PBXBuildFile + + B9076967F8C54A04362C04AA + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Helpers.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Helpers.cpp + sourceTree + SOURCE_ROOT + + 5CC34D433F5806179935B89D + + fileRef + 03A75A648BC4CF1D9DEDD0CE + isa + PBXBuildFile + + 03A75A648BC4CF1D9DEDD0CE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Flow.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Flow.cpp + sourceTree + SOURCE_ROOT + + 45CC483A999BF1065A6B926C + + fileRef + 9DBD717072C35D324E101669 + isa + PBXBuildFile + + 9DBD717072C35D324E101669 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Distance.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Distance.cpp + sourceTree + SOURCE_ROOT + + 6AABAB39E82AF5CFEA23A205 + + fileRef + 5FBB4A8427353AED09174BE5 + isa + PBXBuildFile + + 5FBB4A8427353AED09174BE5 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ContourFinder.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/ContourFinder.cpp + sourceTree + SOURCE_ROOT + + D240A1DD1AE9F8E81BDBCD2B + + children + + 402C8F4015542356D362AC88 + 5FBB4A8427353AED09174BE5 + 9DBD717072C35D324E101669 + 03A75A648BC4CF1D9DEDD0CE + B9076967F8C54A04362C04AA + AE75A3FBA2C2D87D14F06FE6 + 5CBF6AED6A17AC0C17F63CC4 + A810DF70319A10353588F5DB + 6CEC50DB3D06414010233963 + D347FB65D19015303863922A + + isa + PBXGroup + name + src + sourceTree + <group> + + EBCDE831EFAE08274E799C97 + + fileRef + 402C8F4015542356D362AC88 + isa + PBXBuildFile + + 402C8F4015542356D362AC88 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Calibration.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Calibration.cpp + sourceTree + SOURCE_ROOT + + 73157AAE32787C63313C7D8E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Wrappers.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Wrappers.h + sourceTree + SOURCE_ROOT + + 84D3470A12DEE51F320224AC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Utilities.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Utilities.h + sourceTree + SOURCE_ROOT + + 70046E043EDDB466ED625C3B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Tracker.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Tracker.h + sourceTree + SOURCE_ROOT + + 6B3CDFD1A15E92F074E7D5AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + RunningBackground.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/RunningBackground.h + sourceTree + SOURCE_ROOT + + 4524C0ED0C2DD3E085CE3350 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ObjectFinder.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/ObjectFinder.h + sourceTree + SOURCE_ROOT + + 8738DE90218B1E9054A88B54 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Helpers.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Helpers.h + sourceTree + SOURCE_ROOT + + 8326CDEDA153D242D924D2B6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Flow.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Flow.h + sourceTree + SOURCE_ROOT + + D29DD28C195CD81267F3C8A1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Distance.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Distance.h + sourceTree + SOURCE_ROOT + + 178547E33CE398C7B59F08AB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ContourFinder.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/ContourFinder.h + sourceTree + SOURCE_ROOT + + 4EB038C7DF921AA8A4070286 + + children + + 58140E0F92D37844E9C8883D + 178547E33CE398C7B59F08AB + D29DD28C195CD81267F3C8A1 + 8326CDEDA153D242D924D2B6 + 8738DE90218B1E9054A88B54 + 4524C0ED0C2DD3E085CE3350 + 6B3CDFD1A15E92F074E7D5AE + 70046E043EDDB466ED625C3B + 84D3470A12DEE51F320224AC + 73157AAE32787C63313C7D8E + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 13C72B31738CA9F68523CB1C + + children + + 4EB038C7DF921AA8A4070286 + + isa + PBXGroup + name + include + sourceTree + <group> + + 85961BEC127E2550AA7756C9 + + children + + 13C72B31738CA9F68523CB1C + D240A1DD1AE9F8E81BDBCD2B + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 58140E0F92D37844E9C8883D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Calibration.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Calibration.h + sourceTree + SOURCE_ROOT + + F76B4A79BD8DE4854141CB47 + + fileRef + A2D8249D46647E3C51769CDE + isa + PBXBuildFile + + A2D8249D46647E3C51769CDE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + fdog.cpp + path + ../../../addons/ofxCv/libs/CLD/src/fdog.cpp + sourceTree + SOURCE_ROOT + + 37CF39B443ACB0F86B1351ED + + children + + B047FF96258DC01792B272DB + A2D8249D46647E3C51769CDE + + isa + PBXGroup + name + src + sourceTree + <group> + + B6840996567E78436F7ECFAB + + fileRef + B047FF96258DC01792B272DB + isa + PBXBuildFile + + B047FF96258DC01792B272DB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ETF.cpp + path + ../../../addons/ofxCv/libs/CLD/src/ETF.cpp + sourceTree + SOURCE_ROOT + + FE15469185A3A49FEC9D2292 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + myvec.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/myvec.h + sourceTree + SOURCE_ROOT + + DB0CD4C938C079DCD67222FE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imatrix.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/imatrix.h + sourceTree + SOURCE_ROOT + + CC455256CE0ECFE328853737 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + fdog.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/fdog.h + sourceTree + SOURCE_ROOT + + FEA273413D5AFD9607F56ABE + + children + + 820102E51B125101D727B3CC + CC455256CE0ECFE328853737 + DB0CD4C938C079DCD67222FE + FE15469185A3A49FEC9D2292 + + isa + PBXGroup + name + CLD + sourceTree + <group> + + 45591C11B7434576DF6996B4 + + children + + FEA273413D5AFD9607F56ABE + + isa + PBXGroup + name + include + sourceTree + <group> + + 7CC1E591490DB083FB916812 + + children + + 45591C11B7434576DF6996B4 + 37CF39B443ACB0F86B1351ED + + isa + PBXGroup + name + CLD + sourceTree + <group> + + 90D509C72729D1998E28A98F + + children + + 7CC1E591490DB083FB916812 + 85961BEC127E2550AA7756C9 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 820102E51B125101D727B3CC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ETF.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/ETF.h + sourceTree + SOURCE_ROOT + + 873F2BD1A608B2DE7BC81AFB + + children + + 325BD94FFB93161BBC68336E + + isa + PBXGroup + name + src + sourceTree + <group> + + 6025FAF6414C2CA589764D26 + + children + + 873F2BD1A608B2DE7BC81AFB + 90D509C72729D1998E28A98F + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 325BD94FFB93161BBC68336E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCv.h + path + ../../../addons/ofxCv/src/ofxCv.h + sourceTree + SOURCE_ROOT + + 5A4349E9754D6FA14C0F2A3A + + fileRef + FC5DA1C87211D4F6377DA719 + isa + PBXBuildFile + + FC5DA1C87211D4F6377DA719 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxmlparser.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxmlparser.cpp + sourceTree + SOURCE_ROOT + + 9D44DC88EF9E7991B4A09951 + + fileRef + 832BDC407620CDBA568B713D + isa + PBXBuildFile + + 832BDC407620CDBA568B713D + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxmlerror.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxmlerror.cpp + sourceTree + SOURCE_ROOT + + B21E7E5F548EEA92F368040B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + tinyxml.h + path + ../../../addons/ofxXmlSettings/libs/tinyxml.h + sourceTree + SOURCE_ROOT + + 6E54289412D2D94F45A05113 + + children + + 2B40EDA85BEB63E46785BC29 + B21E7E5F548EEA92F368040B + 832BDC407620CDBA568B713D + FC5DA1C87211D4F6377DA719 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 933A2227713C720CEFF80FD9 + + fileRef + 2B40EDA85BEB63E46785BC29 + isa + PBXBuildFile + + 2B40EDA85BEB63E46785BC29 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxml.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxml.cpp + sourceTree + SOURCE_ROOT + + 01DCC0911400F9ACF5B65578 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxXmlSettings.h + path + ../../../addons/ofxXmlSettings/src/ofxXmlSettings.h + sourceTree + SOURCE_ROOT + + 6ECEF0D76BC33727823EADFF + + children + + 50DF87D612C5AAE17AAFA6C0 + 01DCC0911400F9ACF5B65578 + + isa + PBXGroup + name + src + sourceTree + <group> + + 1F4FB5C423662B96ADFDCC0B + + children + + 6ECEF0D76BC33727823EADFF + 6E54289412D2D94F45A05113 + + isa + PBXGroup + name + ofxXmlSettings + sourceTree + <group> + + 63B57AC5BF4EF088491E0317 + + fileRef + 50DF87D612C5AAE17AAFA6C0 + isa + PBXBuildFile + + 50DF87D612C5AAE17AAFA6C0 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxXmlSettings.cpp + path + ../../../addons/ofxXmlSettings/src/ofxXmlSettings.cpp + sourceTree + SOURCE_ROOT + + 97FBD89E6180673035AD1083 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + video.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/video.hpp + sourceTree + SOURCE_ROOT + + E14D3EF03E140F5604900412 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + tracking.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/tracking.hpp + sourceTree + SOURCE_ROOT + + C58CC92A5283B95AA31D50FB + + children + + 71C98C3F44D63B39F1482A54 + E14D3EF03E140F5604900412 + 97FBD89E6180673035AD1083 + + isa + PBXGroup + name + video + sourceTree + <group> + + 71C98C3F44D63B39F1482A54 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + background_segm.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/background_segm.hpp + sourceTree + SOURCE_ROOT + + C4FB85020773DA0F09B8B6CE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ts_gtest.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts/ts_gtest.h + sourceTree + SOURCE_ROOT + + 0478E60892BF4C0731AE0763 + + children + + 7673F0AA19794A4C9517CF14 + C4FB85020773DA0F09B8B6CE + + isa + PBXGroup + name + ts + sourceTree + <group> + + 7673F0AA19794A4C9517CF14 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ts.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts/ts.hpp + sourceTree + SOURCE_ROOT + + 9B7D592E7AB311451A27C46E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + opencv.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/opencv.hpp + sourceTree + SOURCE_ROOT + + D0CAFE48EE488EEED9149670 + + children + + 97CFAD0B2F2DB004A8A3BC0B + + isa + PBXGroup + name + objdetect + sourceTree + <group> + + 97CFAD0B2F2DB004A8A3BC0B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + objdetect.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect/objdetect.hpp + sourceTree + SOURCE_ROOT + + 0F288FD421D474F4AE2684D3 + + children + + 59626D03C690200AD4E8B3A6 + + isa + PBXGroup + name + ml + sourceTree + <group> + + 59626D03C690200AD4E8B3A6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ml.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml/ml.hpp + sourceTree + SOURCE_ROOT + + 60179A75A6C5F9A54DA3A64C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + streams.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/streams.hpp + sourceTree + SOURCE_ROOT + + 8530EAD600CD792B81B2E79D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + legacy.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/legacy.hpp + sourceTree + SOURCE_ROOT + + 665780A3005496E3A4A0D9EF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + compat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/compat.hpp + sourceTree + SOURCE_ROOT + + 961A625BD21068033782887C + + children + + 5D966EA1AA66E2D55D047733 + 665780A3005496E3A4A0D9EF + 8530EAD600CD792B81B2E79D + 60179A75A6C5F9A54DA3A64C + + isa + PBXGroup + name + legacy + sourceTree + <group> + + 5D966EA1AA66E2D55D047733 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + blobtrack.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/blobtrack.hpp + sourceTree + SOURCE_ROOT + + 9B90B3EE60497170AA00BFE8 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + types_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/types_c.h + sourceTree + SOURCE_ROOT + + 9B55998E41388AD8704E4F9A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imgproc_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/imgproc_c.h + sourceTree + SOURCE_ROOT + + 3E44059DCBC2444D65660B9C + + children + + 114B872696817CC33990FC83 + 9B55998E41388AD8704E4F9A + 9B90B3EE60497170AA00BFE8 + + isa + PBXGroup + name + imgproc + sourceTree + <group> + + 114B872696817CC33990FC83 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imgproc.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/imgproc.hpp + sourceTree + SOURCE_ROOT + + AE433383D6CA170C418C8A9E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui/highgui_c.h + sourceTree + SOURCE_ROOT + + 9C99831C330874C2B245AB48 + + children + + C61D3DACE506E4A1C3A6D782 + AE433383D6CA170C418C8A9E + + isa + PBXGroup + name + highgui + sourceTree + <group> + + C61D3DACE506E4A1C3A6D782 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui/highgui.hpp + sourceTree + SOURCE_ROOT + + D902EB2409214285BCF5F191 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + stream_accessor.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/stream_accessor.hpp + sourceTree + SOURCE_ROOT + + B683B7ADA51410A7F0B13E6A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_operations.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/matrix_operations.hpp + sourceTree + SOURCE_ROOT + + E354468911BA093791076DD7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gpumat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/gpumat.hpp + sourceTree + SOURCE_ROOT + + AF9A155219FEDFA6E95454EA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gpu.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/gpu.hpp + sourceTree + SOURCE_ROOT + + 5236346776DB8ECC4B121CA3 + + children + + F886EBA3F8F05C7F74633933 + AF9A155219FEDFA6E95454EA + E354468911BA093791076DD7 + B683B7ADA51410A7F0B13E6A + D902EB2409214285BCF5F191 + + isa + PBXGroup + name + gpu + sourceTree + <group> + + F886EBA3F8F05C7F74633933 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + devmem2d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/devmem2d.hpp + sourceTree + SOURCE_ROOT + + 1E95EFD35ED9C5D97F2F015E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + timer.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/timer.h + sourceTree + SOURCE_ROOT + + 45F38573A0B0DEEC8BBC7A2C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + simplex_downhill.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/simplex_downhill.h + sourceTree + SOURCE_ROOT + + 01DAE5C2E3E0A74207B2BE49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + saving.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/saving.h + sourceTree + SOURCE_ROOT + + 7E57AAE3FAB29F87D19451BC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + sampling.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/sampling.h + sourceTree + SOURCE_ROOT + + 974AACF856A0A1B7D8F259E0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + result_set.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/result_set.h + sourceTree + SOURCE_ROOT + + ECC34C470C60F0A2AE2761B1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + random.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/random.h + sourceTree + SOURCE_ROOT + + F070AF5E3926EB2CB7A15D1B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + params.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/params.h + sourceTree + SOURCE_ROOT + + F9EC3DDC0E9F85C34B21C760 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + object_factory.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/object_factory.h + sourceTree + SOURCE_ROOT + + 8DB45DE3BD6BB97E34BDB411 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + nn_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/nn_index.h + sourceTree + SOURCE_ROOT + + 9DA0CBD43DA38386EB04C9AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + miniflann.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/miniflann.hpp + sourceTree + SOURCE_ROOT + + A15E0125B8C9B7F01DED5695 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/matrix.h + sourceTree + SOURCE_ROOT + + FEDA0B6056089762F5FA11CA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + lsh_table.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/lsh_table.h + sourceTree + SOURCE_ROOT + + B7BF51E8E757FF8A162D3662 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + lsh_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/lsh_index.h + sourceTree + SOURCE_ROOT + + 0173A3F435DECD5A4DDE0B8E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + logger.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/logger.h + sourceTree + SOURCE_ROOT + + FB213FF0567D1B312DDBD05D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + linear_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/linear_index.h + sourceTree + SOURCE_ROOT + + 2E411F99E3AB7154484B4F96 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kmeans_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kmeans_index.h + sourceTree + SOURCE_ROOT + + 758F19335D4E46A5E0DE449F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kdtree_single_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kdtree_single_index.h + sourceTree + SOURCE_ROOT + + 49EFFCF36CF194CCE0E1FAAB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kdtree_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kdtree_index.h + sourceTree + SOURCE_ROOT + + DCB56F4E9F44E31D571BC9C4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + index_testing.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/index_testing.h + sourceTree + SOURCE_ROOT + + 946187321200AC04E570E6EC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + hierarchical_clustering_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/hierarchical_clustering_index.h + sourceTree + SOURCE_ROOT + + 6B907CFBB1B0FEDE76C41AA0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + heap.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/heap.h + sourceTree + SOURCE_ROOT + + FF58A50E588D6A64EE206840 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + hdf5.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/hdf5.h + sourceTree + SOURCE_ROOT + + 0CF0AA3895D28E97D8A1E4A9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ground_truth.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/ground_truth.h + sourceTree + SOURCE_ROOT + + CBDE84185E2969BA4AB209FC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + general.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/general.h + sourceTree + SOURCE_ROOT + + 9B076DCB5B800BE9AF1B71A6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flann_base.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/flann_base.hpp + sourceTree + SOURCE_ROOT + + 6DD5A3CBB6D5BBA1C1354F1B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flann.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/flann.hpp + sourceTree + SOURCE_ROOT + + 096CB33CAD6C5A446E7026E9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dynamic_bitset.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dynamic_bitset.h + sourceTree + SOURCE_ROOT + + 36F0FF7F8D7342D220CC6319 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dummy.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dummy.h + sourceTree + SOURCE_ROOT + + FD609E2EC17FCE181DFE635F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dist.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dist.h + sourceTree + SOURCE_ROOT + + 722542BCDC94162B6A8B9B72 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + defines.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/defines.h + sourceTree + SOURCE_ROOT + + 586A8EC141BDFA82B3B0518C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + config.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/config.h + sourceTree + SOURCE_ROOT + + D5A3AFF36064B2CACAD31716 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + composite_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/composite_index.h + sourceTree + SOURCE_ROOT + + E7DDB716B5AE0DEA82DFFEDA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + autotuned_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/autotuned_index.h + sourceTree + SOURCE_ROOT + + 45410DD818BB205166E67E89 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + any.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/any.h + sourceTree + SOURCE_ROOT + + E5F6E381641665852B997FC4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + allocator.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/allocator.h + sourceTree + SOURCE_ROOT + + 1E45F8C3CCFF6847BFF957AA + + children + + 011E372AEA4DFBC1A32C2851 + E5F6E381641665852B997FC4 + 45410DD818BB205166E67E89 + E7DDB716B5AE0DEA82DFFEDA + D5A3AFF36064B2CACAD31716 + 586A8EC141BDFA82B3B0518C + 722542BCDC94162B6A8B9B72 + FD609E2EC17FCE181DFE635F + 36F0FF7F8D7342D220CC6319 + 096CB33CAD6C5A446E7026E9 + 6DD5A3CBB6D5BBA1C1354F1B + 9B076DCB5B800BE9AF1B71A6 + CBDE84185E2969BA4AB209FC + 0CF0AA3895D28E97D8A1E4A9 + FF58A50E588D6A64EE206840 + 6B907CFBB1B0FEDE76C41AA0 + 946187321200AC04E570E6EC + DCB56F4E9F44E31D571BC9C4 + 49EFFCF36CF194CCE0E1FAAB + 758F19335D4E46A5E0DE449F + 2E411F99E3AB7154484B4F96 + FB213FF0567D1B312DDBD05D + 0173A3F435DECD5A4DDE0B8E + B7BF51E8E757FF8A162D3662 + FEDA0B6056089762F5FA11CA + A15E0125B8C9B7F01DED5695 + 9DA0CBD43DA38386EB04C9AE + 8DB45DE3BD6BB97E34BDB411 + F9EC3DDC0E9F85C34B21C760 + F070AF5E3926EB2CB7A15D1B + ECC34C470C60F0A2AE2761B1 + 974AACF856A0A1B7D8F259E0 + 7E57AAE3FAB29F87D19451BC + 01DAE5C2E3E0A74207B2BE49 + 45F38573A0B0DEEC8BBC7A2C + 1E95EFD35ED9C5D97F2F015E + + isa + PBXGroup + name + flann + sourceTree + <group> + + 011E372AEA4DFBC1A32C2851 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + all_indices.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/all_indices.h + sourceTree + SOURCE_ROOT + + 86FEC009E2721D0FB23338D7 + + children + + 61339778C58D921474B5729E + + isa + PBXGroup + name + features2d + sourceTree + <group> + + 61339778C58D921474B5729E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + features2d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d/features2d.hpp + sourceTree + SOURCE_ROOT + + A9C85208C7E45FB9D1926789 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + wimage.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/wimage.hpp + sourceTree + SOURCE_ROOT + + E8AF1E9150AD818FA9D9195D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + version.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/version.hpp + sourceTree + SOURCE_ROOT + + CD8565F2F122EECA0C095526 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + types_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/types_c.h + sourceTree + SOURCE_ROOT + + E4385429A1E63ACEDC39A612 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + operations.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/operations.hpp + sourceTree + SOURCE_ROOT + + AB2AE477F82ACF17D0121166 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + mat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/mat.hpp + sourceTree + SOURCE_ROOT + + 452417865E4BFB10C9CBF8A2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + internal.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/internal.hpp + sourceTree + SOURCE_ROOT + + A2EE5E80B134EA52A8B369D2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + eigen.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/eigen.hpp + sourceTree + SOURCE_ROOT + + 087522EA37A32B8D902CAB64 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + core_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/core_c.h + sourceTree + SOURCE_ROOT + + A5A3A2F98919E2243C73199C + + children + + C66C6414C8B86FDB99ED3B70 + 087522EA37A32B8D902CAB64 + A2EE5E80B134EA52A8B369D2 + 452417865E4BFB10C9CBF8A2 + AB2AE477F82ACF17D0121166 + E4385429A1E63ACEDC39A612 + CD8565F2F122EECA0C095526 + E8AF1E9150AD818FA9D9195D + A9C85208C7E45FB9D1926789 + + isa + PBXGroup + name + core + sourceTree + <group> + + C66C6414C8B86FDB99ED3B70 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + core.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/core.hpp + sourceTree + SOURCE_ROOT + + A0399084868E7CAFB7E3D8E9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + retina.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib/retina.hpp + sourceTree + SOURCE_ROOT + + 170C3384C93B182490DDC9CC + + children + + 5A59183C98FC5E69FC90F138 + A0399084868E7CAFB7E3D8E9 + + isa + PBXGroup + name + contrib + sourceTree + <group> + + 5A59183C98FC5E69FC90F138 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + contrib.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib/contrib.hpp + sourceTree + SOURCE_ROOT + + 428EB732FD42504F37BCA78A + + children + + 67AF0E794FA186DD25454CC9 + + isa + PBXGroup + name + calib3d + sourceTree + <group> + + 0F07FE174552DEF007BF5AD5 + + children + + 428EB732FD42504F37BCA78A + 170C3384C93B182490DDC9CC + A5A3A2F98919E2243C73199C + 86FEC009E2721D0FB23338D7 + 1E45F8C3CCFF6847BFF957AA + 5236346776DB8ECC4B121CA3 + 9C99831C330874C2B245AB48 + 3E44059DCBC2444D65660B9C + 961A625BD21068033782887C + 0F288FD421D474F4AE2684D3 + D0CAFE48EE488EEED9149670 + 9B7D592E7AB311451A27C46E + 0478E60892BF4C0731AE0763 + C58CC92A5283B95AA31D50FB + + isa + PBXGroup + name + opencv2 + sourceTree + <group> + + 67AF0E794FA186DD25454CC9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + calib3d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d/calib3d.hpp + sourceTree + SOURCE_ROOT + + 7C3D9C0EAC738ED2624D264B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ml.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/ml.h + sourceTree + SOURCE_ROOT + + 9FF9126184DFBDE8A912373E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/highgui.h + sourceTree + SOURCE_ROOT + + E90542C149C83316678AB011 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxmisc.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxmisc.h + sourceTree + SOURCE_ROOT + + 319268D200F1BA567E4CCFF9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxeigen.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxeigen.hpp + sourceTree + SOURCE_ROOT + + 7101CF2125B8B2BF46AA2662 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxcore.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxcore.hpp + sourceTree + SOURCE_ROOT + + B8427966039B53A0FE69C1F0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxcore.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxcore.h + sourceTree + SOURCE_ROOT + + DB8653D6433E14BF06F3EFAF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvwimage.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvwimage.h + sourceTree + SOURCE_ROOT + + CF29BFB3FD3CAA54F336E6FD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvaux.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvaux.hpp + sourceTree + SOURCE_ROOT + + D76A59E7B3601E76351C9BDB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvaux.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvaux.h + sourceTree + SOURCE_ROOT + + 30884ECD9C171AB1B1BDFC3F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cv.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cv.hpp + sourceTree + SOURCE_ROOT + + 737B033AA777B67BA4F8F4D2 + + children + + 33FF03222909C1A0ECE43753 + 30884ECD9C171AB1B1BDFC3F + D76A59E7B3601E76351C9BDB + CF29BFB3FD3CAA54F336E6FD + DB8653D6433E14BF06F3EFAF + B8427966039B53A0FE69C1F0 + 7101CF2125B8B2BF46AA2662 + 319268D200F1BA567E4CCFF9 + E90542C149C83316678AB011 + 9FF9126184DFBDE8A912373E + 7C3D9C0EAC738ED2624D264B + + isa + PBXGroup + name + opencv + sourceTree + <group> + + F9F05170CB9BDF47DA2B6E6A + + children + + 737B033AA777B67BA4F8F4D2 + 0F07FE174552DEF007BF5AD5 + + isa + PBXGroup + name + include + sourceTree + <group> + + AAA97F42C2FE4A31ECFD0585 + + children + + F9F05170CB9BDF47DA2B6E6A + + isa + PBXGroup + name + opencv + sourceTree + <group> + + DCC60D6724B56635AE867535 + + children + + AAA97F42C2FE4A31ECFD0585 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 33FF03222909C1A0ECE43753 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cv.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cv.h + sourceTree + SOURCE_ROOT + + CE81A5E39EB3C871FDF3D4D5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxOpenCv.h + path + ../../../addons/ofxOpenCv/src/ofxOpenCv.h + sourceTree + SOURCE_ROOT + + DEA2EDC0AFD59176FDEDC222 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvShortImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvShortImage.h + sourceTree + SOURCE_ROOT + + D3301F6A0B43BB293ED97C1D + + fileRef + 8A4DD23693DFAB8EC05FAA5D + isa + PBXBuildFile + + 8A4DD23693DFAB8EC05FAA5D + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvShortImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvShortImage.cpp + sourceTree + SOURCE_ROOT + + D847EBE484F4F500F9CF2549 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvImage.h + sourceTree + SOURCE_ROOT + + 63020F16C7E8DED980111241 + + fileRef + C6151136D101F857DAE12722 + isa + PBXBuildFile + + C6151136D101F857DAE12722 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvImage.cpp + sourceTree + SOURCE_ROOT + + 516717F84C0146512C47A3EC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvHaarFinder.h + path + ../../../addons/ofxOpenCv/src/ofxCvHaarFinder.h + sourceTree + SOURCE_ROOT + + E212C821D1064B92DD953A42 + + fileRef + 9A16CBF2E8CFE43AF54FE6F5 + isa + PBXBuildFile + + 9A16CBF2E8CFE43AF54FE6F5 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvHaarFinder.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvHaarFinder.cpp + sourceTree + SOURCE_ROOT + + 9A048549F08C6DFFA79E6DEF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvGrayscaleImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvGrayscaleImage.h + sourceTree + SOURCE_ROOT + + FB09C6B2A1DA0EA217240CB8 + + fileRef + 057122A817D12571F8C0C7A4 + isa + PBXBuildFile + + 057122A817D12571F8C0C7A4 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvGrayscaleImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvGrayscaleImage.cpp + sourceTree + SOURCE_ROOT + + F7269F96AC34A2B44A680D03 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvFloatImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvFloatImage.h + sourceTree + SOURCE_ROOT + + 169D3C72FDE6C5590A1616F5 + + fileRef + 7B6A03390302D5A2C9F0E4AB + isa + PBXBuildFile + + 7B6A03390302D5A2C9F0E4AB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvFloatImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvFloatImage.cpp + sourceTree + SOURCE_ROOT + + C1C56D20A1A57DC44096BFE7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvContourFinder.h + path + ../../../addons/ofxOpenCv/src/ofxCvContourFinder.h + sourceTree + SOURCE_ROOT + + 1D5F3298C2FA073628012944 + + fileRef + C76DE5C29BDBD2CAA1DD0021 + isa + PBXBuildFile + + C76DE5C29BDBD2CAA1DD0021 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvContourFinder.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvContourFinder.cpp + sourceTree + SOURCE_ROOT + + 8E79CF8911DFABAFE23EA45B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvConstants.h + path + ../../../addons/ofxOpenCv/src/ofxCvConstants.h + sourceTree + SOURCE_ROOT + + D5BB6F0357B6422E1B1656B4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvColorImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvColorImage.h + sourceTree + SOURCE_ROOT + + 250A95BA26587BE85DB0A353 + + fileRef + CE9C7160245B19131DAE6128 + isa + PBXBuildFile + + CE9C7160245B19131DAE6128 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvColorImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvColorImage.cpp + sourceTree + SOURCE_ROOT + + C756CAAFD542831674E15FE6 + + children + + 603F2267D449084A4187A049 + CE9C7160245B19131DAE6128 + D5BB6F0357B6422E1B1656B4 + 8E79CF8911DFABAFE23EA45B + C76DE5C29BDBD2CAA1DD0021 + C1C56D20A1A57DC44096BFE7 + 7B6A03390302D5A2C9F0E4AB + F7269F96AC34A2B44A680D03 + 057122A817D12571F8C0C7A4 + 9A048549F08C6DFFA79E6DEF + 9A16CBF2E8CFE43AF54FE6F5 + 516717F84C0146512C47A3EC + C6151136D101F857DAE12722 + D847EBE484F4F500F9CF2549 + 8A4DD23693DFAB8EC05FAA5D + DEA2EDC0AFD59176FDEDC222 + CE81A5E39EB3C871FDF3D4D5 + + isa + PBXGroup + name + src + sourceTree + <group> + + A0B90D3B0ADB9C1716816714 + + children + + C756CAAFD542831674E15FE6 + DCC60D6724B56635AE867535 + + isa + PBXGroup + name + ofxOpenCv + sourceTree + <group> + + 603F2267D449084A4187A049 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvBlob.h + path + ../../../addons/ofxOpenCv/src/ofxCvBlob.h + sourceTree + SOURCE_ROOT + + 2C171637C399A50881F147E9 + + children + + 8B25248CC7F2228B1CEF2EB1 + + isa + PBXGroup + name + libusb-1.0 + sourceTree + <group> + + 1AE6862ED862CA18468E0CCD + + children + + 2C171637C399A50881F147E9 + + isa + PBXGroup + name + include + sourceTree + <group> + + 65726280742CD54BF368BDB8 + + children + + 1AE6862ED862CA18468E0CCD + + isa + PBXGroup + name + libusb-1.0 + sourceTree + <group> + + 8B25248CC7F2228B1CEF2EB1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libusb.h + path + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0/libusb.h + sourceTree + SOURCE_ROOT + + B4A0A006318C06E07DDF19D6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + usb_libusb10.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/usb_libusb10.h + sourceTree + SOURCE_ROOT + + 255A7B680DC81E543C875794 + + fileRef + 28F9707464BA3FF98E05096C + isa + PBXBuildFile + + 28F9707464BA3FF98E05096C + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + usb_libusb10.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/usb_libusb10.c + sourceTree + SOURCE_ROOT + + 49BEEB2DFA5319D55AA6899F + + fileRef + BF2F2AA872288D30F53983EF + isa + PBXBuildFile + + BF2F2AA872288D30F53983EF + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + tilt.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/tilt.c + sourceTree + SOURCE_ROOT + + 3CABCA8EA52D11C95F7A1309 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + registration.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/registration.h + sourceTree + SOURCE_ROOT + + D31F5C1B140C59B2AF1533A8 + + fileRef + 71958293AC5292DE4B7C619D + isa + PBXBuildFile + + 71958293AC5292DE4B7C619D + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + registration.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/registration.c + sourceTree + SOURCE_ROOT + + 093C9EBFCAB5D2649ACF4D0C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + loader.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/loader.h + sourceTree + SOURCE_ROOT + + FCC16AB16073FF0581F50ED7 + + fileRef + FE25F20F363BC625B852BFBC + isa + PBXBuildFile + + FE25F20F363BC625B852BFBC + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + loader.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/loader.c + sourceTree + SOURCE_ROOT + + 3175B69741F3AE805AD3F527 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + keep_alive.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/keep_alive.h + sourceTree + SOURCE_ROOT + + 21A059755481CC0BF969FD2D + + fileRef + A3528DDFF05B00283552455D + isa + PBXBuildFile + + A3528DDFF05B00283552455D + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + keep_alive.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/keep_alive.c + sourceTree + SOURCE_ROOT + + 83C70000C4AE60283CC77EB9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + freenect_internal.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/freenect_internal.h + sourceTree + SOURCE_ROOT + + D097EE679E29AD7B5E2CDFCD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flags.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/flags.h + sourceTree + SOURCE_ROOT + + E55DEEF784A10419E444669E + + fileRef + 682082DEC78C75C8FB18B7DB + isa + PBXBuildFile + + 682082DEC78C75C8FB18B7DB + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + flags.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/flags.c + sourceTree + SOURCE_ROOT + + F4135EEFC911E9ED211FB6F9 + + fileRef + CF528C0E8DBFF5C31E8D6529 + isa + PBXBuildFile + + CF528C0E8DBFF5C31E8D6529 + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + core.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/core.c + sourceTree + SOURCE_ROOT + + 241AAF7769D555E4ECD57E17 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cameras.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/cameras.h + sourceTree + SOURCE_ROOT + + ACE7DC9A3223ED5EE1B80074 + + fileRef + 3DBD37876A11E46E4D7069B3 + isa + PBXBuildFile + + 3DBD37876A11E46E4D7069B3 + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + cameras.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/cameras.c + sourceTree + SOURCE_ROOT + + ED6E9BDB447DB965EE6F1FA6 + + children + + 34FC4C582EA5ED68F36013CD + 3DBD37876A11E46E4D7069B3 + 241AAF7769D555E4ECD57E17 + CF528C0E8DBFF5C31E8D6529 + 682082DEC78C75C8FB18B7DB + D097EE679E29AD7B5E2CDFCD + 83C70000C4AE60283CC77EB9 + A3528DDFF05B00283552455D + 3175B69741F3AE805AD3F527 + FE25F20F363BC625B852BFBC + 093C9EBFCAB5D2649ACF4D0C + 71958293AC5292DE4B7C619D + 3CABCA8EA52D11C95F7A1309 + BF2F2AA872288D30F53983EF + 28F9707464BA3FF98E05096C + B4A0A006318C06E07DDF19D6 + + isa + PBXGroup + name + src + sourceTree + <group> + + 0F8F016776681D468C0D0949 + + fileRef + 34FC4C582EA5ED68F36013CD + isa + PBXBuildFile + + 34FC4C582EA5ED68F36013CD + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + audio.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/audio.c + sourceTree + SOURCE_ROOT + + E5F13FDAE691A5804F4D2DDB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect.h + sourceTree + SOURCE_ROOT + + BCF95CE25C02631B7BF14CB3 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect-registration.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect-registration.h + sourceTree + SOURCE_ROOT + + 6DFA2B327764FCDA2A8D882F + + children + + 44A9633110288F985368AD7D + BCF95CE25C02631B7BF14CB3 + E5F13FDAE691A5804F4D2DDB + + isa + PBXGroup + name + include + sourceTree + <group> + + 32687044708CDA9EDA265387 + + children + + 6DFA2B327764FCDA2A8D882F + ED6E9BDB447DB965EE6F1FA6 + + isa + PBXGroup + name + libfreenect + sourceTree + <group> + + F4101FC676C210E28DCB3220 + + children + + 32687044708CDA9EDA265387 + 65726280742CD54BF368BDB8 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 44A9633110288F985368AD7D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect-audio.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect-audio.h + sourceTree + SOURCE_ROOT + + 44EF97BDD915E758777A9A8C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinect.h + path + ../../../addons/ofxKinect/src/ofxKinect.h + sourceTree + SOURCE_ROOT + + 686B0DF6249B52E1A85B39EC + + fileRef + 7ED9FFC7D08DA194C2CE7D09 + isa + PBXBuildFile + + 7ED9FFC7D08DA194C2CE7D09 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinect.cpp + path + ../../../addons/ofxKinect/src/ofxKinect.cpp + sourceTree + SOURCE_ROOT + + B8A2CBF3E24E6E5026B13A90 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxBase3DVideo.h + path + ../../../addons/ofxKinect/src/ofxBase3DVideo.h + sourceTree + SOURCE_ROOT + + 03A9E977F3814A55A4FA3B4E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectExtras.h + path + ../../../addons/ofxKinect/src/extra/ofxKinectExtras.h + sourceTree + SOURCE_ROOT + + 6E7134DE536888BE82D56327 + + children + + 01438542609FC64F1EC60EEB + 03A9E977F3814A55A4FA3B4E + + isa + PBXGroup + name + extra + sourceTree + <group> + + F3D2DB7201EFA9F7958F421E + + children + + 6E7134DE536888BE82D56327 + B8A2CBF3E24E6E5026B13A90 + 7ED9FFC7D08DA194C2CE7D09 + 44EF97BDD915E758777A9A8C + + isa + PBXGroup + name + src + sourceTree + <group> + + 9683228C705CA3FF4F2EA945 + + children + + F3D2DB7201EFA9F7958F421E + F4101FC676C210E28DCB3220 + + isa + PBXGroup + name + ofxKinect + sourceTree + <group> + + 7ADB04AF67C568EAFAEBA546 + + fileRef + 01438542609FC64F1EC60EEB + isa + PBXBuildFile + + 01438542609FC64F1EC60EEB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectExtras.cpp + path + ../../../addons/ofxKinect/src/extra/ofxKinectExtras.cpp + sourceTree + SOURCE_ROOT + + BB4B014C10F69532006C3DED + + children + + 9683228C705CA3FF4F2EA945 + A0B90D3B0ADB9C1716816714 + 1F4FB5C423662B96ADFDCC0B + 6025FAF6414C2CA589764D26 + FD702F29E90B58DEC499A265 + EDD1D727C7914867117F6F92 + + isa + PBXGroup + name + addons + sourceTree + <group> + + BBAB23BE13894E4700AA2426 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + GLUT.framework + path + ../../../libs/glut/lib/osx/GLUT.framework + sourceTree + <group> + + BBAB23C913894ECA00AA2426 + + children + + E7F985F515E0DE99003869B5 + E4C2424410CC5A17004149E2 + E4C2424510CC5A17004149E2 + E4C2424610CC5A17004149E2 + E45BE9710E8CC7DD009D7055 + E45BE9720E8CC7DD009D7055 + E45BE9730E8CC7DD009D7055 + E45BE9750E8CC7DD009D7055 + E45BE9760E8CC7DD009D7055 + E45BE9770E8CC7DD009D7055 + E45BE9790E8CC7DD009D7055 + E45BE97A0E8CC7DD009D7055 + E7E077E415D3B63C0020DFD4 + E7E077E715D3B6510020DFD4 + + isa + PBXGroup + name + system frameworks + sourceTree + <group> + + BBAB23CA13894EDB00AA2426 + + children + + BBAB23BE13894E4700AA2426 + + isa + PBXGroup + name + 3rd party frameworks + sourceTree + <group> + + BBAB23CB13894F3D00AA2426 + + fileRef + BBAB23BE13894E4700AA2426 + isa + PBXBuildFile + + E4328143138ABC890047C5CB + + isa + PBXFileReference + lastKnownFileType + wrapper.pb-project + name + openFrameworksLib.xcodeproj + path + ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj + sourceTree + SOURCE_ROOT + + E4328144138ABC890047C5CB + + children + + E4328148138ABC890047C5CB + + isa + PBXGroup + name + Products + sourceTree + <group> + + E4328147138ABC890047C5CB + + containerPortal + E4328143138ABC890047C5CB + isa + PBXContainerItemProxy + proxyType + 2 + remoteGlobalIDString + E4B27C1510CBEB8E00536013 + remoteInfo + openFrameworks + + E4328148138ABC890047C5CB + + fileType + archive.ar + isa + PBXReferenceProxy + path + openFrameworksDebug.a + remoteRef + E4328147138ABC890047C5CB + sourceTree + BUILT_PRODUCTS_DIR + + E4328149138ABC9F0047C5CB + + fileRef + E4328148138ABC890047C5CB + isa + PBXBuildFile + + E45BE5980E8CC70C009D7055 + + children + + BBAB23CA13894EDB00AA2426 + BBAB23C913894ECA00AA2426 + + isa + PBXGroup + name + frameworks + sourceTree + <group> + + E45BE9710E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AGL.framework + path + /System/Library/Frameworks/AGL.framework + sourceTree + <absolute> + + E45BE9720E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + ApplicationServices.framework + path + /System/Library/Frameworks/ApplicationServices.framework + sourceTree + <absolute> + + E45BE9730E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AudioToolbox.framework + path + /System/Library/Frameworks/AudioToolbox.framework + sourceTree + <absolute> + + E45BE9750E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreAudio.framework + path + /System/Library/Frameworks/CoreAudio.framework + sourceTree + <absolute> + + E45BE9760E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreFoundation.framework + path + /System/Library/Frameworks/CoreFoundation.framework + sourceTree + <absolute> + + E45BE9770E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreServices.framework + path + /System/Library/Frameworks/CoreServices.framework + sourceTree + <absolute> + + E45BE9790E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + OpenGL.framework + path + /System/Library/Frameworks/OpenGL.framework + sourceTree + <absolute> + + E45BE97A0E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + QuickTime.framework + path + /System/Library/Frameworks/QuickTime.framework + sourceTree + <absolute> + + E45BE97B0E8CC7DD009D7055 + + fileRef + E45BE9710E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97C0E8CC7DD009D7055 + + fileRef + E45BE9720E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97D0E8CC7DD009D7055 + + fileRef + E45BE9730E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97F0E8CC7DD009D7055 + + fileRef + E45BE9750E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9800E8CC7DD009D7055 + + fileRef + E45BE9760E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9810E8CC7DD009D7055 + + fileRef + E45BE9770E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9830E8CC7DD009D7055 + + fileRef + E45BE9790E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9840E8CC7DD009D7055 + + fileRef + E45BE97A0E8CC7DD009D7055 + isa + PBXBuildFile + + E4B69B4A0A3A1720003C02F2 + + children + + E4B6FCAD0C3E899E008CF71C + E4EB6923138AFD0F00A09F29 + E4B69E1C0A3A1BDC003C02F2 + E4EEC9E9138DF44700A80321 + BB4B014C10F69532006C3DED + E45BE5980E8CC70C009D7055 + E4B69B5B0A3A1756003C02F2 + + isa + PBXGroup + sourceTree + <group> + + E4B69B4C0A3A1720003C02F2 + + attributes + + LastUpgradeCheck + 0460 + + buildConfigurationList + E4B69B4D0A3A1720003C02F2 + compatibilityVersion + Xcode 3.2 + developmentRegion + English + hasScannedForEncodings + 0 + isa + PBXProject + knownRegions + + English + Japanese + French + German + + mainGroup + E4B69B4A0A3A1720003C02F2 + productRefGroup + E4B69B4A0A3A1720003C02F2 + projectDirPath + + projectReferences + + + ProductGroup + E4328144138ABC890047C5CB + ProjectRef + E4328143138ABC890047C5CB + + + projectRoot + + targets + + E4B69B5A0A3A1756003C02F2 + + + E4B69B4D0A3A1720003C02F2 + + buildConfigurations + + E4B69B4E0A3A1720003C02F2 + E4B69B4F0A3A1720003C02F2 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + E4B69B4E0A3A1720003C02F2 + + baseConfigurationReference + E4EB6923138AFD0F00A09F29 + buildSettings + + OTHER_LDFLAGS + + $(OF_CORE_LIBS) + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx/usb-1.0.a + ../../../addons/ofxOpenCv/libs/opencv/lib/osx/opencv.a + + HEADER_SEARCH_PATHS + + $(OF_CORE_HEADERS) + ../../../addons/ofxKinect/libs + ../../../addons/ofxKinect/libs/libfreenect + ../../../addons/ofxKinect/libs/libfreenect/include + ../../../addons/ofxKinect/libs/libfreenect/platform + ../../../addons/ofxKinect/libs/libfreenect/src + ../../../addons/ofxKinect/libs/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/include + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/lib + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx + ../../../addons/ofxKinect/libs/libusb-win32 + ../../../addons/ofxKinect/src + ../../../addons/ofxKinect/src/extra + ../../../addons/ofxOpenCv/libs + ../../../addons/ofxOpenCv/libs/opencv + ../../../addons/ofxOpenCv/libs/opencv/include + ../../../addons/ofxOpenCv/libs/opencv/include/opencv + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2 + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video + ../../../addons/ofxOpenCv/libs/opencv/lib + ../../../addons/ofxOpenCv/libs/opencv/lib/osx + ../../../addons/ofxOpenCv/src + ../../../addons/ofxXmlSettings/libs + ../../../addons/ofxXmlSettings/src + ../../../addons/ofxCv/libs + ../../../addons/ofxCv/libs/CLD + ../../../addons/ofxCv/libs/CLD/include + ../../../addons/ofxCv/libs/CLD/include/CLD + ../../../addons/ofxCv/libs/CLD/src + ../../../addons/ofxCv/libs/ofxCv + ../../../addons/ofxCv/libs/ofxCv/include + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv + ../../../addons/ofxCv/libs/ofxCv/src + ../../../addons/ofxCv/src + ../../../addons/ofxKinectProjectorToolkit/libs + ../../../addons/ofxKinectProjectorToolkit/libs/dlib + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode + ../../../addons/ofxKinectProjectorToolkit/src + ../../../addons/ofxSecondWindow/libs + ../../../addons/ofxSecondWindow/src + + ARCHS + $(NATIVE_ARCH) + CONFIGURATION_BUILD_DIR + $(SRCROOT)/bin/ + COPY_PHASE_STRIP + NO + DEAD_CODE_STRIPPING + YES + GCC_AUTO_VECTORIZATION + YES + GCC_ENABLE_SSE3_EXTENSIONS + YES + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS + YES + GCC_INLINES_ARE_PRIVATE_EXTERN + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS + YES + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO + NO + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL + NO + GCC_WARN_UNINITIALIZED_AUTOS + NO + GCC_WARN_UNUSED_VALUE + NO + GCC_WARN_UNUSED_VARIABLE + NO + MACOSX_DEPLOYMENT_TARGET + 10.6 + OTHER_CPLUSPLUSFLAGS + + -D__MACOSX_CORE__ + -lpthread + -mtune=native + + SDKROOT + macosx + + isa + XCBuildConfiguration + name + Debug + + E4B69B4F0A3A1720003C02F2 + + baseConfigurationReference + E4EB6923138AFD0F00A09F29 + buildSettings + + OTHER_LDFLAGS + + $(OF_CORE_LIBS) + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx/usb-1.0.a + ../../../addons/ofxOpenCv/libs/opencv/lib/osx/opencv.a + + HEADER_SEARCH_PATHS + + $(OF_CORE_HEADERS) + ../../../addons/ofxKinect/libs + ../../../addons/ofxKinect/libs/libfreenect + ../../../addons/ofxKinect/libs/libfreenect/include + ../../../addons/ofxKinect/libs/libfreenect/platform + ../../../addons/ofxKinect/libs/libfreenect/src + ../../../addons/ofxKinect/libs/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/include + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/lib + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx + ../../../addons/ofxKinect/libs/libusb-win32 + ../../../addons/ofxKinect/src + ../../../addons/ofxKinect/src/extra + ../../../addons/ofxOpenCv/libs + ../../../addons/ofxOpenCv/libs/opencv + ../../../addons/ofxOpenCv/libs/opencv/include + ../../../addons/ofxOpenCv/libs/opencv/include/opencv + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2 + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video + ../../../addons/ofxOpenCv/libs/opencv/lib + ../../../addons/ofxOpenCv/libs/opencv/lib/osx + ../../../addons/ofxOpenCv/src + ../../../addons/ofxXmlSettings/libs + ../../../addons/ofxXmlSettings/src + ../../../addons/ofxCv/libs + ../../../addons/ofxCv/libs/CLD + ../../../addons/ofxCv/libs/CLD/include + ../../../addons/ofxCv/libs/CLD/include/CLD + ../../../addons/ofxCv/libs/CLD/src + ../../../addons/ofxCv/libs/ofxCv + ../../../addons/ofxCv/libs/ofxCv/include + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv + ../../../addons/ofxCv/libs/ofxCv/src + ../../../addons/ofxCv/src + ../../../addons/ofxKinectProjectorToolkit/libs + ../../../addons/ofxKinectProjectorToolkit/libs/dlib + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode + ../../../addons/ofxKinectProjectorToolkit/src + ../../../addons/ofxSecondWindow/libs + ../../../addons/ofxSecondWindow/src + + ARCHS + $(NATIVE_ARCH) + CONFIGURATION_BUILD_DIR + $(SRCROOT)/bin/ + COPY_PHASE_STRIP + YES + DEAD_CODE_STRIPPING + YES + GCC_AUTO_VECTORIZATION + YES + GCC_ENABLE_SSE3_EXTENSIONS + YES + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS + YES + GCC_INLINES_ARE_PRIVATE_EXTERN + NO + GCC_OPTIMIZATION_LEVEL + 3 + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_UNROLL_LOOPS + YES + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS + YES + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO + NO + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL + NO + GCC_WARN_UNINITIALIZED_AUTOS + NO + GCC_WARN_UNUSED_VALUE + NO + GCC_WARN_UNUSED_VARIABLE + NO + MACOSX_DEPLOYMENT_TARGET + 10.6 + OTHER_CPLUSPLUSFLAGS + + -D__MACOSX_CORE__ + -lpthread + -mtune=native + + SDKROOT + macosx + + isa + XCBuildConfiguration + name + Release + + E4B69B580A3A1756003C02F2 + + buildActionMask + 2147483647 + files + + E4B69E200A3A1BDC003C02F2 + E4B69E210A3A1BDC003C02F2 + 7ADB04AF67C568EAFAEBA546 + 686B0DF6249B52E1A85B39EC + 0F8F016776681D468C0D0949 + ACE7DC9A3223ED5EE1B80074 + F4135EEFC911E9ED211FB6F9 + E55DEEF784A10419E444669E + 21A059755481CC0BF969FD2D + FCC16AB16073FF0581F50ED7 + D31F5C1B140C59B2AF1533A8 + 49BEEB2DFA5319D55AA6899F + 255A7B680DC81E543C875794 + 250A95BA26587BE85DB0A353 + 1D5F3298C2FA073628012944 + 169D3C72FDE6C5590A1616F5 + FB09C6B2A1DA0EA217240CB8 + E212C821D1064B92DD953A42 + 63020F16C7E8DED980111241 + D3301F6A0B43BB293ED97C1D + 63B57AC5BF4EF088491E0317 + 933A2227713C720CEFF80FD9 + 9D44DC88EF9E7991B4A09951 + 5A4349E9754D6FA14C0F2A3A + B6840996567E78436F7ECFAB + F76B4A79BD8DE4854141CB47 + EBCDE831EFAE08274E799C97 + 6AABAB39E82AF5CFEA23A205 + 45CC483A999BF1065A6B926C + 5CC34D433F5806179935B89D + 2023EF517ED2D8B397511D4B + C602002DE761F9B52DB4400A + 7CDAD32BE4FA46701E3552C7 + 10B69DE456AED1288FC9316B + A6668C5B1272D7FCD5B5A16F + DBCB84A37F9AECC254870D79 + 12898A2212C6B1397854D45E + A81AF6FC4B1FD63D16781582 + 87B479F55285F413D96B5A45 + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4B69B590A3A1756003C02F2 + + buildActionMask + 2147483647 + files + + E7F985F815E0DEA3003869B5 + E7E077E815D3B6510020DFD4 + E4EB6799138ADC1D00A09F29 + E4328149138ABC9F0047C5CB + E45BE97B0E8CC7DD009D7055 + E45BE97C0E8CC7DD009D7055 + E45BE97D0E8CC7DD009D7055 + E45BE97F0E8CC7DD009D7055 + E45BE9800E8CC7DD009D7055 + E45BE9810E8CC7DD009D7055 + E45BE9830E8CC7DD009D7055 + E45BE9840E8CC7DD009D7055 + E4C2424710CC5A17004149E2 + E4C2424810CC5A17004149E2 + E4C2424910CC5A17004149E2 + E7E077E515D3B63C0020DFD4 + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4B69B5A0A3A1756003C02F2 + + buildConfigurationList + E4B69B5F0A3A1757003C02F2 + buildPhases + + E4B69B580A3A1756003C02F2 + E4B69B590A3A1756003C02F2 + E4B6FFFD0C3F9AB9008CF71C + E4C2427710CC5ABF004149E2 + + buildRules + + dependencies + + E4EEB9AC138B136A00A80321 + + isa + PBXNativeTarget + name + CALIBRATION + productName + myOFApp + productReference + E4B69B5B0A3A1756003C02F2 + productType + com.apple.product-type.application + + E4B69B5B0A3A1756003C02F2 + + explicitFileType + wrapper.application + includeInIndex + 0 + isa + PBXFileReference + path + CALIBRATIONDebug.app + sourceTree + BUILT_PRODUCTS_DIR + + E4B69B5F0A3A1757003C02F2 + + buildConfigurations + + E4B69B600A3A1757003C02F2 + E4B69B610A3A1757003C02F2 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + E4B69B600A3A1757003C02F2 + + buildSettings + + COMBINE_HIDPI_IMAGES + YES + COPY_PHASE_STRIP + NO + FRAMEWORK_SEARCH_PATHS + + $(inherited) + $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 + "$(SRCROOT)/../../../libs/glut/lib/osx" + GCC_DYNAMIC_NO_PIC + NO + GCC_GENERATE_DEBUGGING_SYMBOLS + YES + GCC_MODEL_TUNING + NONE + ICON + $(ICON_NAME_DEBUG) + ICON_FILE + $(ICON_FILE_PATH)$(ICON) + INFOPLIST_FILE + openFrameworks-Info.plist + INSTALL_PATH + $(HOME)/Applications + LIBRARY_SEARCH_PATHS + + $(inherited) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_52) + + PRODUCT_NAME + $(TARGET_NAME)Debug + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Debug + + E4B69B610A3A1757003C02F2 + + buildSettings + + COMBINE_HIDPI_IMAGES + YES + COPY_PHASE_STRIP + YES + FRAMEWORK_SEARCH_PATHS + + $(inherited) + $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 + "$(SRCROOT)/../../../libs/glut/lib/osx" + GCC_GENERATE_DEBUGGING_SYMBOLS + YES + GCC_MODEL_TUNING + NONE + ICON + $(ICON_NAME_RELEASE) + ICON_FILE + $(ICON_FILE_PATH)$(ICON) + INFOPLIST_FILE + openFrameworks-Info.plist + INSTALL_PATH + $(HOME)/Applications + LIBRARY_SEARCH_PATHS + + $(inherited) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51) + + PRODUCT_NAME + $(TARGET_NAME) + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Release + + E4B69E1C0A3A1BDC003C02F2 + + children + + E4B69E1D0A3A1BDC003C02F2 + E4B69E1E0A3A1BDC003C02F2 + E4B69E1F0A3A1BDC003C02F2 + + isa + PBXGroup + path + src + sourceTree + SOURCE_ROOT + + E4B69E1D0A3A1BDC003C02F2 + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + sourcecode.cpp.cpp + name + main.cpp + path + src/main.cpp + sourceTree + SOURCE_ROOT + + E4B69E1E0A3A1BDC003C02F2 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofApp.cpp + path + src/ofApp.cpp + sourceTree + SOURCE_ROOT + + E4B69E1F0A3A1BDC003C02F2 + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + ofApp.h + path + src/ofApp.h + sourceTree + SOURCE_ROOT + + E4B69E200A3A1BDC003C02F2 + + fileRef + E4B69E1D0A3A1BDC003C02F2 + isa + PBXBuildFile + + E4B69E210A3A1BDC003C02F2 + + fileRef + E4B69E1E0A3A1BDC003C02F2 + isa + PBXBuildFile + + E4B6FCAD0C3E899E008CF71C + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + text.plist.xml + path + openFrameworks-Info.plist + sourceTree + <group> + + E4B6FFFD0C3F9AB9008CF71C + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + cp -f ../../../libs/fmodex/lib/osx/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libfmodex.dylib"; install_name_tool -change ./libfmodex.dylib @executable_path/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"; +mkdir -p "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" +cp -f "$ICON_FILE" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" + + + E4C2424410CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AppKit.framework + path + /System/Library/Frameworks/AppKit.framework + sourceTree + <absolute> + + E4C2424510CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Cocoa.framework + path + /System/Library/Frameworks/Cocoa.framework + sourceTree + <absolute> + + E4C2424610CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + IOKit.framework + path + /System/Library/Frameworks/IOKit.framework + sourceTree + <absolute> + + E4C2424710CC5A17004149E2 + + fileRef + E4C2424410CC5A17004149E2 + isa + PBXBuildFile + + E4C2424810CC5A17004149E2 + + fileRef + E4C2424510CC5A17004149E2 + isa + PBXBuildFile + + E4C2424910CC5A17004149E2 + + fileRef + E4C2424610CC5A17004149E2 + isa + PBXBuildFile + + E4C2427710CC5ABF004149E2 + + buildActionMask + 2147483647 + dstPath + + dstSubfolderSpec + 10 + files + + BBAB23CB13894F3D00AA2426 + + isa + PBXCopyFilesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4EB6799138ADC1D00A09F29 + + fileRef + BBAB23BE13894E4700AA2426 + isa + PBXBuildFile + + E4EB691F138AFCF100A09F29 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + name + CoreOF.xcconfig + path + ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig + sourceTree + SOURCE_ROOT + + E4EB6923138AFD0F00A09F29 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Project.xcconfig + sourceTree + <group> + + E4EEB9AB138B136A00A80321 + + containerPortal + E4328143138ABC890047C5CB + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + E4B27C1410CBEB8E00536013 + remoteInfo + openFrameworks + + E4EEB9AC138B136A00A80321 + + isa + PBXTargetDependency + name + openFrameworks + targetProxy + E4EEB9AB138B136A00A80321 + + E4EEC9E9138DF44700A80321 + + children + + E4EB691F138AFCF100A09F29 + E4328143138ABC890047C5CB + + isa + PBXGroup + name + openFrameworks + sourceTree + <group> + + E7E077E415D3B63C0020DFD4 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreVideo.framework + path + /System/Library/Frameworks/CoreVideo.framework + sourceTree + <absolute> + + E7E077E515D3B63C0020DFD4 + + fileRef + E7E077E415D3B63C0020DFD4 + isa + PBXBuildFile + + E7E077E715D3B6510020DFD4 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + QTKit.framework + path + /System/Library/Frameworks/QTKit.framework + sourceTree + <absolute> + + E7E077E815D3B6510020DFD4 + + fileRef + E7E077E715D3B6510020DFD4 + isa + PBXBuildFile + + E7F985F515E0DE99003869B5 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Accelerate.framework + path + /System/Library/Frameworks/Accelerate.framework + sourceTree + <absolute> + + E7F985F815E0DEA3003869B5 + + fileRef + E7F985F515E0DE99003869B5 + isa + PBXBuildFile + + + rootObject + E4B69B4C0A3A1720003C02F2 + + diff --git a/CALIBRATION/CALIBRATION.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate b/CALIBRATION/CALIBRATION.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ba3e47d Binary files /dev/null and b/CALIBRATION/CALIBRATION.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Debug.xcscheme b/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Debug.xcscheme new file mode 100644 index 0000000..0efc513 --- /dev/null +++ b/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Debug.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Release.xcscheme b/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Release.xcscheme new file mode 100644 index 0000000..4c46c42 --- /dev/null +++ b/CALIBRATION/CALIBRATION.xcodeproj/xcshareddata/xcschemes/CALIBRATION Release.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CALIBRATION/CALIBRATION.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist b/CALIBRATION/CALIBRATION.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..13dfb6e --- /dev/null +++ b/CALIBRATION/CALIBRATION.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SuppressBuildableAutocreation + + E4B69B5A0A3A1756003C02F2 + + primary + + + + + diff --git a/CALIBRATION/Makefile b/CALIBRATION/Makefile new file mode 100644 index 0000000..7a7fe8b --- /dev/null +++ b/CALIBRATION/Makefile @@ -0,0 +1,13 @@ +# Attempt to load a config.make file. +# If none is found, project defaults in config.project.make will be used. +ifneq ($(wildcard config.make),) + include config.make +endif + +# make sure the the OF_ROOT location is defined +ifndef OF_ROOT + OF_ROOT=../../.. +endif + +# call the project makefile! +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk diff --git a/CALIBRATION/Project.xcconfig b/CALIBRATION/Project.xcconfig new file mode 100644 index 0000000..c90f7b1 --- /dev/null +++ b/CALIBRATION/Project.xcconfig @@ -0,0 +1,17 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +//ICONS - NEW IN 0072 +ICON_NAME_DEBUG = icon-debug.icns +ICON_NAME_RELEASE = icon.icns +ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ + +//IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: +//ICON_FILE_PATH = bin/data/ + +OTHER_LDFLAGS = $(OF_CORE_LIBS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) diff --git a/CALIBRATION/addons.make b/CALIBRATION/addons.make new file mode 100644 index 0000000..77297bc --- /dev/null +++ b/CALIBRATION/addons.make @@ -0,0 +1,6 @@ +ofxKinect +ofxOpenCv +ofxXmlSettings +ofxCv +ofxKinectProjectorToolkit +ofxSecondWindow diff --git a/CALIBRATION/bin/data/.gitkeep b/CALIBRATION/bin/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/CALIBRATION/config.make b/CALIBRATION/config.make new file mode 100644 index 0000000..df10f64 --- /dev/null +++ b/CALIBRATION/config.make @@ -0,0 +1,142 @@ +################################################################################ +# CONFIGURE PROJECT MAKEFILE (optional) +# This file is where we make project specific configurations. +################################################################################ + +################################################################################ +# OF ROOT +# The location of your root openFrameworks installation +# (default) OF_ROOT = ../../.. +################################################################################ +# OF_ROOT = ../../.. + +################################################################################ +# PROJECT ROOT +# The location of the project - a starting place for searching for files +# (default) PROJECT_ROOT = . (this directory) +# +################################################################################ +# PROJECT_ROOT = . + +################################################################################ +# PROJECT SPECIFIC CHECKS +# This is a project defined section to create internal makefile flags to +# conditionally enable or disable the addition of various features within +# this makefile. For instance, if you want to make changes based on whether +# GTK is installed, one might test that here and create a variable to check. +################################################################################ +# None + +################################################################################ +# PROJECT EXTERNAL SOURCE PATHS +# These are fully qualified paths that are not within the PROJECT_ROOT folder. +# Like source folders in the PROJECT_ROOT, these paths are subject to +# exlclusion via the PROJECT_EXLCUSIONS list. +# +# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXTERNAL_SOURCE_PATHS = + +################################################################################ +# PROJECT EXCLUSIONS +# These makefiles assume that all folders in your current project directory +# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations +# to look for source code. The any folders or files that match any of the +# items in the PROJECT_EXCLUSIONS list below will be ignored. +# +# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete +# string unless teh user adds a wildcard (%) operator to match subdirectories. +# GNU make only allows one wildcard for matching. The second wildcard (%) is +# treated literally. +# +# (default) PROJECT_EXCLUSIONS = (blank) +# +# Will automatically exclude the following: +# +# $(PROJECT_ROOT)/bin% +# $(PROJECT_ROOT)/obj% +# $(PROJECT_ROOT)/%.xcodeproj +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXCLUSIONS = + +################################################################################ +# PROJECT LINKER FLAGS +# These flags will be sent to the linker when compiling the executable. +# +# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ + +# Currently, shared libraries that are needed are copied to the +# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to +# add a runtime path to search for those shared libraries, since they aren't +# incorporated directly into the final executable application binary. +# TODO: should this be a default setting? +# PROJECT_LDFLAGS=-Wl,-rpath=./libs + +################################################################################ +# PROJECT DEFINES +# Create a space-delimited list of DEFINES. The list will be converted into +# CFLAGS with the "-D" flag later in the makefile. +# +# (default) PROJECT_DEFINES = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_DEFINES = + +################################################################################ +# PROJECT CFLAGS +# This is a list of fully qualified CFLAGS required when compiling for this +# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS +# defined in your platform specific core configuration files. These flags are +# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. +# +# (default) PROJECT_CFLAGS = (blank) +# +# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in +# your platform specific configuration file will be applied by default and +# further flags here may not be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CFLAGS = + +################################################################################ +# PROJECT OPTIMIZATION CFLAGS +# These are lists of CFLAGS that are target-specific. While any flags could +# be conditionally added, they are usually limited to optimization flags. +# These flags are added BEFORE the PROJECT_CFLAGS. +# +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) +# +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) +# +# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the +# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration +# file will be applied by default and further optimization flags here may not +# be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE = +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG = + +################################################################################ +# PROJECT COMPILERS +# Custom compilers can be set for CC and CXX +# (default) PROJECT_CXX = (blank) +# (default) PROJECT_CC = (blank) +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CXX = +# PROJECT_CC = diff --git a/CALIBRATION/openFrameworks-Info.plist b/CALIBRATION/openFrameworks-Info.plist new file mode 100644 index 0000000..8d64d2b --- /dev/null +++ b/CALIBRATION/openFrameworks-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + cc.openFrameworks.ofapp + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFBundleIconFile + ${ICON} + + diff --git a/CALIBRATION/src/main.cpp b/CALIBRATION/src/main.cpp new file mode 100644 index 0000000..e57370b --- /dev/null +++ b/CALIBRATION/src/main.cpp @@ -0,0 +1,13 @@ +#include "ofMain.h" +#include "ofApp.h" + +//======================================================================== +int main( ){ + ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp(new ofApp()); + +} diff --git a/CALIBRATION/src/ofApp.cpp b/CALIBRATION/src/ofApp.cpp new file mode 100644 index 0000000..e909a71 --- /dev/null +++ b/CALIBRATION/src/ofApp.cpp @@ -0,0 +1,163 @@ +#include "ofApp.h" + +//-------------------------------------------------------------- +void ofApp::setup(){ + kinect.setRegistration(true); + kinect.init(); + kinect.open(); + + rgbImage = new ofxCvColorImage(); + rgbImage->allocate(kinect.width, kinect.height); + + fboChessboard.allocate(PROJECTOR_RESOLUTION_X, PROJECTOR_RESOLUTION_Y, GL_RGBA); + secondWindow.setup("chessboard", ofGetScreenWidth(), 0, fboChessboard.getWidth(), fboChessboard.getHeight(), true); +} + +//-------------------------------------------------------------- +void ofApp::drawChessboard(int x, int y, int chessboardSize) { + float w = chessboardSize / chessboardX; + float h = chessboardSize / chessboardY; + currentProjectorPoints.clear(); + fboChessboard.begin(); + ofBackground(255); + ofSetColor(0); + ofTranslate(x, y); + for (int j=0; j0 && i>0) { + currentProjectorPoints.push_back(ofVec2f( + ofMap(x+x0, 0, fboChessboard.getWidth(), 0, 1), + ofMap(y+y0, 0, fboChessboard.getHeight(), 0, 1) + )); + } + if ((i+j)%2==0) ofRect(x0, y0, w, h); + } + } + ofSetColor(255); + fboChessboard.end(); +} + +//-------------------------------------------------------------- +void ofApp::drawTestingPoint(ofVec2f projectedPoint) { + float ptSize = ofMap(sin(ofGetFrameNum()*0.1), -1, 1, 3, 40); + fboChessboard.begin(); + ofBackground(255); + ofSetColor(0, 255, 0); + ofCircle( + ofMap(projectedPoint.x, 0, 1, 0, fboChessboard.getWidth()), + ofMap(projectedPoint.y, 0, 1, 0, fboChessboard.getHeight()), + ptSize); + ofSetColor(255); + fboChessboard.end(); +} + +//-------------------------------------------------------------- +void ofApp::addPointPair() { + int nDepthPoints = 0; + for (int i=0; i 0) nDepthPoints++; + } + if (nDepthPoints == (chessboardX-1)*(chessboardY-1)) { + for (int i=0; isetFromPixels(kinect.getPixels(), kinect.width, kinect.height); + if (testing) { + ofVec2f t = ofVec2f(min(kinect.getWidth()-1,testPoint.x), min(kinect.getHeight()-1,testPoint.y)); + ofVec3f worldPoint = kinect.getWorldCoordinateAt(t.x, t.y); + ofVec2f projectedPoint = kpt.getProjectedPoint(worldPoint); + drawTestingPoint(projectedPoint); + } + else { + drawChessboard(ofGetMouseX(), ofGetMouseY(), chessboardSize); + cvRgbImage = ofxCv::toCv(rgbImage->getPixelsRef()); + cv::Size patternSize = cv::Size(chessboardX-1, chessboardY-1); + int chessFlags = cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_FAST_CHECK; + bool foundChessboard = findChessboardCorners(cvRgbImage, patternSize, cvPoints, chessFlags); + if(foundChessboard) { + cv::Mat gray; + cvtColor(cvRgbImage, gray, CV_RGB2GRAY); + cornerSubPix(gray, cvPoints, cv::Size(11, 11), cv::Size(-1, -1), + cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1)); + drawChessboardCorners(cvRgbImage, patternSize, cv::Mat(cvPoints), foundChessboard); + } + } + } +} + +//-------------------------------------------------------------- +void ofApp::draw(){ + rgbImage->draw(0, 0); + kinect.drawDepth(10, 490, 320, 240); + + ofSetColor(0); + if (testing) { + ofDrawBitmapString("Click on the image to test a point in the RGB image.", 340, 510); + ofDrawBitmapString("The projector should place a green dot on the corresponding point.", 340, 530); + ofDrawBitmapString("Press the 's' key to save the calibration.", 340, 550); + if (saved) { + ofDrawBitmapString("Calibration saved.", 340, 590); + } + ofSetColor(255, 0, 0); + float ptSize = ofMap(cos(ofGetFrameNum()*0.1), -1, 1, 3, 40); + ofCircle(testPoint.x, testPoint.y, ptSize); + } else { + ofDrawBitmapString("Position the chessboard using the mouse.", 340, 510); + ofDrawBitmapString("Adjust the size of the chessboard using the 'q' and 'w' keys.", 340, 530); + ofDrawBitmapString("Press the spacebar to save a set of point pairs.", 340, 550); + ofDrawBitmapString("Press the 'c' key to calibrate.", 340, 570); + ofSetColor(resultMessageColor); + ofDrawBitmapString(resultMessage, 340, 610); + ofSetColor(0); + ofDrawBitmapString(ofToString(pairsKinect.size())+" point pairs collected.", 340, 630); + } + ofSetColor(255); + + secondWindow.begin(); + fboChessboard.draw(0, 0); + secondWindow.end(); +} + +//-------------------------------------------------------------- +void ofApp::keyPressed(int key){ + if (key==' '){ + addPointPair(); + } else if (key=='q') { + chessboardSize -= 20; + } else if (key=='w') { + chessboardSize += 20; + } else if (key=='c') { + kpt.calibrate(pairsKinect, pairsProjector); + testing = true; + } else if (key=='s') { + kpt.saveCalibration("calibration.xml"); + saved = true; + } else if (key=='l') { + kpt.loadCalibration("calibration.xml"); + testing = true; + } +} + +//-------------------------------------------------------------- +void ofApp::mousePressed(int x, int y, int button){ + if (testing) { + testPoint.set(min(x, kinect.width-1), min(y, kinect.height-1)); + } +} diff --git a/CALIBRATION/src/ofApp.h b/CALIBRATION/src/ofApp.h new file mode 100644 index 0000000..87816c5 --- /dev/null +++ b/CALIBRATION/src/ofApp.h @@ -0,0 +1,54 @@ +#pragma once + +#include "ofMain.h" +#include "ofxKinectProjectorToolkit.h" +#include "ofxKinect.h" +#include "ofxOpenCv.h" +#include "ofxCv.h" +#include "ofxSecondWindow.h" + + +// this must match the display resolution of your projector +#define PROJECTOR_RESOLUTION_X 1280 +#define PROJECTOR_RESOLUTION_Y 800 + + +class ofApp : public ofBaseApp +{ +public: + void setup(); + void update(); + void draw(); + + void keyPressed(int key); + void mousePressed(int x, int y, int button); + + void drawChessboard(int x, int y, int chessboardSize); + void drawTestingPoint(ofVec2f projectedPoint); + void addPointPair(); + + ofxKinect kinect; + ofxKinectProjectorToolkit kpt; + + ofxSecondWindow secondWindow; + ofFbo fboChessboard; + ofxCvColorImage* rgbImage; + cv::Mat cvRgbImage; + + vector currentProjectorPoints; + vector cvPoints; + vector pairsKinect; + vector pairsProjector; + + string resultMessage; + ofColor resultMessageColor; + ofVec2f testPoint; + + int chessboardSize = 300; + int chessboardX = 5; + int chessboardY = 4; + bool testing; + bool saved; +}; + + diff --git a/README.md b/README.md index cbcbb82..80c228c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,41 @@ -ofxKinectProjectorToolkit -========================= +# ofxKinectProjectorToolkit -openFrameworks addon for calibrating a Kinect to a projector for real-time projection mapping onto Kinect-derived spaces +This is an [openFrameworks](http://www.openframeworks.cc) addon for calibrating a projector to a Kinect, allowing for automated projection mapping aligned to the Kinect. + +This toolkit is also [implemented as a Processing library](https://github.com/genekogan/KinectProjectorToolkit). It is based on this method described by [Jan Hrdlička](http://blog.3dsense.org/programming/kinect-projector-calibration-human-mapping-2/). ofxKinectProjectorToolkit is similar to [ofxCamaraLucida](https://github.com/chparsons/ofxCamaraLucida), [ofxReprojection](https://github.com/luteberget/ofxReprojection), and [https://github.com/Kj1/ofxProjectorKinectCalibration](https://github.com/Kj1/ofxProjectorKinectCalibration). + + +## Dependencies + +This library and the included calibration app have several dependencies: + + - ofxKinect (included with openFrameworks) + - ofxOpenCv (included with openFrameworks) + - [ofxCv](https://github.com/kylemcdonald/ofxCv) + - [ofxSecondWindow](https://github.com/genekogan/ofxSecondWindow) + +Additionally, the included post-calibration examples require [ofxUI](https://github.com/rezaali/ofxUI). + + +## Instructions + +### Calibration + +First, you must create the calibration. Set your display to dual-screen so the projector has its own display (right screen), and launch the CALIBRATION example. + +*Very important*: make note of the screen resolution of the projector's display (e.g. 1280x800) and copy those values to the defined variables PROJECTOR_RESOLUTION_X and PROJECTOR_RESOLUTION_Y. + +Follow the instructions in the calibration app to collect a series of point pairs. Move the chessboard display around using the mouse ('q' and 'r' keys resize it). Calibrate and save calibration file using 'c' and 's' keys. This will generate the calibration.xml file in the data folder of the calibration app. Copy this file somewhere. + +### Mapping + +There are two included examples, example-bodyMapping and example-segmentation. Both project solid colors onto objects found and tracked from the kinect using CV. The difference is that bodyMapping finds blobs by thresholding the depth image, whereas segmentation finds blobs without thresholding, instead segmenting the entire depth image using edge detection. Both examples use ofxCv for persistent blob tracking to keep identity of tracked blobs from frame to frame, though this is not 100% reliable. + +Make sure you load the calibration file you saved in the previous step in the line: + + kpt.loadCalibration(PATH_TO_YOUR_CALIBRTION_FILE); + +The key function for mapping is `getProjectedPoint(ofVec3f worldPoint)`. This function takes any 3d world point from `ofxKinect` and converts it to a pixel point. For example, the pixel point associated with the world point inside the depth image at (x, y) is found: + + ofVec3f wp = kinect.getWorldCoordinateAt(x, y); + ofVec2f pp = kpt.getProjectedPoint(wp); diff --git a/example_bodyMapping/Makefile b/example_bodyMapping/Makefile new file mode 100644 index 0000000..7a7fe8b --- /dev/null +++ b/example_bodyMapping/Makefile @@ -0,0 +1,13 @@ +# Attempt to load a config.make file. +# If none is found, project defaults in config.project.make will be used. +ifneq ($(wildcard config.make),) + include config.make +endif + +# make sure the the OF_ROOT location is defined +ifndef OF_ROOT + OF_ROOT=../../.. +endif + +# call the project makefile! +include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk diff --git a/example_bodyMapping/Project.xcconfig b/example_bodyMapping/Project.xcconfig new file mode 100644 index 0000000..c90f7b1 --- /dev/null +++ b/example_bodyMapping/Project.xcconfig @@ -0,0 +1,17 @@ +//THE PATH TO THE ROOT OF OUR OF PATH RELATIVE TO THIS PROJECT. +//THIS NEEDS TO BE DEFINED BEFORE CoreOF.xcconfig IS INCLUDED +OF_PATH = ../../.. + +//THIS HAS ALL THE HEADER AND LIBS FOR OF CORE +#include "../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig" + +//ICONS - NEW IN 0072 +ICON_NAME_DEBUG = icon-debug.icns +ICON_NAME_RELEASE = icon.icns +ICON_FILE_PATH = $(OF_PATH)/libs/openFrameworksCompiled/project/osx/ + +//IF YOU WANT AN APP TO HAVE A CUSTOM ICON - PUT THEM IN YOUR DATA FOLDER AND CHANGE ICON_FILE_PATH to: +//ICON_FILE_PATH = bin/data/ + +OTHER_LDFLAGS = $(OF_CORE_LIBS) +HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) diff --git a/example_bodyMapping/addons.make b/example_bodyMapping/addons.make new file mode 100644 index 0000000..5e88e30 --- /dev/null +++ b/example_bodyMapping/addons.make @@ -0,0 +1,7 @@ +ofxKinect +ofxOpenCv +ofxXmlSettings +ofxCv +ofxKinectProjectorToolkit +ofxSecondWindow +ofxUI diff --git a/example_bodyMapping/bin/data/.gitkeep b/example_bodyMapping/bin/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/example_bodyMapping/config.make b/example_bodyMapping/config.make new file mode 100644 index 0000000..df10f64 --- /dev/null +++ b/example_bodyMapping/config.make @@ -0,0 +1,142 @@ +################################################################################ +# CONFIGURE PROJECT MAKEFILE (optional) +# This file is where we make project specific configurations. +################################################################################ + +################################################################################ +# OF ROOT +# The location of your root openFrameworks installation +# (default) OF_ROOT = ../../.. +################################################################################ +# OF_ROOT = ../../.. + +################################################################################ +# PROJECT ROOT +# The location of the project - a starting place for searching for files +# (default) PROJECT_ROOT = . (this directory) +# +################################################################################ +# PROJECT_ROOT = . + +################################################################################ +# PROJECT SPECIFIC CHECKS +# This is a project defined section to create internal makefile flags to +# conditionally enable or disable the addition of various features within +# this makefile. For instance, if you want to make changes based on whether +# GTK is installed, one might test that here and create a variable to check. +################################################################################ +# None + +################################################################################ +# PROJECT EXTERNAL SOURCE PATHS +# These are fully qualified paths that are not within the PROJECT_ROOT folder. +# Like source folders in the PROJECT_ROOT, these paths are subject to +# exlclusion via the PROJECT_EXLCUSIONS list. +# +# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXTERNAL_SOURCE_PATHS = + +################################################################################ +# PROJECT EXCLUSIONS +# These makefiles assume that all folders in your current project directory +# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations +# to look for source code. The any folders or files that match any of the +# items in the PROJECT_EXCLUSIONS list below will be ignored. +# +# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete +# string unless teh user adds a wildcard (%) operator to match subdirectories. +# GNU make only allows one wildcard for matching. The second wildcard (%) is +# treated literally. +# +# (default) PROJECT_EXCLUSIONS = (blank) +# +# Will automatically exclude the following: +# +# $(PROJECT_ROOT)/bin% +# $(PROJECT_ROOT)/obj% +# $(PROJECT_ROOT)/%.xcodeproj +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_EXCLUSIONS = + +################################################################################ +# PROJECT LINKER FLAGS +# These flags will be sent to the linker when compiling the executable. +# +# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ + +# Currently, shared libraries that are needed are copied to the +# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to +# add a runtime path to search for those shared libraries, since they aren't +# incorporated directly into the final executable application binary. +# TODO: should this be a default setting? +# PROJECT_LDFLAGS=-Wl,-rpath=./libs + +################################################################################ +# PROJECT DEFINES +# Create a space-delimited list of DEFINES. The list will be converted into +# CFLAGS with the "-D" flag later in the makefile. +# +# (default) PROJECT_DEFINES = (blank) +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_DEFINES = + +################################################################################ +# PROJECT CFLAGS +# This is a list of fully qualified CFLAGS required when compiling for this +# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS +# defined in your platform specific core configuration files. These flags are +# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below. +# +# (default) PROJECT_CFLAGS = (blank) +# +# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in +# your platform specific configuration file will be applied by default and +# further flags here may not be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CFLAGS = + +################################################################################ +# PROJECT OPTIMIZATION CFLAGS +# These are lists of CFLAGS that are target-specific. While any flags could +# be conditionally added, they are usually limited to optimization flags. +# These flags are added BEFORE the PROJECT_CFLAGS. +# +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank) +# +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets. +# +# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank) +# +# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the +# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration +# file will be applied by default and further optimization flags here may not +# be needed. +# +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_OPTIMIZATION_CFLAGS_RELEASE = +# PROJECT_OPTIMIZATION_CFLAGS_DEBUG = + +################################################################################ +# PROJECT COMPILERS +# Custom compilers can be set for CC and CXX +# (default) PROJECT_CXX = (blank) +# (default) PROJECT_CC = (blank) +# Note: Leave a leading space when adding list items with the += operator +################################################################################ +# PROJECT_CXX = +# PROJECT_CC = diff --git a/example_bodyMapping/example_bodyMapping.xcodeproj/project.pbxproj b/example_bodyMapping/example_bodyMapping.xcodeproj/project.pbxproj new file mode 100644 index 0000000..237a007 --- /dev/null +++ b/example_bodyMapping/example_bodyMapping.xcodeproj/project.pbxproj @@ -0,0 +1,7901 @@ + + + + archiveVersion + 1 + classes + + objectVersion + 46 + objects + + 5E62D62D32EFCA8D05DDAD1A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWrapper.h + path + ../../../addons/ofxUI/src/ofxUIWrapper.h + sourceTree + SOURCE_ROOT + + 02677FA320D6C63B228A7562 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWidgetWithLabel.h + path + ../../../addons/ofxUI/src/ofxUIWidgetWithLabel.h + sourceTree + SOURCE_ROOT + + CE5D89B9893EAA12F511DCAC + + fileRef + 5AD807D1AF254F978AB20B1C + isa + PBXBuildFile + + 5AD807D1AF254F978AB20B1C + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWidgetWithLabel.cpp + path + ../../../addons/ofxUI/src/ofxUIWidgetWithLabel.cpp + sourceTree + SOURCE_ROOT + + 23FA31CAEA236B2C1E218497 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWidgets.h + path + ../../../addons/ofxUI/src/ofxUIWidgets.h + sourceTree + SOURCE_ROOT + + 32BD050A579633ADBCA5AF6B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWidget.h + path + ../../../addons/ofxUI/src/ofxUIWidget.h + sourceTree + SOURCE_ROOT + + 82845E1F8C90E1F5A99D9868 + + fileRef + 08A9C84B3CA68561BE01FF37 + isa + PBXBuildFile + + 08A9C84B3CA68561BE01FF37 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWidget.cpp + path + ../../../addons/ofxUI/src/ofxUIWidget.cpp + sourceTree + SOURCE_ROOT + + FCCBDB55B98DA36682809F03 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWaveform.h + path + ../../../addons/ofxUI/src/ofxUIWaveform.h + sourceTree + SOURCE_ROOT + + AE281BEBF3A00F1FC37F3DA0 + + fileRef + 9345327AA463407B3DADBADE + isa + PBXBuildFile + + 9345327AA463407B3DADBADE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIWaveform.cpp + path + ../../../addons/ofxUI/src/ofxUIWaveform.cpp + sourceTree + SOURCE_ROOT + + D1387F25A47EF6809B55B59C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIValuePlotter.h + path + ../../../addons/ofxUI/src/ofxUIValuePlotter.h + sourceTree + SOURCE_ROOT + + 60012C723B05938A3D388335 + + fileRef + 4D902D60E5CCFA9F2554BC7C + isa + PBXBuildFile + + 4D902D60E5CCFA9F2554BC7C + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIValuePlotter.cpp + path + ../../../addons/ofxUI/src/ofxUIValuePlotter.cpp + sourceTree + SOURCE_ROOT + + 87035EFE3D4427294D4D1338 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIUtils.h + path + ../../../addons/ofxUI/src/ofxUIUtils.h + sourceTree + SOURCE_ROOT + + 8178EB9AA3C0268331AF3AF3 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIToggleMatrix.h + path + ../../../addons/ofxUI/src/ofxUIToggleMatrix.h + sourceTree + SOURCE_ROOT + + E3A1109F67D711D6C256031E + + fileRef + 702A2528CA64B397E9B91ABE + isa + PBXBuildFile + + 702A2528CA64B397E9B91ABE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIToggleMatrix.cpp + path + ../../../addons/ofxUI/src/ofxUIToggleMatrix.cpp + sourceTree + SOURCE_ROOT + + 4117B8C24D49837D3DF9C23B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIToggle.h + path + ../../../addons/ofxUI/src/ofxUIToggle.h + sourceTree + SOURCE_ROOT + + 04C82720B149CE576B8CBB06 + + fileRef + 48CCCEA0C681DE8B4945111B + isa + PBXBuildFile + + 48CCCEA0C681DE8B4945111B + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIToggle.cpp + path + ../../../addons/ofxUI/src/ofxUIToggle.cpp + sourceTree + SOURCE_ROOT + + E65D547C2CD6A84FC9AF15FA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITextInput.h + path + ../../../addons/ofxUI/src/ofxUITextInput.h + sourceTree + SOURCE_ROOT + + F8D05F7C7F785CE323983B47 + + fileRef + 06C7032F68D99A145A53CB6F + isa + PBXBuildFile + + 06C7032F68D99A145A53CB6F + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITextInput.cpp + path + ../../../addons/ofxUI/src/ofxUITextInput.cpp + sourceTree + SOURCE_ROOT + + F9DF961B5E7D4C4E1E5D029C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITextArea.h + path + ../../../addons/ofxUI/src/ofxUITextArea.h + sourceTree + SOURCE_ROOT + + C961BE22AB9A8CCF037FC18F + + fileRef + DBE31D52BCB0CE44B9D154F0 + isa + PBXBuildFile + + DBE31D52BCB0CE44B9D154F0 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITextArea.cpp + path + ../../../addons/ofxUI/src/ofxUITextArea.cpp + sourceTree + SOURCE_ROOT + + D45991C927E805C3B1AD7516 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITabBar.h + path + ../../../addons/ofxUI/src/ofxUITabBar.h + sourceTree + SOURCE_ROOT + + 5AE95ADB5549701423B6DA48 + + fileRef + A64B8AA7481267CD4A76C16B + isa + PBXBuildFile + + A64B8AA7481267CD4A76C16B + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUITabBar.cpp + path + ../../../addons/ofxUI/src/ofxUITabBar.cpp + sourceTree + SOURCE_ROOT + + 1C43CDB79BF40EA7424B9680 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISuperCanvas.h + path + ../../../addons/ofxUI/src/ofxUISuperCanvas.h + sourceTree + SOURCE_ROOT + + 1DAAC3FB4B98B08AE63F4687 + + fileRef + 38EBD5650A3BF5A499B07525 + isa + PBXBuildFile + + 38EBD5650A3BF5A499B07525 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISuperCanvas.cpp + path + ../../../addons/ofxUI/src/ofxUISuperCanvas.cpp + sourceTree + SOURCE_ROOT + + C6305369801B450557086284 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISpectrum.h + path + ../../../addons/ofxUI/src/ofxUISpectrum.h + sourceTree + SOURCE_ROOT + + 52AFF80A869790144ACCC9BA + + fileRef + D7177CC1E771E1E857F8CB48 + isa + PBXBuildFile + + D7177CC1E771E1E857F8CB48 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISpectrum.cpp + path + ../../../addons/ofxUI/src/ofxUISpectrum.cpp + sourceTree + SOURCE_ROOT + + C7B4B8AD9464A693A3683D0F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISpacer.h + path + ../../../addons/ofxUI/src/ofxUISpacer.h + sourceTree + SOURCE_ROOT + + BFEFCE32DAFE10A8EB519F6C + + fileRef + 30CBAAEC78A0E9EBBB10A05A + isa + PBXBuildFile + + 30CBAAEC78A0E9EBBB10A05A + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISpacer.cpp + path + ../../../addons/ofxUI/src/ofxUISpacer.cpp + sourceTree + SOURCE_ROOT + + E88F5D4D5E360FA5B5C8F99E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISortableList.h + path + ../../../addons/ofxUI/src/ofxUISortableList.h + sourceTree + SOURCE_ROOT + + ADE7C2AFC51E3F7E5E389026 + + fileRef + 5613D5D24B00D8AD909F7E6A + isa + PBXBuildFile + + 5613D5D24B00D8AD909F7E6A + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISortableList.cpp + path + ../../../addons/ofxUI/src/ofxUISortableList.cpp + sourceTree + SOURCE_ROOT + + 470B5D2AC2F616D10B2E6025 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISlider.h + path + ../../../addons/ofxUI/src/ofxUISlider.h + sourceTree + SOURCE_ROOT + + 740A58CBFDFE578C83A349AF + + fileRef + 0DE8B77977749C1835A9472B + isa + PBXBuildFile + + 0DE8B77977749C1835A9472B + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUISlider.cpp + path + ../../../addons/ofxUI/src/ofxUISlider.cpp + sourceTree + SOURCE_ROOT + + C38D6DCC3AB9AAE213A64015 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIScrollableCanvas.h + path + ../../../addons/ofxUI/src/ofxUIScrollableCanvas.h + sourceTree + SOURCE_ROOT + + 43BADBB2FE0F17D34B57A705 + + fileRef + BFD3387AA9EFA53E1B4F087B + isa + PBXBuildFile + + BFD3387AA9EFA53E1B4F087B + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIScrollableCanvas.cpp + path + ../../../addons/ofxUI/src/ofxUIScrollableCanvas.cpp + sourceTree + SOURCE_ROOT + + 885850B62FAD08EB1D2F0BF4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRotarySlider.h + path + ../../../addons/ofxUI/src/ofxUIRotarySlider.h + sourceTree + SOURCE_ROOT + + FE0F1DB69ACCD163E9DA2A15 + + fileRef + 64F3DE24F191ECED9DBE903C + isa + PBXBuildFile + + 64F3DE24F191ECED9DBE903C + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRotarySlider.cpp + path + ../../../addons/ofxUI/src/ofxUIRotarySlider.cpp + sourceTree + SOURCE_ROOT + + 1E29C7E8C47E3E2DB1C58766 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRectangle.h + path + ../../../addons/ofxUI/src/ofxUIRectangle.h + sourceTree + SOURCE_ROOT + + 59C5F2F5D7254C33C00F97CB + + fileRef + 828EDF7F6C239EA7B17F32F0 + isa + PBXBuildFile + + 828EDF7F6C239EA7B17F32F0 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRectangle.cpp + path + ../../../addons/ofxUI/src/ofxUIRectangle.cpp + sourceTree + SOURCE_ROOT + + 856BF5AB0322D0689EE63829 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRangeSlider.h + path + ../../../addons/ofxUI/src/ofxUIRangeSlider.h + sourceTree + SOURCE_ROOT + + 1587708E3CAC72997E43504E + + fileRef + E2813E36CEFD8D1C1B70E600 + isa + PBXBuildFile + + E2813E36CEFD8D1C1B70E600 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRangeSlider.cpp + path + ../../../addons/ofxUI/src/ofxUIRangeSlider.cpp + sourceTree + SOURCE_ROOT + + 4C9B919B991B4E45BC5DC0DB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRadio.h + path + ../../../addons/ofxUI/src/ofxUIRadio.h + sourceTree + SOURCE_ROOT + + D60E54E7FD6E19BC8636E0D2 + + fileRef + 9D33A3E929B0B5D9C002E30E + isa + PBXBuildFile + + 9D33A3E929B0B5D9C002E30E + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIRadio.cpp + path + ../../../addons/ofxUI/src/ofxUIRadio.cpp + sourceTree + SOURCE_ROOT + + 334840CA6B3402C8C30CAC4E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIOFWrapper.h + path + ../../../addons/ofxUI/src/ofxUIOFWrapper.h + sourceTree + SOURCE_ROOT + + 15C99204FF4D8D72AD034B63 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUINumberDialer.h + path + ../../../addons/ofxUI/src/ofxUINumberDialer.h + sourceTree + SOURCE_ROOT + + E3D59A6B55F05669B3FBF8BD + + fileRef + 0D6768C572B6CA49227C29EA + isa + PBXBuildFile + + 0D6768C572B6CA49227C29EA + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUINumberDialer.cpp + path + ../../../addons/ofxUI/src/ofxUINumberDialer.cpp + sourceTree + SOURCE_ROOT + + 1902452F5E510A2DBC1E5BD6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMultiImageToggle.h + path + ../../../addons/ofxUI/src/ofxUIMultiImageToggle.h + sourceTree + SOURCE_ROOT + + F9C20834354ACC8337320B8C + + fileRef + 1C5ED4467DFF0AC3482E9362 + isa + PBXBuildFile + + 1C5ED4467DFF0AC3482E9362 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMultiImageToggle.cpp + path + ../../../addons/ofxUI/src/ofxUIMultiImageToggle.cpp + sourceTree + SOURCE_ROOT + + BC6931447DE6C359DDDF21F1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMultiImageButton.h + path + ../../../addons/ofxUI/src/ofxUIMultiImageButton.h + sourceTree + SOURCE_ROOT + + 222C3AB10FA3158602718602 + + fileRef + 17E06821FB98542FDB806E50 + isa + PBXBuildFile + + 17E06821FB98542FDB806E50 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMultiImageButton.cpp + path + ../../../addons/ofxUI/src/ofxUIMultiImageButton.cpp + sourceTree + SOURCE_ROOT + + 5C48E3511951BB86FA9AA642 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMovingGraph.h + path + ../../../addons/ofxUI/src/ofxUIMovingGraph.h + sourceTree + SOURCE_ROOT + + F440B307990F8F5CE40B9111 + + fileRef + 7965EE214E4C332003852642 + isa + PBXBuildFile + + 7965EE214E4C332003852642 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMovingGraph.cpp + path + ../../../addons/ofxUI/src/ofxUIMovingGraph.cpp + sourceTree + SOURCE_ROOT + + CCEC29A4351C40BA86F2E491 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMinimalSlider.h + path + ../../../addons/ofxUI/src/ofxUIMinimalSlider.h + sourceTree + SOURCE_ROOT + + 9A83D1B3FB64456BC907667F + + fileRef + 2BE7216430113F333B8351ED + isa + PBXBuildFile + + 2BE7216430113F333B8351ED + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIMinimalSlider.cpp + path + ../../../addons/ofxUI/src/ofxUIMinimalSlider.cpp + sourceTree + SOURCE_ROOT + + 6248640C06B47042BB5BD3F2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabelToggle.h + path + ../../../addons/ofxUI/src/ofxUILabelToggle.h + sourceTree + SOURCE_ROOT + + C30B3A2A37F8F32EE7318718 + + fileRef + 76AF3B44E0E2FA8BFBD5F592 + isa + PBXBuildFile + + 76AF3B44E0E2FA8BFBD5F592 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabelToggle.cpp + path + ../../../addons/ofxUI/src/ofxUILabelToggle.cpp + sourceTree + SOURCE_ROOT + + FBE1B379902B3C585DC8F7A2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabelButton.h + path + ../../../addons/ofxUI/src/ofxUILabelButton.h + sourceTree + SOURCE_ROOT + + FFD1EBFCA24DFB4E4427B4FE + + fileRef + F9A4454B00CCFD7265D3CA85 + isa + PBXBuildFile + + F9A4454B00CCFD7265D3CA85 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabelButton.cpp + path + ../../../addons/ofxUI/src/ofxUILabelButton.cpp + sourceTree + SOURCE_ROOT + + F26E25F3872C0799D6433B99 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabel.h + path + ../../../addons/ofxUI/src/ofxUILabel.h + sourceTree + SOURCE_ROOT + + 7C3DC84C9BFCBD2866DB2B6C + + fileRef + D7D83EF74FC7508D9146FA63 + isa + PBXBuildFile + + D7D83EF74FC7508D9146FA63 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUILabel.cpp + path + ../../../addons/ofxUI/src/ofxUILabel.cpp + sourceTree + SOURCE_ROOT + + 2D394124F88F348AA4142DCF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageToggle.h + path + ../../../addons/ofxUI/src/ofxUIImageToggle.h + sourceTree + SOURCE_ROOT + + FB8AA9FA6535767BE31806BC + + fileRef + B848522CCA3A75ABD56752C9 + isa + PBXBuildFile + + B848522CCA3A75ABD56752C9 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageToggle.cpp + path + ../../../addons/ofxUI/src/ofxUIImageToggle.cpp + sourceTree + SOURCE_ROOT + + D66E735BE796BC0675320DC8 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageSlider.h + path + ../../../addons/ofxUI/src/ofxUIImageSlider.h + sourceTree + SOURCE_ROOT + + 26874B150C8535AEA0F24C8C + + fileRef + 2689C5C8A97002C218125F2F + isa + PBXBuildFile + + 2689C5C8A97002C218125F2F + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageSlider.cpp + path + ../../../addons/ofxUI/src/ofxUIImageSlider.cpp + sourceTree + SOURCE_ROOT + + 4AEA0D08C3B0323FEDC8D974 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageSampler.h + path + ../../../addons/ofxUI/src/ofxUIImageSampler.h + sourceTree + SOURCE_ROOT + + FBD0CD0AFE3849C14E829CAF + + fileRef + 8B5F60B902BFFD95E99AAB34 + isa + PBXBuildFile + + 8B5F60B902BFFD95E99AAB34 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageSampler.cpp + path + ../../../addons/ofxUI/src/ofxUIImageSampler.cpp + sourceTree + SOURCE_ROOT + + E67BC70E17DDA0081C8FD9DD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageButton.h + path + ../../../addons/ofxUI/src/ofxUIImageButton.h + sourceTree + SOURCE_ROOT + + 7F2CD93F681F3C1547B3BF2C + + fileRef + E6280B5FA1CEA20450916E49 + isa + PBXBuildFile + + E6280B5FA1CEA20450916E49 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImageButton.cpp + path + ../../../addons/ofxUI/src/ofxUIImageButton.cpp + sourceTree + SOURCE_ROOT + + 4ED7BC3AF72F6BE8F0917A30 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImage.h + path + ../../../addons/ofxUI/src/ofxUIImage.h + sourceTree + SOURCE_ROOT + + 3D4EA8E172D3E4A30FEFA969 + + fileRef + 938F5A098A216B403906129C + isa + PBXBuildFile + + 938F5A098A216B403906129C + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIImage.cpp + path + ../../../addons/ofxUI/src/ofxUIImage.cpp + sourceTree + SOURCE_ROOT + + 664D65407BE633C038FA9498 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIFPSSlider.h + path + ../../../addons/ofxUI/src/ofxUIFPSSlider.h + sourceTree + SOURCE_ROOT + + 22030CBDCC25D815E7ED6757 + + fileRef + 7E7E592342D8B7FB73A6F64D + isa + PBXBuildFile + + 7E7E592342D8B7FB73A6F64D + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIFPSSlider.cpp + path + ../../../addons/ofxUI/src/ofxUIFPSSlider.cpp + sourceTree + SOURCE_ROOT + + FDA2832E78CFA22BEEC74160 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIFPS.h + path + ../../../addons/ofxUI/src/ofxUIFPS.h + sourceTree + SOURCE_ROOT + + 7252706DA14C1BE63950ADDA + + fileRef + FEB61645EF9120F5BACB7462 + isa + PBXBuildFile + + FEB61645EF9120F5BACB7462 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIFPS.cpp + path + ../../../addons/ofxUI/src/ofxUIFPS.cpp + sourceTree + SOURCE_ROOT + + CF73E1AF93352CF515E7C9F2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIEventArgs.h + path + ../../../addons/ofxUI/src/ofxUIEventArgs.h + sourceTree + SOURCE_ROOT + + 084025DA517D8329301FE1B6 + + fileRef + A8896AC3BECAAA504E3828F4 + isa + PBXBuildFile + + A8896AC3BECAAA504E3828F4 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIEventArgs.cpp + path + ../../../addons/ofxUI/src/ofxUIEventArgs.cpp + sourceTree + SOURCE_ROOT + + 531D8D09739D338239967B3A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIDropDownList.h + path + ../../../addons/ofxUI/src/ofxUIDropDownList.h + sourceTree + SOURCE_ROOT + + F392A99D83698FC099127880 + + fileRef + 31517A9D3D67D9C054954DC5 + isa + PBXBuildFile + + 31517A9D3D67D9C054954DC5 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIDropDownList.cpp + path + ../../../addons/ofxUI/src/ofxUIDropDownList.cpp + sourceTree + SOURCE_ROOT + + 3C9066FB257B904A547019ED + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIDragableLabelButton.h + path + ../../../addons/ofxUI/src/ofxUIDragableLabelButton.h + sourceTree + SOURCE_ROOT + + 9BE4AE0AA2B8C436BDFE9D4D + + fileRef + FFD5D3C9D38E29DB72B32254 + isa + PBXBuildFile + + FFD5D3C9D38E29DB72B32254 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIDragableLabelButton.cpp + path + ../../../addons/ofxUI/src/ofxUIDragableLabelButton.cpp + sourceTree + SOURCE_ROOT + + AEFCF7E549ACA862C022AD40 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIDefines.h + path + ../../../addons/ofxUI/src/ofxUIDefines.h + sourceTree + SOURCE_ROOT + + EDFEB3D8C9183ADE3FACB4B5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUICircleSlider.h + path + ../../../addons/ofxUI/src/ofxUICircleSlider.h + sourceTree + SOURCE_ROOT + + DF0C851B244C4C867CEA8806 + + fileRef + 2556100026B425E8370BCF75 + isa + PBXBuildFile + + 2556100026B425E8370BCF75 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUICircleSlider.cpp + path + ../../../addons/ofxUI/src/ofxUICircleSlider.cpp + sourceTree + SOURCE_ROOT + + 4FF2F2D5A01ADA37A9ADE20F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUICanvas.h + path + ../../../addons/ofxUI/src/ofxUICanvas.h + sourceTree + SOURCE_ROOT + + 7BE46522B64E24FAEDE1A25D + + fileRef + E71733956CD601886837BE2E + isa + PBXBuildFile + + E71733956CD601886837BE2E + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUICanvas.cpp + path + ../../../addons/ofxUI/src/ofxUICanvas.cpp + sourceTree + SOURCE_ROOT + + B3CA0202B1A3B6D8920C2B15 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIButton.h + path + ../../../addons/ofxUI/src/ofxUIButton.h + sourceTree + SOURCE_ROOT + + 7D393646FB859A930EF58917 + + fileRef + 8F8238006E98A8E39851968C + isa + PBXBuildFile + + 8F8238006E98A8E39851968C + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIButton.cpp + path + ../../../addons/ofxUI/src/ofxUIButton.cpp + sourceTree + SOURCE_ROOT + + 2DD185513A2875EC8A078670 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIBiLabelSlider.h + path + ../../../addons/ofxUI/src/ofxUIBiLabelSlider.h + sourceTree + SOURCE_ROOT + + C381F2B7CFD84C0E540EB4BC + + fileRef + 876BBA9542E267584885CAD8 + isa + PBXBuildFile + + 876BBA9542E267584885CAD8 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIBiLabelSlider.cpp + path + ../../../addons/ofxUI/src/ofxUIBiLabelSlider.cpp + sourceTree + SOURCE_ROOT + + C161222F68D4F7CE28BC4F61 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIBaseDraws.h + path + ../../../addons/ofxUI/src/ofxUIBaseDraws.h + sourceTree + SOURCE_ROOT + + F1E8DE8734BA6F69A5112FA8 + + fileRef + 28155024C27152A66926B553 + isa + PBXBuildFile + + 28155024C27152A66926B553 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUIBaseDraws.cpp + path + ../../../addons/ofxUI/src/ofxUIBaseDraws.cpp + sourceTree + SOURCE_ROOT + + 961DE8B564EF22E65C9480AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUI2DPad.h + path + ../../../addons/ofxUI/src/ofxUI2DPad.h + sourceTree + SOURCE_ROOT + + 4B3ED367CA852D522E2EE996 + + fileRef + 1553D7111BCBE7834BCC0784 + isa + PBXBuildFile + + 1553D7111BCBE7834BCC0784 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUI2DPad.cpp + path + ../../../addons/ofxUI/src/ofxUI2DPad.cpp + sourceTree + SOURCE_ROOT + + 653CFAE31336DAA04B1F1503 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUI2DGraph.h + path + ../../../addons/ofxUI/src/ofxUI2DGraph.h + sourceTree + SOURCE_ROOT + + 9F5C6DD965B4F3A6DB5B88F8 + + fileRef + 02FF3B8D243CFB85AE0909EB + isa + PBXBuildFile + + 02FF3B8D243CFB85AE0909EB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxUI2DGraph.cpp + path + ../../../addons/ofxUI/src/ofxUI2DGraph.cpp + sourceTree + SOURCE_ROOT + + D60F85FE32E11F4003B80627 + + children + + 64C6F7AD018FFD34C7ABB6F2 + 02FF3B8D243CFB85AE0909EB + 653CFAE31336DAA04B1F1503 + 1553D7111BCBE7834BCC0784 + 961DE8B564EF22E65C9480AE + 28155024C27152A66926B553 + C161222F68D4F7CE28BC4F61 + 876BBA9542E267584885CAD8 + 2DD185513A2875EC8A078670 + 8F8238006E98A8E39851968C + B3CA0202B1A3B6D8920C2B15 + E71733956CD601886837BE2E + 4FF2F2D5A01ADA37A9ADE20F + 2556100026B425E8370BCF75 + EDFEB3D8C9183ADE3FACB4B5 + AEFCF7E549ACA862C022AD40 + FFD5D3C9D38E29DB72B32254 + 3C9066FB257B904A547019ED + 31517A9D3D67D9C054954DC5 + 531D8D09739D338239967B3A + A8896AC3BECAAA504E3828F4 + CF73E1AF93352CF515E7C9F2 + FEB61645EF9120F5BACB7462 + FDA2832E78CFA22BEEC74160 + 7E7E592342D8B7FB73A6F64D + 664D65407BE633C038FA9498 + 938F5A098A216B403906129C + 4ED7BC3AF72F6BE8F0917A30 + E6280B5FA1CEA20450916E49 + E67BC70E17DDA0081C8FD9DD + 8B5F60B902BFFD95E99AAB34 + 4AEA0D08C3B0323FEDC8D974 + 2689C5C8A97002C218125F2F + D66E735BE796BC0675320DC8 + B848522CCA3A75ABD56752C9 + 2D394124F88F348AA4142DCF + D7D83EF74FC7508D9146FA63 + F26E25F3872C0799D6433B99 + F9A4454B00CCFD7265D3CA85 + FBE1B379902B3C585DC8F7A2 + 76AF3B44E0E2FA8BFBD5F592 + 6248640C06B47042BB5BD3F2 + 2BE7216430113F333B8351ED + CCEC29A4351C40BA86F2E491 + 7965EE214E4C332003852642 + 5C48E3511951BB86FA9AA642 + 17E06821FB98542FDB806E50 + BC6931447DE6C359DDDF21F1 + 1C5ED4467DFF0AC3482E9362 + 1902452F5E510A2DBC1E5BD6 + 0D6768C572B6CA49227C29EA + 15C99204FF4D8D72AD034B63 + 334840CA6B3402C8C30CAC4E + 9D33A3E929B0B5D9C002E30E + 4C9B919B991B4E45BC5DC0DB + E2813E36CEFD8D1C1B70E600 + 856BF5AB0322D0689EE63829 + 828EDF7F6C239EA7B17F32F0 + 1E29C7E8C47E3E2DB1C58766 + 64F3DE24F191ECED9DBE903C + 885850B62FAD08EB1D2F0BF4 + BFD3387AA9EFA53E1B4F087B + C38D6DCC3AB9AAE213A64015 + 0DE8B77977749C1835A9472B + 470B5D2AC2F616D10B2E6025 + 5613D5D24B00D8AD909F7E6A + E88F5D4D5E360FA5B5C8F99E + 30CBAAEC78A0E9EBBB10A05A + C7B4B8AD9464A693A3683D0F + D7177CC1E771E1E857F8CB48 + C6305369801B450557086284 + 38EBD5650A3BF5A499B07525 + 1C43CDB79BF40EA7424B9680 + A64B8AA7481267CD4A76C16B + D45991C927E805C3B1AD7516 + DBE31D52BCB0CE44B9D154F0 + F9DF961B5E7D4C4E1E5D029C + 06C7032F68D99A145A53CB6F + E65D547C2CD6A84FC9AF15FA + 48CCCEA0C681DE8B4945111B + 4117B8C24D49837D3DF9C23B + 702A2528CA64B397E9B91ABE + 8178EB9AA3C0268331AF3AF3 + 87035EFE3D4427294D4D1338 + 4D902D60E5CCFA9F2554BC7C + D1387F25A47EF6809B55B59C + 9345327AA463407B3DADBADE + FCCBDB55B98DA36682809F03 + 08A9C84B3CA68561BE01FF37 + 32BD050A579633ADBCA5AF6B + 23FA31CAEA236B2C1E218497 + 5AD807D1AF254F978AB20B1C + 02677FA320D6C63B228A7562 + 5E62D62D32EFCA8D05DDAD1A + + isa + PBXGroup + name + src + sourceTree + <group> + + A492CE86424AB8905550BFD8 + + children + + D60F85FE32E11F4003B80627 + + isa + PBXGroup + name + ofxUI + sourceTree + <group> + + 64C6F7AD018FFD34C7ABB6F2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxUI.h + path + ../../../addons/ofxUI/src/ofxUI.h + sourceTree + SOURCE_ROOT + + F905D46EF2AE96B79CEF0609 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxSecondWindow.h + path + ../../../addons/ofxSecondWindow/src/ofxSecondWindow.h + sourceTree + SOURCE_ROOT + + 4373A30F72067F000063CFF4 + + children + + F6CD5194C7EEB1B621758398 + F905D46EF2AE96B79CEF0609 + + isa + PBXGroup + name + src + sourceTree + <group> + + EDD1D727C7914867117F6F92 + + children + + 4373A30F72067F000063CFF4 + + isa + PBXGroup + name + ofxSecondWindow + sourceTree + <group> + + 87B479F55285F413D96B5A45 + + fileRef + F6CD5194C7EEB1B621758398 + isa + PBXBuildFile + + F6CD5194C7EEB1B621758398 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxSecondWindow.cpp + path + ../../../addons/ofxSecondWindow/src/ofxSecondWindow.cpp + sourceTree + SOURCE_ROOT + + B2B3CC2C074F2E95CED241D8 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + windows_magic.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/windows_magic.h + sourceTree + SOURCE_ROOT + + 200174BB50406AD149EF230B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode.h + sourceTree + SOURCE_ROOT + + E3AF3027D049D507AB40880B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode_abstract.h + sourceTree + SOURCE_ROOT + + 5AE0D7789D08AD70EB9107D7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + unicode.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode.h + sourceTree + SOURCE_ROOT + + CC9A07986E7E8BC4F67FE001 + + children + + 751648C5D0FFBBB967F90216 + 5AE0D7789D08AD70EB9107D7 + E3AF3027D049D507AB40880B + + isa + PBXGroup + name + unicode + sourceTree + <group> + + A81AF6FC4B1FD63D16781582 + + fileRef + 751648C5D0FFBBB967F90216 + isa + PBXBuildFile + + 751648C5D0FFBBB967F90216 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + unicode.cpp + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode/unicode.cpp + sourceTree + SOURCE_ROOT + + 655EE8DEB5C4ECB817FB91AD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + uintn.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/uintn.h + sourceTree + SOURCE_ROOT + + 99D85B9D9ECE68D0ED8DC29E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + stack_trace.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/stack_trace.h + sourceTree + SOURCE_ROOT + + 08B6312D910A25F3FAB2DE34 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + serialize.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/serialize.h + sourceTree + SOURCE_ROOT + + 3A6E2829D76CBA6C2B41AEA9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + platform.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/platform.h + sourceTree + SOURCE_ROOT + + 24CA650B26E1CFA470686366 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + noncopyable.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/noncopyable.h + sourceTree + SOURCE_ROOT + + 23B8C23107F8B07C891E7D8A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + sourceTree + SOURCE_ROOT + + 87B8D031E975EB9A76234A5E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_2.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h + sourceTree + SOURCE_ROOT + + BAD4B18F907F95EE926231A6 + + children + + 49AFD4ACDBD0960C4B2F895D + 87B8D031E975EB9A76234A5E + 23B8C23107F8B07C891E7D8A + + isa + PBXGroup + name + memory_manager_stateless + sourceTree + <group> + + 49AFD4ACDBD0960C4B2F895D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + memory_manager_stateless_kernel_1.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h + sourceTree + SOURCE_ROOT + + C29D31730FB0B5CB905B9128 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix.h + sourceTree + SOURCE_ROOT + + 5CDB5539437B7BFA07BB4835 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + symmetric_matrix_cache_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/symmetric_matrix_cache_abstract.h + sourceTree + SOURCE_ROOT + + 25E5B701EB5BDC165F2DF194 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + symmetric_matrix_cache.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/symmetric_matrix_cache.h + sourceTree + SOURCE_ROOT + + 4B671ACA3983B56A2E1E6C49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_utilities_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_utilities_abstract.h + sourceTree + SOURCE_ROOT + + D40B7CB04EFCB56793A9154D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_utilities.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_utilities.h + sourceTree + SOURCE_ROOT + + E7D2991201D3040FCC343C33 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_trsm.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_trsm.h + sourceTree + SOURCE_ROOT + + AEE4A28F87338E2B366F3943 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_subexp_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_subexp_abstract.h + sourceTree + SOURCE_ROOT + + 275CF29F9F6E302EA3CC39C0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_subexp.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_subexp.h + sourceTree + SOURCE_ROOT + + 87F49A85F9C4184CC5CC65B2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_qr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_qr.h + sourceTree + SOURCE_ROOT + + 1CCB66E5BD14D4CDDBF86AAD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_op.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_op.h + sourceTree + SOURCE_ROOT + + 31ABEE1C91CCD3B8FA515C8C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_math_functions_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_math_functions_abstract.h + sourceTree + SOURCE_ROOT + + 67C70CF980A994969612E66B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_math_functions.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_math_functions.h + sourceTree + SOURCE_ROOT + + E49C95D2F3306510F1D76F5C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_lu.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_lu.h + sourceTree + SOURCE_ROOT + + 59521FEC8B9141FA87A36CC2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_la_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_la_abstract.h + sourceTree + SOURCE_ROOT + + 17F61530DDA2B8B681979EBA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_la.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_la.h + sourceTree + SOURCE_ROOT + + 39F9A5CDDB000E39DDB17368 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_fwd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_fwd.h + sourceTree + SOURCE_ROOT + + 3191CF6F09B2AB0EB02BD884 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_expressions.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_expressions.h + sourceTree + SOURCE_ROOT + + C0A0EF9E9FF190AC8CFC4F4A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_exp_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_exp_abstract.h + sourceTree + SOURCE_ROOT + + 7BE8671BE7DE0BB5832C9A72 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_exp.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_exp.h + sourceTree + SOURCE_ROOT + + F1D431FD749CADB0CAC492F9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_eigenvalue.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_eigenvalue.h + sourceTree + SOURCE_ROOT + + 36C3CDBDC3158A31596788EF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_default_mul.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_default_mul.h + sourceTree + SOURCE_ROOT + + EB21EA3ADDC311649BF059E5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_data_layout_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_data_layout_abstract.h + sourceTree + SOURCE_ROOT + + 2DFB2730898955BDD89EC4CE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_data_layout.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_data_layout.h + sourceTree + SOURCE_ROOT + + B5E6B871EEE8436AD0DF95DA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conv_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conv_abstract.h + sourceTree + SOURCE_ROOT + + A87F18347AF88C7D4AE5696B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conv.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conv.h + sourceTree + SOURCE_ROOT + + AF32EEE2A36AAAD543E5D3E3 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_conj_trans.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_conj_trans.h + sourceTree + SOURCE_ROOT + + 7EE951C9C80AD0DCDB1B48C1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_cholesky.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_cholesky.h + sourceTree + SOURCE_ROOT + + 10473BD60FE76A2833294872 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_blas_bindings.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_blas_bindings.h + sourceTree + SOURCE_ROOT + + F1206CCDEB0A39D50DB4A31A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_assign_fwd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_assign_fwd.h + sourceTree + SOURCE_ROOT + + B1E998B893F7E4148F66A475 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_assign.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_assign.h + sourceTree + SOURCE_ROOT + + EC93B468EB46C8FDA8C94EDC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix_abstract.h + sourceTree + SOURCE_ROOT + + AD381357C0335B99D24BE481 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/matrix.h + sourceTree + SOURCE_ROOT + + 0933A20B994E518CFA2790E6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + syevr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/syevr.h + sourceTree + SOURCE_ROOT + + 45BCB7612D9FBB60AB94D519 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + syev.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/syev.h + sourceTree + SOURCE_ROOT + + C7A2C9F2FBB7CBBF11409562 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + potrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/potrf.h + sourceTree + SOURCE_ROOT + + 0B7EBA8894558B7945CA4A09 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ormqr.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/ormqr.h + sourceTree + SOURCE_ROOT + + E41AEAD9D228B75F62D974F5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + getrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/getrf.h + sourceTree + SOURCE_ROOT + + 71B0FD4BF94BEFED75CFAA84 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gesvd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gesvd.h + sourceTree + SOURCE_ROOT + + ECD39DA0412513D625786668 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gesdd.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gesdd.h + sourceTree + SOURCE_ROOT + + 9F302AC7E036FE8648A7CC79 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + geqrf.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/geqrf.h + sourceTree + SOURCE_ROOT + + A098A96B509DA9C5F88CE89E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + geev.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/geev.h + sourceTree + SOURCE_ROOT + + 460BFED3116BE472629E249A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gees.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/gees.h + sourceTree + SOURCE_ROOT + + 5DBA52B926F1A58092156EE8 + + children + + 478FC1C0EF37E878F11135E0 + 460BFED3116BE472629E249A + A098A96B509DA9C5F88CE89E + 9F302AC7E036FE8648A7CC79 + ECD39DA0412513D625786668 + 71B0FD4BF94BEFED75CFAA84 + E41AEAD9D228B75F62D974F5 + 0B7EBA8894558B7945CA4A09 + C7A2C9F2FBB7CBBF11409562 + 45BCB7612D9FBB60AB94D519 + 0933A20B994E518CFA2790E6 + + isa + PBXGroup + name + lapack + sourceTree + <group> + + 478FC1C0EF37E878F11135E0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + fortran_id.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack/fortran_id.h + sourceTree + SOURCE_ROOT + + 44C2B72920E6B50F102F7269 + + children + + 01BB0905E394E835585A82AE + 5DBA52B926F1A58092156EE8 + AD381357C0335B99D24BE481 + EC93B468EB46C8FDA8C94EDC + B1E998B893F7E4148F66A475 + F1206CCDEB0A39D50DB4A31A + 10473BD60FE76A2833294872 + 7EE951C9C80AD0DCDB1B48C1 + AF32EEE2A36AAAD543E5D3E3 + A87F18347AF88C7D4AE5696B + B5E6B871EEE8436AD0DF95DA + 2DFB2730898955BDD89EC4CE + EB21EA3ADDC311649BF059E5 + 36C3CDBDC3158A31596788EF + F1D431FD749CADB0CAC492F9 + 7BE8671BE7DE0BB5832C9A72 + C0A0EF9E9FF190AC8CFC4F4A + 3191CF6F09B2AB0EB02BD884 + 39F9A5CDDB000E39DDB17368 + 17F61530DDA2B8B681979EBA + 59521FEC8B9141FA87A36CC2 + E49C95D2F3306510F1D76F5C + 67C70CF980A994969612E66B + 31ABEE1C91CCD3B8FA515C8C + 1CCB66E5BD14D4CDDBF86AAD + 87F49A85F9C4184CC5CC65B2 + 275CF29F9F6E302EA3CC39C0 + AEE4A28F87338E2B366F3943 + E7D2991201D3040FCC343C33 + D40B7CB04EFCB56793A9154D + 4B671ACA3983B56A2E1E6C49 + 25E5B701EB5BDC165F2DF194 + 5CDB5539437B7BFA07BB4835 + + isa + PBXGroup + name + matrix + sourceTree + <group> + + 01BB0905E394E835585A82AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cblas_constants.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/cblas_constants.h + sourceTree + SOURCE_ROOT + + 9EBA5A473DF6602B55ED5A24 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + is_kind.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/is_kind.h + sourceTree + SOURCE_ROOT + + B7FFF828FB3FC4CB1D215EE2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + remover.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/remover.h + sourceTree + SOURCE_ROOT + + 66E7E760DDF064D6668F45A4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + map_pair.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/map_pair.h + sourceTree + SOURCE_ROOT + + 6288E24AAE815FD4E7BB801D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + enumerable.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/enumerable.h + sourceTree + SOURCE_ROOT + + D921FCCC63B1E4FAFFCFE868 + + children + + 4E498923F62DF3BC70DDDEB2 + 6288E24AAE815FD4E7BB801D + 66E7E760DDF064D6668F45A4 + B7FFF828FB3FC4CB1D215EE2 + + isa + PBXGroup + name + interfaces + sourceTree + <group> + + 4E498923F62DF3BC70DDDEB2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cmd_line_parser_option.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces/cmd_line_parser_option.h + sourceTree + SOURCE_ROOT + + 480C8EC00BA4CE29EF81DCBD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + vector_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/vector_abstract.h + sourceTree + SOURCE_ROOT + + 4CE94487715FC9258E27F263 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + vector.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/vector.h + sourceTree + SOURCE_ROOT + + 4770FCC900806FF4A318B9DD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + rectangle_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/rectangle_abstract.h + sourceTree + SOURCE_ROOT + + EFE7CF779199FC56C99C8301 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + rectangle.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/rectangle.h + sourceTree + SOURCE_ROOT + + 34854DEA54B6E271DDB3EC88 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + border_enumerator_abstract.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/border_enumerator_abstract.h + sourceTree + SOURCE_ROOT + + 1024DC0F73E42400BEA1BED5 + + children + + AA589AAECC2B11C988C51CD0 + 34854DEA54B6E271DDB3EC88 + EFE7CF779199FC56C99C8301 + 4770FCC900806FF4A318B9DD + 4CE94487715FC9258E27F263 + 480C8EC00BA4CE29EF81DCBD + + isa + PBXGroup + name + geometry + sourceTree + <group> + + AA589AAECC2B11C988C51CD0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + border_enumerator.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry/border_enumerator.h + sourceTree + SOURCE_ROOT + + 0483F8A1ACA86368FB1BF327 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + error.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/error.h + sourceTree + SOURCE_ROOT + + A1A95627959627BD1FD18E13 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + enable_if.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/enable_if.h + sourceTree + SOURCE_ROOT + + BB0839801B8ED36BF6A65A49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dassert.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/dassert.h + sourceTree + SOURCE_ROOT + + 14C7E0F55968225EA9BFE780 + + children + + 47E8718ACC3E212F1F9C4E2D + BB0839801B8ED36BF6A65A49 + A1A95627959627BD1FD18E13 + 0483F8A1ACA86368FB1BF327 + 1024DC0F73E42400BEA1BED5 + D921FCCC63B1E4FAFFCFE868 + 9EBA5A473DF6602B55ED5A24 + 44C2B72920E6B50F102F7269 + C29D31730FB0B5CB905B9128 + BAD4B18F907F95EE926231A6 + 24CA650B26E1CFA470686366 + 3A6E2829D76CBA6C2B41AEA9 + 08B6312D910A25F3FAB2DE34 + 99D85B9D9ECE68D0ED8DC29E + 655EE8DEB5C4ECB817FB91AD + CC9A07986E7E8BC4F67FE001 + 200174BB50406AD149EF230B + B2B3CC2C074F2E95CED241D8 + + isa + PBXGroup + name + dlib + sourceTree + <group> + + D485F5AC132675EC9F9B3690 + + children + + 14C7E0F55968225EA9BFE780 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 47E8718ACC3E212F1F9C4E2D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + algs.h + path + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/algs.h + sourceTree + SOURCE_ROOT + + 44F1E3614D38B396A22DD7E7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectProjectorToolkit.h + path + ../../../addons/ofxKinectProjectorToolkit/src/ofxKinectProjectorToolkit.h + sourceTree + SOURCE_ROOT + + 3803B3BFF0E596F8697B9DCE + + children + + B9F41088D07970B50DBA136F + 44F1E3614D38B396A22DD7E7 + + isa + PBXGroup + name + src + sourceTree + <group> + + FD702F29E90B58DEC499A265 + + children + + 3803B3BFF0E596F8697B9DCE + D485F5AC132675EC9F9B3690 + + isa + PBXGroup + name + ofxKinectProjectorToolkit + sourceTree + <group> + + 12898A2212C6B1397854D45E + + fileRef + B9F41088D07970B50DBA136F + isa + PBXBuildFile + + B9F41088D07970B50DBA136F + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectProjectorToolkit.cpp + path + ../../../addons/ofxKinectProjectorToolkit/src/ofxKinectProjectorToolkit.cpp + sourceTree + SOURCE_ROOT + + DBCB84A37F9AECC254870D79 + + fileRef + D347FB65D19015303863922A + isa + PBXBuildFile + + D347FB65D19015303863922A + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Wrappers.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Wrappers.cpp + sourceTree + SOURCE_ROOT + + A6668C5B1272D7FCD5B5A16F + + fileRef + 6CEC50DB3D06414010233963 + isa + PBXBuildFile + + 6CEC50DB3D06414010233963 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Utilities.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Utilities.cpp + sourceTree + SOURCE_ROOT + + 10B69DE456AED1288FC9316B + + fileRef + A810DF70319A10353588F5DB + isa + PBXBuildFile + + A810DF70319A10353588F5DB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Tracker.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Tracker.cpp + sourceTree + SOURCE_ROOT + + 7CDAD32BE4FA46701E3552C7 + + fileRef + 5CBF6AED6A17AC0C17F63CC4 + isa + PBXBuildFile + + 5CBF6AED6A17AC0C17F63CC4 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + RunningBackground.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/RunningBackground.cpp + sourceTree + SOURCE_ROOT + + C602002DE761F9B52DB4400A + + fileRef + AE75A3FBA2C2D87D14F06FE6 + isa + PBXBuildFile + + AE75A3FBA2C2D87D14F06FE6 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ObjectFinder.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/ObjectFinder.cpp + sourceTree + SOURCE_ROOT + + 2023EF517ED2D8B397511D4B + + fileRef + B9076967F8C54A04362C04AA + isa + PBXBuildFile + + B9076967F8C54A04362C04AA + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Helpers.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Helpers.cpp + sourceTree + SOURCE_ROOT + + 5CC34D433F5806179935B89D + + fileRef + 03A75A648BC4CF1D9DEDD0CE + isa + PBXBuildFile + + 03A75A648BC4CF1D9DEDD0CE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Flow.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Flow.cpp + sourceTree + SOURCE_ROOT + + 45CC483A999BF1065A6B926C + + fileRef + 9DBD717072C35D324E101669 + isa + PBXBuildFile + + 9DBD717072C35D324E101669 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Distance.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Distance.cpp + sourceTree + SOURCE_ROOT + + 6AABAB39E82AF5CFEA23A205 + + fileRef + 5FBB4A8427353AED09174BE5 + isa + PBXBuildFile + + 5FBB4A8427353AED09174BE5 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ContourFinder.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/ContourFinder.cpp + sourceTree + SOURCE_ROOT + + D240A1DD1AE9F8E81BDBCD2B + + children + + 402C8F4015542356D362AC88 + 5FBB4A8427353AED09174BE5 + 9DBD717072C35D324E101669 + 03A75A648BC4CF1D9DEDD0CE + B9076967F8C54A04362C04AA + AE75A3FBA2C2D87D14F06FE6 + 5CBF6AED6A17AC0C17F63CC4 + A810DF70319A10353588F5DB + 6CEC50DB3D06414010233963 + D347FB65D19015303863922A + + isa + PBXGroup + name + src + sourceTree + <group> + + EBCDE831EFAE08274E799C97 + + fileRef + 402C8F4015542356D362AC88 + isa + PBXBuildFile + + 402C8F4015542356D362AC88 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + Calibration.cpp + path + ../../../addons/ofxCv/libs/ofxCv/src/Calibration.cpp + sourceTree + SOURCE_ROOT + + 73157AAE32787C63313C7D8E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Wrappers.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Wrappers.h + sourceTree + SOURCE_ROOT + + 84D3470A12DEE51F320224AC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Utilities.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Utilities.h + sourceTree + SOURCE_ROOT + + 70046E043EDDB466ED625C3B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Tracker.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Tracker.h + sourceTree + SOURCE_ROOT + + 6B3CDFD1A15E92F074E7D5AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + RunningBackground.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/RunningBackground.h + sourceTree + SOURCE_ROOT + + 4524C0ED0C2DD3E085CE3350 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ObjectFinder.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/ObjectFinder.h + sourceTree + SOURCE_ROOT + + 8738DE90218B1E9054A88B54 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Helpers.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Helpers.h + sourceTree + SOURCE_ROOT + + 8326CDEDA153D242D924D2B6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Flow.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Flow.h + sourceTree + SOURCE_ROOT + + D29DD28C195CD81267F3C8A1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Distance.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Distance.h + sourceTree + SOURCE_ROOT + + 178547E33CE398C7B59F08AB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ContourFinder.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/ContourFinder.h + sourceTree + SOURCE_ROOT + + 4EB038C7DF921AA8A4070286 + + children + + 58140E0F92D37844E9C8883D + 178547E33CE398C7B59F08AB + D29DD28C195CD81267F3C8A1 + 8326CDEDA153D242D924D2B6 + 8738DE90218B1E9054A88B54 + 4524C0ED0C2DD3E085CE3350 + 6B3CDFD1A15E92F074E7D5AE + 70046E043EDDB466ED625C3B + 84D3470A12DEE51F320224AC + 73157AAE32787C63313C7D8E + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 13C72B31738CA9F68523CB1C + + children + + 4EB038C7DF921AA8A4070286 + + isa + PBXGroup + name + include + sourceTree + <group> + + 85961BEC127E2550AA7756C9 + + children + + 13C72B31738CA9F68523CB1C + D240A1DD1AE9F8E81BDBCD2B + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 58140E0F92D37844E9C8883D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + Calibration.h + path + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv/Calibration.h + sourceTree + SOURCE_ROOT + + F76B4A79BD8DE4854141CB47 + + fileRef + A2D8249D46647E3C51769CDE + isa + PBXBuildFile + + A2D8249D46647E3C51769CDE + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + fdog.cpp + path + ../../../addons/ofxCv/libs/CLD/src/fdog.cpp + sourceTree + SOURCE_ROOT + + 37CF39B443ACB0F86B1351ED + + children + + B047FF96258DC01792B272DB + A2D8249D46647E3C51769CDE + + isa + PBXGroup + name + src + sourceTree + <group> + + B6840996567E78436F7ECFAB + + fileRef + B047FF96258DC01792B272DB + isa + PBXBuildFile + + B047FF96258DC01792B272DB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ETF.cpp + path + ../../../addons/ofxCv/libs/CLD/src/ETF.cpp + sourceTree + SOURCE_ROOT + + FE15469185A3A49FEC9D2292 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + myvec.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/myvec.h + sourceTree + SOURCE_ROOT + + DB0CD4C938C079DCD67222FE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imatrix.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/imatrix.h + sourceTree + SOURCE_ROOT + + CC455256CE0ECFE328853737 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + fdog.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/fdog.h + sourceTree + SOURCE_ROOT + + FEA273413D5AFD9607F56ABE + + children + + 820102E51B125101D727B3CC + CC455256CE0ECFE328853737 + DB0CD4C938C079DCD67222FE + FE15469185A3A49FEC9D2292 + + isa + PBXGroup + name + CLD + sourceTree + <group> + + 45591C11B7434576DF6996B4 + + children + + FEA273413D5AFD9607F56ABE + + isa + PBXGroup + name + include + sourceTree + <group> + + 7CC1E591490DB083FB916812 + + children + + 45591C11B7434576DF6996B4 + 37CF39B443ACB0F86B1351ED + + isa + PBXGroup + name + CLD + sourceTree + <group> + + 90D509C72729D1998E28A98F + + children + + 7CC1E591490DB083FB916812 + 85961BEC127E2550AA7756C9 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 820102E51B125101D727B3CC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ETF.h + path + ../../../addons/ofxCv/libs/CLD/include/CLD/ETF.h + sourceTree + SOURCE_ROOT + + 873F2BD1A608B2DE7BC81AFB + + children + + 325BD94FFB93161BBC68336E + + isa + PBXGroup + name + src + sourceTree + <group> + + 6025FAF6414C2CA589764D26 + + children + + 873F2BD1A608B2DE7BC81AFB + 90D509C72729D1998E28A98F + + isa + PBXGroup + name + ofxCv + sourceTree + <group> + + 325BD94FFB93161BBC68336E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCv.h + path + ../../../addons/ofxCv/src/ofxCv.h + sourceTree + SOURCE_ROOT + + 5A4349E9754D6FA14C0F2A3A + + fileRef + FC5DA1C87211D4F6377DA719 + isa + PBXBuildFile + + FC5DA1C87211D4F6377DA719 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxmlparser.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxmlparser.cpp + sourceTree + SOURCE_ROOT + + 9D44DC88EF9E7991B4A09951 + + fileRef + 832BDC407620CDBA568B713D + isa + PBXBuildFile + + 832BDC407620CDBA568B713D + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxmlerror.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxmlerror.cpp + sourceTree + SOURCE_ROOT + + B21E7E5F548EEA92F368040B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + tinyxml.h + path + ../../../addons/ofxXmlSettings/libs/tinyxml.h + sourceTree + SOURCE_ROOT + + 6E54289412D2D94F45A05113 + + children + + 2B40EDA85BEB63E46785BC29 + B21E7E5F548EEA92F368040B + 832BDC407620CDBA568B713D + FC5DA1C87211D4F6377DA719 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 933A2227713C720CEFF80FD9 + + fileRef + 2B40EDA85BEB63E46785BC29 + isa + PBXBuildFile + + 2B40EDA85BEB63E46785BC29 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + tinyxml.cpp + path + ../../../addons/ofxXmlSettings/libs/tinyxml.cpp + sourceTree + SOURCE_ROOT + + 01DCC0911400F9ACF5B65578 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxXmlSettings.h + path + ../../../addons/ofxXmlSettings/src/ofxXmlSettings.h + sourceTree + SOURCE_ROOT + + 6ECEF0D76BC33727823EADFF + + children + + 50DF87D612C5AAE17AAFA6C0 + 01DCC0911400F9ACF5B65578 + + isa + PBXGroup + name + src + sourceTree + <group> + + 1F4FB5C423662B96ADFDCC0B + + children + + 6ECEF0D76BC33727823EADFF + 6E54289412D2D94F45A05113 + + isa + PBXGroup + name + ofxXmlSettings + sourceTree + <group> + + 63B57AC5BF4EF088491E0317 + + fileRef + 50DF87D612C5AAE17AAFA6C0 + isa + PBXBuildFile + + 50DF87D612C5AAE17AAFA6C0 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxXmlSettings.cpp + path + ../../../addons/ofxXmlSettings/src/ofxXmlSettings.cpp + sourceTree + SOURCE_ROOT + + 97FBD89E6180673035AD1083 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + video.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/video.hpp + sourceTree + SOURCE_ROOT + + E14D3EF03E140F5604900412 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + tracking.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/tracking.hpp + sourceTree + SOURCE_ROOT + + C58CC92A5283B95AA31D50FB + + children + + 71C98C3F44D63B39F1482A54 + E14D3EF03E140F5604900412 + 97FBD89E6180673035AD1083 + + isa + PBXGroup + name + video + sourceTree + <group> + + 71C98C3F44D63B39F1482A54 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + background_segm.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video/background_segm.hpp + sourceTree + SOURCE_ROOT + + C4FB85020773DA0F09B8B6CE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ts_gtest.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts/ts_gtest.h + sourceTree + SOURCE_ROOT + + 0478E60892BF4C0731AE0763 + + children + + 7673F0AA19794A4C9517CF14 + C4FB85020773DA0F09B8B6CE + + isa + PBXGroup + name + ts + sourceTree + <group> + + 7673F0AA19794A4C9517CF14 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ts.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts/ts.hpp + sourceTree + SOURCE_ROOT + + 9B7D592E7AB311451A27C46E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + opencv.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/opencv.hpp + sourceTree + SOURCE_ROOT + + D0CAFE48EE488EEED9149670 + + children + + 97CFAD0B2F2DB004A8A3BC0B + + isa + PBXGroup + name + objdetect + sourceTree + <group> + + 97CFAD0B2F2DB004A8A3BC0B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + objdetect.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect/objdetect.hpp + sourceTree + SOURCE_ROOT + + 0F288FD421D474F4AE2684D3 + + children + + 59626D03C690200AD4E8B3A6 + + isa + PBXGroup + name + ml + sourceTree + <group> + + 59626D03C690200AD4E8B3A6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ml.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml/ml.hpp + sourceTree + SOURCE_ROOT + + 60179A75A6C5F9A54DA3A64C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + streams.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/streams.hpp + sourceTree + SOURCE_ROOT + + 8530EAD600CD792B81B2E79D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + legacy.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/legacy.hpp + sourceTree + SOURCE_ROOT + + 665780A3005496E3A4A0D9EF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + compat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/compat.hpp + sourceTree + SOURCE_ROOT + + 961A625BD21068033782887C + + children + + 5D966EA1AA66E2D55D047733 + 665780A3005496E3A4A0D9EF + 8530EAD600CD792B81B2E79D + 60179A75A6C5F9A54DA3A64C + + isa + PBXGroup + name + legacy + sourceTree + <group> + + 5D966EA1AA66E2D55D047733 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + blobtrack.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy/blobtrack.hpp + sourceTree + SOURCE_ROOT + + 9B90B3EE60497170AA00BFE8 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + types_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/types_c.h + sourceTree + SOURCE_ROOT + + 9B55998E41388AD8704E4F9A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imgproc_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/imgproc_c.h + sourceTree + SOURCE_ROOT + + 3E44059DCBC2444D65660B9C + + children + + 114B872696817CC33990FC83 + 9B55998E41388AD8704E4F9A + 9B90B3EE60497170AA00BFE8 + + isa + PBXGroup + name + imgproc + sourceTree + <group> + + 114B872696817CC33990FC83 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + imgproc.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc/imgproc.hpp + sourceTree + SOURCE_ROOT + + AE433383D6CA170C418C8A9E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui/highgui_c.h + sourceTree + SOURCE_ROOT + + 9C99831C330874C2B245AB48 + + children + + C61D3DACE506E4A1C3A6D782 + AE433383D6CA170C418C8A9E + + isa + PBXGroup + name + highgui + sourceTree + <group> + + C61D3DACE506E4A1C3A6D782 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui/highgui.hpp + sourceTree + SOURCE_ROOT + + D902EB2409214285BCF5F191 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + stream_accessor.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/stream_accessor.hpp + sourceTree + SOURCE_ROOT + + B683B7ADA51410A7F0B13E6A + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix_operations.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/matrix_operations.hpp + sourceTree + SOURCE_ROOT + + E354468911BA093791076DD7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gpumat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/gpumat.hpp + sourceTree + SOURCE_ROOT + + AF9A155219FEDFA6E95454EA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + gpu.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/gpu.hpp + sourceTree + SOURCE_ROOT + + 5236346776DB8ECC4B121CA3 + + children + + F886EBA3F8F05C7F74633933 + AF9A155219FEDFA6E95454EA + E354468911BA093791076DD7 + B683B7ADA51410A7F0B13E6A + D902EB2409214285BCF5F191 + + isa + PBXGroup + name + gpu + sourceTree + <group> + + F886EBA3F8F05C7F74633933 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + devmem2d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu/devmem2d.hpp + sourceTree + SOURCE_ROOT + + 1E95EFD35ED9C5D97F2F015E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + timer.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/timer.h + sourceTree + SOURCE_ROOT + + 45F38573A0B0DEEC8BBC7A2C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + simplex_downhill.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/simplex_downhill.h + sourceTree + SOURCE_ROOT + + 01DAE5C2E3E0A74207B2BE49 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + saving.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/saving.h + sourceTree + SOURCE_ROOT + + 7E57AAE3FAB29F87D19451BC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + sampling.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/sampling.h + sourceTree + SOURCE_ROOT + + 974AACF856A0A1B7D8F259E0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + result_set.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/result_set.h + sourceTree + SOURCE_ROOT + + ECC34C470C60F0A2AE2761B1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + random.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/random.h + sourceTree + SOURCE_ROOT + + F070AF5E3926EB2CB7A15D1B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + params.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/params.h + sourceTree + SOURCE_ROOT + + F9EC3DDC0E9F85C34B21C760 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + object_factory.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/object_factory.h + sourceTree + SOURCE_ROOT + + 8DB45DE3BD6BB97E34BDB411 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + nn_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/nn_index.h + sourceTree + SOURCE_ROOT + + 9DA0CBD43DA38386EB04C9AE + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + miniflann.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/miniflann.hpp + sourceTree + SOURCE_ROOT + + A15E0125B8C9B7F01DED5695 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + matrix.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/matrix.h + sourceTree + SOURCE_ROOT + + FEDA0B6056089762F5FA11CA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + lsh_table.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/lsh_table.h + sourceTree + SOURCE_ROOT + + B7BF51E8E757FF8A162D3662 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + lsh_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/lsh_index.h + sourceTree + SOURCE_ROOT + + 0173A3F435DECD5A4DDE0B8E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + logger.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/logger.h + sourceTree + SOURCE_ROOT + + FB213FF0567D1B312DDBD05D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + linear_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/linear_index.h + sourceTree + SOURCE_ROOT + + 2E411F99E3AB7154484B4F96 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kmeans_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kmeans_index.h + sourceTree + SOURCE_ROOT + + 758F19335D4E46A5E0DE449F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kdtree_single_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kdtree_single_index.h + sourceTree + SOURCE_ROOT + + 49EFFCF36CF194CCE0E1FAAB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + kdtree_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/kdtree_index.h + sourceTree + SOURCE_ROOT + + DCB56F4E9F44E31D571BC9C4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + index_testing.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/index_testing.h + sourceTree + SOURCE_ROOT + + 946187321200AC04E570E6EC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + hierarchical_clustering_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/hierarchical_clustering_index.h + sourceTree + SOURCE_ROOT + + 6B907CFBB1B0FEDE76C41AA0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + heap.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/heap.h + sourceTree + SOURCE_ROOT + + FF58A50E588D6A64EE206840 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + hdf5.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/hdf5.h + sourceTree + SOURCE_ROOT + + 0CF0AA3895D28E97D8A1E4A9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ground_truth.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/ground_truth.h + sourceTree + SOURCE_ROOT + + CBDE84185E2969BA4AB209FC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + general.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/general.h + sourceTree + SOURCE_ROOT + + 9B076DCB5B800BE9AF1B71A6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flann_base.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/flann_base.hpp + sourceTree + SOURCE_ROOT + + 6DD5A3CBB6D5BBA1C1354F1B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flann.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/flann.hpp + sourceTree + SOURCE_ROOT + + 096CB33CAD6C5A446E7026E9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dynamic_bitset.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dynamic_bitset.h + sourceTree + SOURCE_ROOT + + 36F0FF7F8D7342D220CC6319 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dummy.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dummy.h + sourceTree + SOURCE_ROOT + + FD609E2EC17FCE181DFE635F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + dist.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/dist.h + sourceTree + SOURCE_ROOT + + 722542BCDC94162B6A8B9B72 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + defines.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/defines.h + sourceTree + SOURCE_ROOT + + 586A8EC141BDFA82B3B0518C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + config.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/config.h + sourceTree + SOURCE_ROOT + + D5A3AFF36064B2CACAD31716 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + composite_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/composite_index.h + sourceTree + SOURCE_ROOT + + E7DDB716B5AE0DEA82DFFEDA + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + autotuned_index.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/autotuned_index.h + sourceTree + SOURCE_ROOT + + 45410DD818BB205166E67E89 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + any.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/any.h + sourceTree + SOURCE_ROOT + + E5F6E381641665852B997FC4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + allocator.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/allocator.h + sourceTree + SOURCE_ROOT + + 1E45F8C3CCFF6847BFF957AA + + children + + 011E372AEA4DFBC1A32C2851 + E5F6E381641665852B997FC4 + 45410DD818BB205166E67E89 + E7DDB716B5AE0DEA82DFFEDA + D5A3AFF36064B2CACAD31716 + 586A8EC141BDFA82B3B0518C + 722542BCDC94162B6A8B9B72 + FD609E2EC17FCE181DFE635F + 36F0FF7F8D7342D220CC6319 + 096CB33CAD6C5A446E7026E9 + 6DD5A3CBB6D5BBA1C1354F1B + 9B076DCB5B800BE9AF1B71A6 + CBDE84185E2969BA4AB209FC + 0CF0AA3895D28E97D8A1E4A9 + FF58A50E588D6A64EE206840 + 6B907CFBB1B0FEDE76C41AA0 + 946187321200AC04E570E6EC + DCB56F4E9F44E31D571BC9C4 + 49EFFCF36CF194CCE0E1FAAB + 758F19335D4E46A5E0DE449F + 2E411F99E3AB7154484B4F96 + FB213FF0567D1B312DDBD05D + 0173A3F435DECD5A4DDE0B8E + B7BF51E8E757FF8A162D3662 + FEDA0B6056089762F5FA11CA + A15E0125B8C9B7F01DED5695 + 9DA0CBD43DA38386EB04C9AE + 8DB45DE3BD6BB97E34BDB411 + F9EC3DDC0E9F85C34B21C760 + F070AF5E3926EB2CB7A15D1B + ECC34C470C60F0A2AE2761B1 + 974AACF856A0A1B7D8F259E0 + 7E57AAE3FAB29F87D19451BC + 01DAE5C2E3E0A74207B2BE49 + 45F38573A0B0DEEC8BBC7A2C + 1E95EFD35ED9C5D97F2F015E + + isa + PBXGroup + name + flann + sourceTree + <group> + + 011E372AEA4DFBC1A32C2851 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + all_indices.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann/all_indices.h + sourceTree + SOURCE_ROOT + + 86FEC009E2721D0FB23338D7 + + children + + 61339778C58D921474B5729E + + isa + PBXGroup + name + features2d + sourceTree + <group> + + 61339778C58D921474B5729E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + features2d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d/features2d.hpp + sourceTree + SOURCE_ROOT + + A9C85208C7E45FB9D1926789 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + wimage.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/wimage.hpp + sourceTree + SOURCE_ROOT + + E8AF1E9150AD818FA9D9195D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + version.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/version.hpp + sourceTree + SOURCE_ROOT + + CD8565F2F122EECA0C095526 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + types_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/types_c.h + sourceTree + SOURCE_ROOT + + E4385429A1E63ACEDC39A612 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + operations.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/operations.hpp + sourceTree + SOURCE_ROOT + + AB2AE477F82ACF17D0121166 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + mat.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/mat.hpp + sourceTree + SOURCE_ROOT + + 452417865E4BFB10C9CBF8A2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + internal.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/internal.hpp + sourceTree + SOURCE_ROOT + + A2EE5E80B134EA52A8B369D2 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + eigen.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/eigen.hpp + sourceTree + SOURCE_ROOT + + 087522EA37A32B8D902CAB64 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + core_c.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/core_c.h + sourceTree + SOURCE_ROOT + + A5A3A2F98919E2243C73199C + + children + + C66C6414C8B86FDB99ED3B70 + 087522EA37A32B8D902CAB64 + A2EE5E80B134EA52A8B369D2 + 452417865E4BFB10C9CBF8A2 + AB2AE477F82ACF17D0121166 + E4385429A1E63ACEDC39A612 + CD8565F2F122EECA0C095526 + E8AF1E9150AD818FA9D9195D + A9C85208C7E45FB9D1926789 + + isa + PBXGroup + name + core + sourceTree + <group> + + C66C6414C8B86FDB99ED3B70 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + core.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core/core.hpp + sourceTree + SOURCE_ROOT + + A0399084868E7CAFB7E3D8E9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + retina.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib/retina.hpp + sourceTree + SOURCE_ROOT + + 170C3384C93B182490DDC9CC + + children + + 5A59183C98FC5E69FC90F138 + A0399084868E7CAFB7E3D8E9 + + isa + PBXGroup + name + contrib + sourceTree + <group> + + 5A59183C98FC5E69FC90F138 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + contrib.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib/contrib.hpp + sourceTree + SOURCE_ROOT + + 428EB732FD42504F37BCA78A + + children + + 67AF0E794FA186DD25454CC9 + + isa + PBXGroup + name + calib3d + sourceTree + <group> + + 0F07FE174552DEF007BF5AD5 + + children + + 428EB732FD42504F37BCA78A + 170C3384C93B182490DDC9CC + A5A3A2F98919E2243C73199C + 86FEC009E2721D0FB23338D7 + 1E45F8C3CCFF6847BFF957AA + 5236346776DB8ECC4B121CA3 + 9C99831C330874C2B245AB48 + 3E44059DCBC2444D65660B9C + 961A625BD21068033782887C + 0F288FD421D474F4AE2684D3 + D0CAFE48EE488EEED9149670 + 9B7D592E7AB311451A27C46E + 0478E60892BF4C0731AE0763 + C58CC92A5283B95AA31D50FB + + isa + PBXGroup + name + opencv2 + sourceTree + <group> + + 67AF0E794FA186DD25454CC9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + calib3d.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d/calib3d.hpp + sourceTree + SOURCE_ROOT + + 7C3D9C0EAC738ED2624D264B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ml.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/ml.h + sourceTree + SOURCE_ROOT + + 9FF9126184DFBDE8A912373E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + highgui.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/highgui.h + sourceTree + SOURCE_ROOT + + E90542C149C83316678AB011 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxmisc.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxmisc.h + sourceTree + SOURCE_ROOT + + 319268D200F1BA567E4CCFF9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxeigen.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxeigen.hpp + sourceTree + SOURCE_ROOT + + 7101CF2125B8B2BF46AA2662 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxcore.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxcore.hpp + sourceTree + SOURCE_ROOT + + B8427966039B53A0FE69C1F0 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cxcore.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cxcore.h + sourceTree + SOURCE_ROOT + + DB8653D6433E14BF06F3EFAF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvwimage.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvwimage.h + sourceTree + SOURCE_ROOT + + CF29BFB3FD3CAA54F336E6FD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvaux.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvaux.hpp + sourceTree + SOURCE_ROOT + + D76A59E7B3601E76351C9BDB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cvaux.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cvaux.h + sourceTree + SOURCE_ROOT + + 30884ECD9C171AB1B1BDFC3F + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cv.hpp + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cv.hpp + sourceTree + SOURCE_ROOT + + 737B033AA777B67BA4F8F4D2 + + children + + 33FF03222909C1A0ECE43753 + 30884ECD9C171AB1B1BDFC3F + D76A59E7B3601E76351C9BDB + CF29BFB3FD3CAA54F336E6FD + DB8653D6433E14BF06F3EFAF + B8427966039B53A0FE69C1F0 + 7101CF2125B8B2BF46AA2662 + 319268D200F1BA567E4CCFF9 + E90542C149C83316678AB011 + 9FF9126184DFBDE8A912373E + 7C3D9C0EAC738ED2624D264B + + isa + PBXGroup + name + opencv + sourceTree + <group> + + F9F05170CB9BDF47DA2B6E6A + + children + + 737B033AA777B67BA4F8F4D2 + 0F07FE174552DEF007BF5AD5 + + isa + PBXGroup + name + include + sourceTree + <group> + + AAA97F42C2FE4A31ECFD0585 + + children + + F9F05170CB9BDF47DA2B6E6A + + isa + PBXGroup + name + opencv + sourceTree + <group> + + DCC60D6724B56635AE867535 + + children + + AAA97F42C2FE4A31ECFD0585 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 33FF03222909C1A0ECE43753 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cv.h + path + ../../../addons/ofxOpenCv/libs/opencv/include/opencv/cv.h + sourceTree + SOURCE_ROOT + + CE81A5E39EB3C871FDF3D4D5 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxOpenCv.h + path + ../../../addons/ofxOpenCv/src/ofxOpenCv.h + sourceTree + SOURCE_ROOT + + DEA2EDC0AFD59176FDEDC222 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvShortImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvShortImage.h + sourceTree + SOURCE_ROOT + + D3301F6A0B43BB293ED97C1D + + fileRef + 8A4DD23693DFAB8EC05FAA5D + isa + PBXBuildFile + + 8A4DD23693DFAB8EC05FAA5D + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvShortImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvShortImage.cpp + sourceTree + SOURCE_ROOT + + D847EBE484F4F500F9CF2549 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvImage.h + sourceTree + SOURCE_ROOT + + 63020F16C7E8DED980111241 + + fileRef + C6151136D101F857DAE12722 + isa + PBXBuildFile + + C6151136D101F857DAE12722 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvImage.cpp + sourceTree + SOURCE_ROOT + + 516717F84C0146512C47A3EC + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvHaarFinder.h + path + ../../../addons/ofxOpenCv/src/ofxCvHaarFinder.h + sourceTree + SOURCE_ROOT + + E212C821D1064B92DD953A42 + + fileRef + 9A16CBF2E8CFE43AF54FE6F5 + isa + PBXBuildFile + + 9A16CBF2E8CFE43AF54FE6F5 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvHaarFinder.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvHaarFinder.cpp + sourceTree + SOURCE_ROOT + + 9A048549F08C6DFFA79E6DEF + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvGrayscaleImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvGrayscaleImage.h + sourceTree + SOURCE_ROOT + + FB09C6B2A1DA0EA217240CB8 + + fileRef + 057122A817D12571F8C0C7A4 + isa + PBXBuildFile + + 057122A817D12571F8C0C7A4 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvGrayscaleImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvGrayscaleImage.cpp + sourceTree + SOURCE_ROOT + + F7269F96AC34A2B44A680D03 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvFloatImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvFloatImage.h + sourceTree + SOURCE_ROOT + + 169D3C72FDE6C5590A1616F5 + + fileRef + 7B6A03390302D5A2C9F0E4AB + isa + PBXBuildFile + + 7B6A03390302D5A2C9F0E4AB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvFloatImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvFloatImage.cpp + sourceTree + SOURCE_ROOT + + C1C56D20A1A57DC44096BFE7 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvContourFinder.h + path + ../../../addons/ofxOpenCv/src/ofxCvContourFinder.h + sourceTree + SOURCE_ROOT + + 1D5F3298C2FA073628012944 + + fileRef + C76DE5C29BDBD2CAA1DD0021 + isa + PBXBuildFile + + C76DE5C29BDBD2CAA1DD0021 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvContourFinder.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvContourFinder.cpp + sourceTree + SOURCE_ROOT + + 8E79CF8911DFABAFE23EA45B + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvConstants.h + path + ../../../addons/ofxOpenCv/src/ofxCvConstants.h + sourceTree + SOURCE_ROOT + + D5BB6F0357B6422E1B1656B4 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvColorImage.h + path + ../../../addons/ofxOpenCv/src/ofxCvColorImage.h + sourceTree + SOURCE_ROOT + + 250A95BA26587BE85DB0A353 + + fileRef + CE9C7160245B19131DAE6128 + isa + PBXBuildFile + + CE9C7160245B19131DAE6128 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvColorImage.cpp + path + ../../../addons/ofxOpenCv/src/ofxCvColorImage.cpp + sourceTree + SOURCE_ROOT + + C756CAAFD542831674E15FE6 + + children + + 603F2267D449084A4187A049 + CE9C7160245B19131DAE6128 + D5BB6F0357B6422E1B1656B4 + 8E79CF8911DFABAFE23EA45B + C76DE5C29BDBD2CAA1DD0021 + C1C56D20A1A57DC44096BFE7 + 7B6A03390302D5A2C9F0E4AB + F7269F96AC34A2B44A680D03 + 057122A817D12571F8C0C7A4 + 9A048549F08C6DFFA79E6DEF + 9A16CBF2E8CFE43AF54FE6F5 + 516717F84C0146512C47A3EC + C6151136D101F857DAE12722 + D847EBE484F4F500F9CF2549 + 8A4DD23693DFAB8EC05FAA5D + DEA2EDC0AFD59176FDEDC222 + CE81A5E39EB3C871FDF3D4D5 + + isa + PBXGroup + name + src + sourceTree + <group> + + A0B90D3B0ADB9C1716816714 + + children + + C756CAAFD542831674E15FE6 + DCC60D6724B56635AE867535 + + isa + PBXGroup + name + ofxOpenCv + sourceTree + <group> + + 603F2267D449084A4187A049 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxCvBlob.h + path + ../../../addons/ofxOpenCv/src/ofxCvBlob.h + sourceTree + SOURCE_ROOT + + 2C171637C399A50881F147E9 + + children + + 8B25248CC7F2228B1CEF2EB1 + + isa + PBXGroup + name + libusb-1.0 + sourceTree + <group> + + 1AE6862ED862CA18468E0CCD + + children + + 2C171637C399A50881F147E9 + + isa + PBXGroup + name + include + sourceTree + <group> + + 65726280742CD54BF368BDB8 + + children + + 1AE6862ED862CA18468E0CCD + + isa + PBXGroup + name + libusb-1.0 + sourceTree + <group> + + 8B25248CC7F2228B1CEF2EB1 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libusb.h + path + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0/libusb.h + sourceTree + SOURCE_ROOT + + B4A0A006318C06E07DDF19D6 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + usb_libusb10.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/usb_libusb10.h + sourceTree + SOURCE_ROOT + + 255A7B680DC81E543C875794 + + fileRef + 28F9707464BA3FF98E05096C + isa + PBXBuildFile + + 28F9707464BA3FF98E05096C + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + usb_libusb10.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/usb_libusb10.c + sourceTree + SOURCE_ROOT + + 49BEEB2DFA5319D55AA6899F + + fileRef + BF2F2AA872288D30F53983EF + isa + PBXBuildFile + + BF2F2AA872288D30F53983EF + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + tilt.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/tilt.c + sourceTree + SOURCE_ROOT + + 3CABCA8EA52D11C95F7A1309 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + registration.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/registration.h + sourceTree + SOURCE_ROOT + + D31F5C1B140C59B2AF1533A8 + + fileRef + 71958293AC5292DE4B7C619D + isa + PBXBuildFile + + 71958293AC5292DE4B7C619D + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + registration.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/registration.c + sourceTree + SOURCE_ROOT + + 093C9EBFCAB5D2649ACF4D0C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + loader.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/loader.h + sourceTree + SOURCE_ROOT + + FCC16AB16073FF0581F50ED7 + + fileRef + FE25F20F363BC625B852BFBC + isa + PBXBuildFile + + FE25F20F363BC625B852BFBC + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + loader.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/loader.c + sourceTree + SOURCE_ROOT + + 3175B69741F3AE805AD3F527 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + keep_alive.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/keep_alive.h + sourceTree + SOURCE_ROOT + + 21A059755481CC0BF969FD2D + + fileRef + A3528DDFF05B00283552455D + isa + PBXBuildFile + + A3528DDFF05B00283552455D + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + keep_alive.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/keep_alive.c + sourceTree + SOURCE_ROOT + + 83C70000C4AE60283CC77EB9 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + freenect_internal.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/freenect_internal.h + sourceTree + SOURCE_ROOT + + D097EE679E29AD7B5E2CDFCD + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + flags.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/flags.h + sourceTree + SOURCE_ROOT + + E55DEEF784A10419E444669E + + fileRef + 682082DEC78C75C8FB18B7DB + isa + PBXBuildFile + + 682082DEC78C75C8FB18B7DB + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + flags.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/flags.c + sourceTree + SOURCE_ROOT + + F4135EEFC911E9ED211FB6F9 + + fileRef + CF528C0E8DBFF5C31E8D6529 + isa + PBXBuildFile + + CF528C0E8DBFF5C31E8D6529 + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + core.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/core.c + sourceTree + SOURCE_ROOT + + 241AAF7769D555E4ECD57E17 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + cameras.h + path + ../../../addons/ofxKinect/libs/libfreenect/src/cameras.h + sourceTree + SOURCE_ROOT + + ACE7DC9A3223ED5EE1B80074 + + fileRef + 3DBD37876A11E46E4D7069B3 + isa + PBXBuildFile + + 3DBD37876A11E46E4D7069B3 + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + cameras.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/cameras.c + sourceTree + SOURCE_ROOT + + ED6E9BDB447DB965EE6F1FA6 + + children + + 34FC4C582EA5ED68F36013CD + 3DBD37876A11E46E4D7069B3 + 241AAF7769D555E4ECD57E17 + CF528C0E8DBFF5C31E8D6529 + 682082DEC78C75C8FB18B7DB + D097EE679E29AD7B5E2CDFCD + 83C70000C4AE60283CC77EB9 + A3528DDFF05B00283552455D + 3175B69741F3AE805AD3F527 + FE25F20F363BC625B852BFBC + 093C9EBFCAB5D2649ACF4D0C + 71958293AC5292DE4B7C619D + 3CABCA8EA52D11C95F7A1309 + BF2F2AA872288D30F53983EF + 28F9707464BA3FF98E05096C + B4A0A006318C06E07DDF19D6 + + isa + PBXGroup + name + src + sourceTree + <group> + + 0F8F016776681D468C0D0949 + + fileRef + 34FC4C582EA5ED68F36013CD + isa + PBXBuildFile + + 34FC4C582EA5ED68F36013CD + + explicitFileType + sourcecode.c.c + fileEncoding + 30 + isa + PBXFileReference + name + audio.c + path + ../../../addons/ofxKinect/libs/libfreenect/src/audio.c + sourceTree + SOURCE_ROOT + + E5F13FDAE691A5804F4D2DDB + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect.h + sourceTree + SOURCE_ROOT + + BCF95CE25C02631B7BF14CB3 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect-registration.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect-registration.h + sourceTree + SOURCE_ROOT + + 6DFA2B327764FCDA2A8D882F + + children + + 44A9633110288F985368AD7D + BCF95CE25C02631B7BF14CB3 + E5F13FDAE691A5804F4D2DDB + + isa + PBXGroup + name + include + sourceTree + <group> + + 32687044708CDA9EDA265387 + + children + + 6DFA2B327764FCDA2A8D882F + ED6E9BDB447DB965EE6F1FA6 + + isa + PBXGroup + name + libfreenect + sourceTree + <group> + + F4101FC676C210E28DCB3220 + + children + + 32687044708CDA9EDA265387 + 65726280742CD54BF368BDB8 + + isa + PBXGroup + name + libs + sourceTree + <group> + + 44A9633110288F985368AD7D + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + libfreenect-audio.h + path + ../../../addons/ofxKinect/libs/libfreenect/include/libfreenect-audio.h + sourceTree + SOURCE_ROOT + + 44EF97BDD915E758777A9A8C + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinect.h + path + ../../../addons/ofxKinect/src/ofxKinect.h + sourceTree + SOURCE_ROOT + + 686B0DF6249B52E1A85B39EC + + fileRef + 7ED9FFC7D08DA194C2CE7D09 + isa + PBXBuildFile + + 7ED9FFC7D08DA194C2CE7D09 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinect.cpp + path + ../../../addons/ofxKinect/src/ofxKinect.cpp + sourceTree + SOURCE_ROOT + + B8A2CBF3E24E6E5026B13A90 + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxBase3DVideo.h + path + ../../../addons/ofxKinect/src/ofxBase3DVideo.h + sourceTree + SOURCE_ROOT + + 03A9E977F3814A55A4FA3B4E + + explicitFileType + sourcecode.c.h + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectExtras.h + path + ../../../addons/ofxKinect/src/extra/ofxKinectExtras.h + sourceTree + SOURCE_ROOT + + 6E7134DE536888BE82D56327 + + children + + 01438542609FC64F1EC60EEB + 03A9E977F3814A55A4FA3B4E + + isa + PBXGroup + name + extra + sourceTree + <group> + + F3D2DB7201EFA9F7958F421E + + children + + 6E7134DE536888BE82D56327 + B8A2CBF3E24E6E5026B13A90 + 7ED9FFC7D08DA194C2CE7D09 + 44EF97BDD915E758777A9A8C + + isa + PBXGroup + name + src + sourceTree + <group> + + 9683228C705CA3FF4F2EA945 + + children + + F3D2DB7201EFA9F7958F421E + F4101FC676C210E28DCB3220 + + isa + PBXGroup + name + ofxKinect + sourceTree + <group> + + 7ADB04AF67C568EAFAEBA546 + + fileRef + 01438542609FC64F1EC60EEB + isa + PBXBuildFile + + 01438542609FC64F1EC60EEB + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofxKinectExtras.cpp + path + ../../../addons/ofxKinect/src/extra/ofxKinectExtras.cpp + sourceTree + SOURCE_ROOT + + BB4B014C10F69532006C3DED + + children + + 9683228C705CA3FF4F2EA945 + A0B90D3B0ADB9C1716816714 + 1F4FB5C423662B96ADFDCC0B + 6025FAF6414C2CA589764D26 + FD702F29E90B58DEC499A265 + EDD1D727C7914867117F6F92 + A492CE86424AB8905550BFD8 + + isa + PBXGroup + name + addons + sourceTree + <group> + + BBAB23BE13894E4700AA2426 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + GLUT.framework + path + ../../../libs/glut/lib/osx/GLUT.framework + sourceTree + <group> + + BBAB23C913894ECA00AA2426 + + children + + E7F985F515E0DE99003869B5 + E4C2424410CC5A17004149E2 + E4C2424510CC5A17004149E2 + E4C2424610CC5A17004149E2 + E45BE9710E8CC7DD009D7055 + E45BE9720E8CC7DD009D7055 + E45BE9730E8CC7DD009D7055 + E45BE9750E8CC7DD009D7055 + E45BE9760E8CC7DD009D7055 + E45BE9770E8CC7DD009D7055 + E45BE9790E8CC7DD009D7055 + E45BE97A0E8CC7DD009D7055 + E7E077E415D3B63C0020DFD4 + E7E077E715D3B6510020DFD4 + + isa + PBXGroup + name + system frameworks + sourceTree + <group> + + BBAB23CA13894EDB00AA2426 + + children + + BBAB23BE13894E4700AA2426 + + isa + PBXGroup + name + 3rd party frameworks + sourceTree + <group> + + BBAB23CB13894F3D00AA2426 + + fileRef + BBAB23BE13894E4700AA2426 + isa + PBXBuildFile + + E4328143138ABC890047C5CB + + isa + PBXFileReference + lastKnownFileType + wrapper.pb-project + name + openFrameworksLib.xcodeproj + path + ../../../libs/openFrameworksCompiled/project/osx/openFrameworksLib.xcodeproj + sourceTree + SOURCE_ROOT + + E4328144138ABC890047C5CB + + children + + E4328148138ABC890047C5CB + + isa + PBXGroup + name + Products + sourceTree + <group> + + E4328147138ABC890047C5CB + + containerPortal + E4328143138ABC890047C5CB + isa + PBXContainerItemProxy + proxyType + 2 + remoteGlobalIDString + E4B27C1510CBEB8E00536013 + remoteInfo + openFrameworks + + E4328148138ABC890047C5CB + + fileType + archive.ar + isa + PBXReferenceProxy + path + openFrameworksDebug.a + remoteRef + E4328147138ABC890047C5CB + sourceTree + BUILT_PRODUCTS_DIR + + E4328149138ABC9F0047C5CB + + fileRef + E4328148138ABC890047C5CB + isa + PBXBuildFile + + E45BE5980E8CC70C009D7055 + + children + + BBAB23CA13894EDB00AA2426 + BBAB23C913894ECA00AA2426 + + isa + PBXGroup + name + frameworks + sourceTree + <group> + + E45BE9710E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AGL.framework + path + /System/Library/Frameworks/AGL.framework + sourceTree + <absolute> + + E45BE9720E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + ApplicationServices.framework + path + /System/Library/Frameworks/ApplicationServices.framework + sourceTree + <absolute> + + E45BE9730E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AudioToolbox.framework + path + /System/Library/Frameworks/AudioToolbox.framework + sourceTree + <absolute> + + E45BE9750E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreAudio.framework + path + /System/Library/Frameworks/CoreAudio.framework + sourceTree + <absolute> + + E45BE9760E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreFoundation.framework + path + /System/Library/Frameworks/CoreFoundation.framework + sourceTree + <absolute> + + E45BE9770E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreServices.framework + path + /System/Library/Frameworks/CoreServices.framework + sourceTree + <absolute> + + E45BE9790E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + OpenGL.framework + path + /System/Library/Frameworks/OpenGL.framework + sourceTree + <absolute> + + E45BE97A0E8CC7DD009D7055 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + QuickTime.framework + path + /System/Library/Frameworks/QuickTime.framework + sourceTree + <absolute> + + E45BE97B0E8CC7DD009D7055 + + fileRef + E45BE9710E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97C0E8CC7DD009D7055 + + fileRef + E45BE9720E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97D0E8CC7DD009D7055 + + fileRef + E45BE9730E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE97F0E8CC7DD009D7055 + + fileRef + E45BE9750E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9800E8CC7DD009D7055 + + fileRef + E45BE9760E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9810E8CC7DD009D7055 + + fileRef + E45BE9770E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9830E8CC7DD009D7055 + + fileRef + E45BE9790E8CC7DD009D7055 + isa + PBXBuildFile + + E45BE9840E8CC7DD009D7055 + + fileRef + E45BE97A0E8CC7DD009D7055 + isa + PBXBuildFile + + E4B69B4A0A3A1720003C02F2 + + children + + E4B6FCAD0C3E899E008CF71C + E4EB6923138AFD0F00A09F29 + E4B69E1C0A3A1BDC003C02F2 + E4EEC9E9138DF44700A80321 + BB4B014C10F69532006C3DED + E45BE5980E8CC70C009D7055 + E4B69B5B0A3A1756003C02F2 + + isa + PBXGroup + sourceTree + <group> + + E4B69B4C0A3A1720003C02F2 + + attributes + + LastUpgradeCheck + 0460 + + buildConfigurationList + E4B69B4D0A3A1720003C02F2 + compatibilityVersion + Xcode 3.2 + developmentRegion + English + hasScannedForEncodings + 0 + isa + PBXProject + knownRegions + + English + Japanese + French + German + + mainGroup + E4B69B4A0A3A1720003C02F2 + productRefGroup + E4B69B4A0A3A1720003C02F2 + projectDirPath + + projectReferences + + + ProductGroup + E4328144138ABC890047C5CB + ProjectRef + E4328143138ABC890047C5CB + + + projectRoot + + targets + + E4B69B5A0A3A1756003C02F2 + + + E4B69B4D0A3A1720003C02F2 + + buildConfigurations + + E4B69B4E0A3A1720003C02F2 + E4B69B4F0A3A1720003C02F2 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + E4B69B4E0A3A1720003C02F2 + + baseConfigurationReference + E4EB6923138AFD0F00A09F29 + buildSettings + + OTHER_LDFLAGS + + $(OF_CORE_LIBS) + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx/usb-1.0.a + ../../../addons/ofxOpenCv/libs/opencv/lib/osx/opencv.a + + HEADER_SEARCH_PATHS + + $(OF_CORE_HEADERS) + ../../../addons/ofxKinect/libs + ../../../addons/ofxKinect/libs/libfreenect + ../../../addons/ofxKinect/libs/libfreenect/include + ../../../addons/ofxKinect/libs/libfreenect/platform + ../../../addons/ofxKinect/libs/libfreenect/src + ../../../addons/ofxKinect/libs/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/include + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/lib + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx + ../../../addons/ofxKinect/libs/libusb-win32 + ../../../addons/ofxKinect/src + ../../../addons/ofxKinect/src/extra + ../../../addons/ofxOpenCv/libs + ../../../addons/ofxOpenCv/libs/opencv + ../../../addons/ofxOpenCv/libs/opencv/include + ../../../addons/ofxOpenCv/libs/opencv/include/opencv + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2 + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video + ../../../addons/ofxOpenCv/libs/opencv/lib + ../../../addons/ofxOpenCv/libs/opencv/lib/osx + ../../../addons/ofxOpenCv/src + ../../../addons/ofxXmlSettings/libs + ../../../addons/ofxXmlSettings/src + ../../../addons/ofxCv/libs + ../../../addons/ofxCv/libs/CLD + ../../../addons/ofxCv/libs/CLD/include + ../../../addons/ofxCv/libs/CLD/include/CLD + ../../../addons/ofxCv/libs/CLD/src + ../../../addons/ofxCv/libs/ofxCv + ../../../addons/ofxCv/libs/ofxCv/include + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv + ../../../addons/ofxCv/libs/ofxCv/src + ../../../addons/ofxCv/src + ../../../addons/ofxKinectProjectorToolkit/libs + ../../../addons/ofxKinectProjectorToolkit/libs/dlib + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode + ../../../addons/ofxKinectProjectorToolkit/src + ../../../addons/ofxSecondWindow/libs + ../../../addons/ofxSecondWindow/src + ../../../addons/ofxUI/libs + ../../../addons/ofxUI/src + src + + ARCHS + $(NATIVE_ARCH) + CONFIGURATION_BUILD_DIR + $(SRCROOT)/bin/ + COPY_PHASE_STRIP + NO + DEAD_CODE_STRIPPING + YES + GCC_AUTO_VECTORIZATION + YES + GCC_ENABLE_SSE3_EXTENSIONS + YES + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS + YES + GCC_INLINES_ARE_PRIVATE_EXTERN + NO + GCC_OPTIMIZATION_LEVEL + 0 + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS + YES + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO + NO + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL + NO + GCC_WARN_UNINITIALIZED_AUTOS + NO + GCC_WARN_UNUSED_VALUE + NO + GCC_WARN_UNUSED_VARIABLE + NO + MACOSX_DEPLOYMENT_TARGET + 10.6 + OTHER_CPLUSPLUSFLAGS + + -D__MACOSX_CORE__ + -lpthread + -mtune=native + + SDKROOT + macosx + + isa + XCBuildConfiguration + name + Debug + + E4B69B4F0A3A1720003C02F2 + + baseConfigurationReference + E4EB6923138AFD0F00A09F29 + buildSettings + + OTHER_LDFLAGS + + $(OF_CORE_LIBS) + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx/usb-1.0.a + ../../../addons/ofxOpenCv/libs/opencv/lib/osx/opencv.a + + HEADER_SEARCH_PATHS + + $(OF_CORE_HEADERS) + ../../../addons/ofxKinect/libs + ../../../addons/ofxKinect/libs/libfreenect + ../../../addons/ofxKinect/libs/libfreenect/include + ../../../addons/ofxKinect/libs/libfreenect/platform + ../../../addons/ofxKinect/libs/libfreenect/src + ../../../addons/ofxKinect/libs/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/include + ../../../addons/ofxKinect/libs/libusb-1.0/include/libusb-1.0 + ../../../addons/ofxKinect/libs/libusb-1.0/lib + ../../../addons/ofxKinect/libs/libusb-1.0/lib/osx + ../../../addons/ofxKinect/libs/libusb-win32 + ../../../addons/ofxKinect/src + ../../../addons/ofxKinect/src/extra + ../../../addons/ofxOpenCv/libs + ../../../addons/ofxOpenCv/libs/opencv + ../../../addons/ofxOpenCv/libs/opencv/include + ../../../addons/ofxOpenCv/libs/opencv/include/opencv + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2 + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/calib3d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/contrib + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/core + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/features2d + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/flann + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/gpu + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/highgui + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/imgproc + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/legacy + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ml + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/objdetect + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/ts + ../../../addons/ofxOpenCv/libs/opencv/include/opencv2/video + ../../../addons/ofxOpenCv/libs/opencv/lib + ../../../addons/ofxOpenCv/libs/opencv/lib/osx + ../../../addons/ofxOpenCv/src + ../../../addons/ofxXmlSettings/libs + ../../../addons/ofxXmlSettings/src + ../../../addons/ofxCv/libs + ../../../addons/ofxCv/libs/CLD + ../../../addons/ofxCv/libs/CLD/include + ../../../addons/ofxCv/libs/CLD/include/CLD + ../../../addons/ofxCv/libs/CLD/src + ../../../addons/ofxCv/libs/ofxCv + ../../../addons/ofxCv/libs/ofxCv/include + ../../../addons/ofxCv/libs/ofxCv/include/ofxCv + ../../../addons/ofxCv/libs/ofxCv/src + ../../../addons/ofxCv/src + ../../../addons/ofxKinectProjectorToolkit/libs + ../../../addons/ofxKinectProjectorToolkit/libs/dlib + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/geometry + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/interfaces + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/matrix/lapack + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/memory_manager_stateless + ../../../addons/ofxKinectProjectorToolkit/libs/dlib/unicode + ../../../addons/ofxKinectProjectorToolkit/src + ../../../addons/ofxSecondWindow/libs + ../../../addons/ofxSecondWindow/src + ../../../addons/ofxUI/libs + ../../../addons/ofxUI/src + src + + ARCHS + $(NATIVE_ARCH) + CONFIGURATION_BUILD_DIR + $(SRCROOT)/bin/ + COPY_PHASE_STRIP + YES + DEAD_CODE_STRIPPING + YES + GCC_AUTO_VECTORIZATION + YES + GCC_ENABLE_SSE3_EXTENSIONS + YES + GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS + YES + GCC_INLINES_ARE_PRIVATE_EXTERN + NO + GCC_OPTIMIZATION_LEVEL + 3 + GCC_SYMBOLS_PRIVATE_EXTERN + NO + GCC_UNROLL_LOOPS + YES + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS + YES + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO + NO + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL + NO + GCC_WARN_UNINITIALIZED_AUTOS + NO + GCC_WARN_UNUSED_VALUE + NO + GCC_WARN_UNUSED_VARIABLE + NO + MACOSX_DEPLOYMENT_TARGET + 10.6 + OTHER_CPLUSPLUSFLAGS + + -D__MACOSX_CORE__ + -lpthread + -mtune=native + + SDKROOT + macosx + + isa + XCBuildConfiguration + name + Release + + E4B69B580A3A1756003C02F2 + + buildActionMask + 2147483647 + files + + E4B69E200A3A1BDC003C02F2 + E4B69E210A3A1BDC003C02F2 + 7ADB04AF67C568EAFAEBA546 + 686B0DF6249B52E1A85B39EC + 0F8F016776681D468C0D0949 + ACE7DC9A3223ED5EE1B80074 + F4135EEFC911E9ED211FB6F9 + E55DEEF784A10419E444669E + 21A059755481CC0BF969FD2D + FCC16AB16073FF0581F50ED7 + D31F5C1B140C59B2AF1533A8 + 49BEEB2DFA5319D55AA6899F + 255A7B680DC81E543C875794 + 250A95BA26587BE85DB0A353 + 1D5F3298C2FA073628012944 + 169D3C72FDE6C5590A1616F5 + FB09C6B2A1DA0EA217240CB8 + E212C821D1064B92DD953A42 + 63020F16C7E8DED980111241 + D3301F6A0B43BB293ED97C1D + 63B57AC5BF4EF088491E0317 + 933A2227713C720CEFF80FD9 + 9D44DC88EF9E7991B4A09951 + 5A4349E9754D6FA14C0F2A3A + B6840996567E78436F7ECFAB + F76B4A79BD8DE4854141CB47 + EBCDE831EFAE08274E799C97 + 6AABAB39E82AF5CFEA23A205 + 45CC483A999BF1065A6B926C + 5CC34D433F5806179935B89D + 2023EF517ED2D8B397511D4B + C602002DE761F9B52DB4400A + 7CDAD32BE4FA46701E3552C7 + 10B69DE456AED1288FC9316B + A6668C5B1272D7FCD5B5A16F + DBCB84A37F9AECC254870D79 + 12898A2212C6B1397854D45E + A81AF6FC4B1FD63D16781582 + 87B479F55285F413D96B5A45 + 9F5C6DD965B4F3A6DB5B88F8 + 4B3ED367CA852D522E2EE996 + F1E8DE8734BA6F69A5112FA8 + C381F2B7CFD84C0E540EB4BC + 7D393646FB859A930EF58917 + 7BE46522B64E24FAEDE1A25D + DF0C851B244C4C867CEA8806 + 9BE4AE0AA2B8C436BDFE9D4D + F392A99D83698FC099127880 + 084025DA517D8329301FE1B6 + 7252706DA14C1BE63950ADDA + 22030CBDCC25D815E7ED6757 + 3D4EA8E172D3E4A30FEFA969 + 7F2CD93F681F3C1547B3BF2C + FBD0CD0AFE3849C14E829CAF + 26874B150C8535AEA0F24C8C + FB8AA9FA6535767BE31806BC + 7C3DC84C9BFCBD2866DB2B6C + FFD1EBFCA24DFB4E4427B4FE + C30B3A2A37F8F32EE7318718 + 9A83D1B3FB64456BC907667F + F440B307990F8F5CE40B9111 + 222C3AB10FA3158602718602 + F9C20834354ACC8337320B8C + E3D59A6B55F05669B3FBF8BD + D60E54E7FD6E19BC8636E0D2 + 1587708E3CAC72997E43504E + 59C5F2F5D7254C33C00F97CB + FE0F1DB69ACCD163E9DA2A15 + 43BADBB2FE0F17D34B57A705 + 740A58CBFDFE578C83A349AF + ADE7C2AFC51E3F7E5E389026 + BFEFCE32DAFE10A8EB519F6C + 52AFF80A869790144ACCC9BA + 1DAAC3FB4B98B08AE63F4687 + 5AE95ADB5549701423B6DA48 + C961BE22AB9A8CCF037FC18F + F8D05F7C7F785CE323983B47 + 04C82720B149CE576B8CBB06 + E3A1109F67D711D6C256031E + 60012C723B05938A3D388335 + AE281BEBF3A00F1FC37F3DA0 + 82845E1F8C90E1F5A99D9868 + CE5D89B9893EAA12F511DCAC + + isa + PBXSourcesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4B69B590A3A1756003C02F2 + + buildActionMask + 2147483647 + files + + E7F985F815E0DEA3003869B5 + E7E077E815D3B6510020DFD4 + E4EB6799138ADC1D00A09F29 + E4328149138ABC9F0047C5CB + E45BE97B0E8CC7DD009D7055 + E45BE97C0E8CC7DD009D7055 + E45BE97D0E8CC7DD009D7055 + E45BE97F0E8CC7DD009D7055 + E45BE9800E8CC7DD009D7055 + E45BE9810E8CC7DD009D7055 + E45BE9830E8CC7DD009D7055 + E45BE9840E8CC7DD009D7055 + E4C2424710CC5A17004149E2 + E4C2424810CC5A17004149E2 + E4C2424910CC5A17004149E2 + E7E077E515D3B63C0020DFD4 + + isa + PBXFrameworksBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4B69B5A0A3A1756003C02F2 + + buildConfigurationList + E4B69B5F0A3A1757003C02F2 + buildPhases + + E4B69B580A3A1756003C02F2 + E4B69B590A3A1756003C02F2 + E4B6FFFD0C3F9AB9008CF71C + E4C2427710CC5ABF004149E2 + + buildRules + + dependencies + + E4EEB9AC138B136A00A80321 + + isa + PBXNativeTarget + name + example_bodyMapping + productName + myOFApp + productReference + E4B69B5B0A3A1756003C02F2 + productType + com.apple.product-type.application + + E4B69B5B0A3A1756003C02F2 + + explicitFileType + wrapper.application + includeInIndex + 0 + isa + PBXFileReference + path + example_bodyMappingDebug.app + sourceTree + BUILT_PRODUCTS_DIR + + E4B69B5F0A3A1757003C02F2 + + buildConfigurations + + E4B69B600A3A1757003C02F2 + E4B69B610A3A1757003C02F2 + + defaultConfigurationIsVisible + 0 + defaultConfigurationName + Release + isa + XCConfigurationList + + E4B69B600A3A1757003C02F2 + + buildSettings + + COMBINE_HIDPI_IMAGES + YES + COPY_PHASE_STRIP + NO + FRAMEWORK_SEARCH_PATHS + + $(inherited) + $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 + "$(SRCROOT)/../../../libs/glut/lib/osx" + GCC_DYNAMIC_NO_PIC + NO + GCC_GENERATE_DEBUGGING_SYMBOLS + YES + GCC_MODEL_TUNING + NONE + ICON + $(ICON_NAME_DEBUG) + ICON_FILE + $(ICON_FILE_PATH)$(ICON) + INFOPLIST_FILE + openFrameworks-Info.plist + INSTALL_PATH + $(HOME)/Applications + LIBRARY_SEARCH_PATHS + + $(inherited) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_52) + + PRODUCT_NAME + $(TARGET_NAME)Debug + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Debug + + E4B69B610A3A1757003C02F2 + + buildSettings + + COMBINE_HIDPI_IMAGES + YES + COPY_PHASE_STRIP + YES + FRAMEWORK_SEARCH_PATHS + + $(inherited) + $(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + + FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 + "$(SRCROOT)/../../../libs/glut/lib/osx" + GCC_GENERATE_DEBUGGING_SYMBOLS + YES + GCC_MODEL_TUNING + NONE + ICON + $(ICON_NAME_RELEASE) + ICON_FILE + $(ICON_FILE_PATH)$(ICON) + INFOPLIST_FILE + openFrameworks-Info.plist + INSTALL_PATH + $(HOME)/Applications + LIBRARY_SEARCH_PATHS + + $(inherited) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_5) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_6) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_14) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_15) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2) + $(LIBRARY_SEARCH_PATHS_QUOTED_1) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_7) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_8) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_9) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_10) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_11) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_12) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_13) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_16) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_17) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_18) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_19) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_20) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_21) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_22) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_23) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_24) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_25) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_26) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_27) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_28) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_29) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_30) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_31) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_32) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_33) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_34) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_35) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_36) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_37) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_38) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_39) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_40) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_41) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_42) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_43) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_44) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_45) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_46) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_47) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_48) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_49) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_50) + $(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_51) + + PRODUCT_NAME + $(TARGET_NAME) + WRAPPER_EXTENSION + app + + isa + XCBuildConfiguration + name + Release + + E4B69E1C0A3A1BDC003C02F2 + + children + + E4B69E1D0A3A1BDC003C02F2 + E4B69E1E0A3A1BDC003C02F2 + E4B69E1F0A3A1BDC003C02F2 + + isa + PBXGroup + path + src + sourceTree + SOURCE_ROOT + + E4B69E1D0A3A1BDC003C02F2 + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + sourcecode.cpp.cpp + name + main.cpp + path + src/main.cpp + sourceTree + SOURCE_ROOT + + E4B69E1E0A3A1BDC003C02F2 + + explicitFileType + sourcecode.cpp.cpp + fileEncoding + 30 + isa + PBXFileReference + name + ofApp.cpp + path + src/ofApp.cpp + sourceTree + SOURCE_ROOT + + E4B69E1F0A3A1BDC003C02F2 + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + sourcecode.c.h + name + ofApp.h + path + src/ofApp.h + sourceTree + SOURCE_ROOT + + E4B69E200A3A1BDC003C02F2 + + fileRef + E4B69E1D0A3A1BDC003C02F2 + isa + PBXBuildFile + + E4B69E210A3A1BDC003C02F2 + + fileRef + E4B69E1E0A3A1BDC003C02F2 + isa + PBXBuildFile + + E4B6FCAD0C3E899E008CF71C + + fileEncoding + 30 + isa + PBXFileReference + lastKnownFileType + text.plist.xml + path + openFrameworks-Info.plist + sourceTree + <group> + + E4B6FFFD0C3F9AB9008CF71C + + buildActionMask + 2147483647 + files + + inputPaths + + isa + PBXShellScriptBuildPhase + outputPaths + + runOnlyForDeploymentPostprocessing + 0 + shellPath + /bin/sh + shellScript + cp -f ../../../libs/fmodex/lib/osx/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/libfmodex.dylib"; install_name_tool -change ./libfmodex.dylib @executable_path/libfmodex.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"; +mkdir -p "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" +cp -f "$ICON_FILE" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources/" + + + E4C2424410CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + AppKit.framework + path + /System/Library/Frameworks/AppKit.framework + sourceTree + <absolute> + + E4C2424510CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Cocoa.framework + path + /System/Library/Frameworks/Cocoa.framework + sourceTree + <absolute> + + E4C2424610CC5A17004149E2 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + IOKit.framework + path + /System/Library/Frameworks/IOKit.framework + sourceTree + <absolute> + + E4C2424710CC5A17004149E2 + + fileRef + E4C2424410CC5A17004149E2 + isa + PBXBuildFile + + E4C2424810CC5A17004149E2 + + fileRef + E4C2424510CC5A17004149E2 + isa + PBXBuildFile + + E4C2424910CC5A17004149E2 + + fileRef + E4C2424610CC5A17004149E2 + isa + PBXBuildFile + + E4C2427710CC5ABF004149E2 + + buildActionMask + 2147483647 + dstPath + + dstSubfolderSpec + 10 + files + + BBAB23CB13894F3D00AA2426 + + isa + PBXCopyFilesBuildPhase + runOnlyForDeploymentPostprocessing + 0 + + E4EB6799138ADC1D00A09F29 + + fileRef + BBAB23BE13894E4700AA2426 + isa + PBXBuildFile + + E4EB691F138AFCF100A09F29 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + name + CoreOF.xcconfig + path + ../../../libs/openFrameworksCompiled/project/osx/CoreOF.xcconfig + sourceTree + SOURCE_ROOT + + E4EB6923138AFD0F00A09F29 + + fileEncoding + 4 + isa + PBXFileReference + lastKnownFileType + text.xcconfig + path + Project.xcconfig + sourceTree + <group> + + E4EEB9AB138B136A00A80321 + + containerPortal + E4328143138ABC890047C5CB + isa + PBXContainerItemProxy + proxyType + 1 + remoteGlobalIDString + E4B27C1410CBEB8E00536013 + remoteInfo + openFrameworks + + E4EEB9AC138B136A00A80321 + + isa + PBXTargetDependency + name + openFrameworks + targetProxy + E4EEB9AB138B136A00A80321 + + E4EEC9E9138DF44700A80321 + + children + + E4EB691F138AFCF100A09F29 + E4328143138ABC890047C5CB + + isa + PBXGroup + name + openFrameworks + sourceTree + <group> + + E7E077E415D3B63C0020DFD4 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + CoreVideo.framework + path + /System/Library/Frameworks/CoreVideo.framework + sourceTree + <absolute> + + E7E077E515D3B63C0020DFD4 + + fileRef + E7E077E415D3B63C0020DFD4 + isa + PBXBuildFile + + E7E077E715D3B6510020DFD4 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + QTKit.framework + path + /System/Library/Frameworks/QTKit.framework + sourceTree + <absolute> + + E7E077E815D3B6510020DFD4 + + fileRef + E7E077E715D3B6510020DFD4 + isa + PBXBuildFile + + E7F985F515E0DE99003869B5 + + isa + PBXFileReference + lastKnownFileType + wrapper.framework + name + Accelerate.framework + path + /System/Library/Frameworks/Accelerate.framework + sourceTree + <absolute> + + E7F985F815E0DEA3003869B5 + + fileRef + E7F985F515E0DE99003869B5 + isa + PBXBuildFile + + + rootObject + E4B69B4C0A3A1720003C02F2 + + diff --git a/example_bodyMapping/example_bodyMapping.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate b/example_bodyMapping/example_bodyMapping.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..7284940 Binary files /dev/null and b/example_bodyMapping/example_bodyMapping.xcodeproj/project.xcworkspace/xcuserdata/Gene.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Debug.xcscheme b/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Debug.xcscheme new file mode 100644 index 0000000..7637800 --- /dev/null +++ b/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Debug.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Release.xcscheme b/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Release.xcscheme new file mode 100644 index 0000000..ebbeb12 --- /dev/null +++ b/example_bodyMapping/example_bodyMapping.xcodeproj/xcshareddata/xcschemes/example_bodyMapping Release.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example_bodyMapping/example_bodyMapping.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist b/example_bodyMapping/example_bodyMapping.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..13dfb6e --- /dev/null +++ b/example_bodyMapping/example_bodyMapping.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SuppressBuildableAutocreation + + E4B69B5A0A3A1756003C02F2 + + primary + + + + + diff --git a/example_bodyMapping/openFrameworks-Info.plist b/example_bodyMapping/openFrameworks-Info.plist new file mode 100644 index 0000000..8d64d2b --- /dev/null +++ b/example_bodyMapping/openFrameworks-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + cc.openFrameworks.ofapp + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFBundleIconFile + ${ICON} + + diff --git a/example_bodyMapping/src/main.cpp b/example_bodyMapping/src/main.cpp new file mode 100644 index 0000000..0fb60a8 --- /dev/null +++ b/example_bodyMapping/src/main.cpp @@ -0,0 +1,13 @@ +#include "ofMain.h" +#include "ofApp.h" + +//======================================================================== +int main( ){ + ofSetupOpenGL(1280,960,OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp(new ofApp()); + +} diff --git a/example_bodyMapping/src/ofApp.cpp b/example_bodyMapping/src/ofApp.cpp new file mode 100644 index 0000000..640813f --- /dev/null +++ b/example_bodyMapping/src/ofApp.cpp @@ -0,0 +1,121 @@ +#include "ofApp.h" + + +void ofApp::setup() { + ofSetVerticalSync(true); + + blobColors[0] = ofColor(255, 0, 0); + blobColors[1] = ofColor(0, 255, 0); + blobColors[2] = ofColor(0, 0, 255); + blobColors[3] = ofColor(255, 255, 0); + blobColors[4] = ofColor(255, 0, 255); + blobColors[5] = ofColor(0, 127, 255); + blobColors[6] = ofColor(0, 255, 127); + blobColors[7] = ofColor(127, 0, 255); + blobColors[8] = ofColor(255, 0, 127); + blobColors[9] = ofColor(127, 255, 0); + blobColors[10]= ofColor(255, 127, 0); + + // set up kinect + kinect.setRegistration(true); + kinect.init(); + kinect.open(); + grayImage.allocate(kinect.width, kinect.height); + grayThreshNear.allocate(kinect.width, kinect.height); + grayThreshFar.allocate(kinect.width, kinect.height); + + kpt.loadCalibration("/Users/Gene/Desktop/calibration.xml"); + + secondWindow.setup("main", ofGetScreenWidth(), 0, PROJECTOR_RESOLUTION_X, PROJECTOR_RESOLUTION_Y, true); + + // setup gui + gui = new ofxUICanvas(); + gui->setHeight(800); + gui->setName("parameters"); + gui->addLabel("kinect"); + gui->addSpacer(); + gui->addSlider("nearThresh", 0, 255, &nearThreshold); + gui->addSlider("farThresh", 0, 255, &farThreshold); + gui->addLabel("contours"); + gui->addSpacer(); + gui->addSlider("minArea", 0, 5000, &minArea); + gui->addSlider("maxArea", 15000, 150000, &maxArea); + gui->addSlider("threshold", 1, 100, &threshold); + gui->addSlider("persistence", 1, 100, &persistence); + gui->addSlider("maxDistance", 1, 100, &maxDistance); +} + +void ofApp::update() { + kinect.update(); + + if(kinect.isFrameNew()) { + // process kinect depth image + grayImage.setFromPixels(kinect.getDepthPixels(), kinect.width, kinect.height); + grayThreshNear = grayImage; + grayThreshFar = grayImage; + grayThreshNear.threshold(nearThreshold, true); + grayThreshFar.threshold(farThreshold); + cvAnd(grayThreshNear.getCvImage(), grayThreshFar.getCvImage(), grayImage.getCvImage(), NULL); + grayImage.flagImageChanged(); + + // set contour tracker parameters + contourFinder.setMinArea(minArea); + contourFinder.setMaxArea(maxArea); + contourFinder.setThreshold(threshold); + contourFinder.getTracker().setPersistence(persistence); + contourFinder.getTracker().setMaximumDistance(maxDistance); + + // determine found contours + contourFinder.findContours(grayImage); + } +} + +void ofApp::draw() { + // GUI + ofBackground(0); + ofSetColor(255); + ofPushMatrix(); + kinect.draw(0, 0); + ofTranslate(640, 0); + grayImage.draw(0, 0); + ofTranslate(-640, 480); + contourFinder.draw(); + ofTranslate(640, 0); + ofPopMatrix(); + + + // MAIN WINDOW + secondWindow.begin(); + + ofBackground(0); + + RectTracker& tracker = contourFinder.getTracker(); + + for(int i = 0; i < contourFinder.size(); i++) { + // get contour, label, center point, and age of contour + vector points = contourFinder.getContour(i); + int label = contourFinder.getLabel(i); + ofPoint center = toOf(contourFinder.getCenter(i)); + int age = tracker.getAge(label); + + // map contour using calibration and draw to main window + ofBeginShape(); + ofFill(); + ofSetColor(blobColors[label % 11]); + for (int j=0; j + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Debug.xcscheme b/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Debug.xcscheme new file mode 100644 index 0000000..1916aef --- /dev/null +++ b/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Debug.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Release.xcscheme b/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Release.xcscheme new file mode 100644 index 0000000..fe14f27 --- /dev/null +++ b/exmple_segmentation/example_segmentation.xcodeproj/xcshareddata/xcschemes/kinect_segmentation Release.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/exmple_segmentation/example_segmentation.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist b/exmple_segmentation/example_segmentation.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..13dfb6e --- /dev/null +++ b/exmple_segmentation/example_segmentation.xcodeproj/xcuserdata/Gene.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SuppressBuildableAutocreation + + E4B69B5A0A3A1756003C02F2 + + primary + + + + + diff --git a/exmple_segmentation/openFrameworks-Info.plist b/exmple_segmentation/openFrameworks-Info.plist new file mode 100644 index 0000000..8d64d2b --- /dev/null +++ b/exmple_segmentation/openFrameworks-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + cc.openFrameworks.ofapp + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFBundleIconFile + ${ICON} + + diff --git a/exmple_segmentation/src/main.cpp b/exmple_segmentation/src/main.cpp new file mode 100644 index 0000000..6cb29c1 --- /dev/null +++ b/exmple_segmentation/src/main.cpp @@ -0,0 +1,13 @@ +#include "ofMain.h" +#include "ofApp.h" + +//======================================================================== +int main( ){ + ofSetupOpenGL(1280, 960, OF_WINDOW); // <-------- setup the GL context + + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp(new ofApp()); + +} diff --git a/exmple_segmentation/src/ofApp.cpp b/exmple_segmentation/src/ofApp.cpp new file mode 100644 index 0000000..9a9d406 --- /dev/null +++ b/exmple_segmentation/src/ofApp.cpp @@ -0,0 +1,207 @@ +#include "ofApp.h" + +using namespace ofxCv; +using namespace cv; + + +//-------------------------------------------------------------- +void ofApp::setup() { + blobColors[0] = ofColor(255, 0, 0); + blobColors[1] = ofColor(0, 255, 0); + blobColors[2] = ofColor(0, 0, 255); + blobColors[3] = ofColor(255, 255, 0); + blobColors[4] = ofColor(255, 0, 255); + blobColors[5] = ofColor(0, 127, 255); + blobColors[6] = ofColor(0, 255, 127); + blobColors[7] = ofColor(127, 0, 255); + blobColors[8] = ofColor(255, 0, 127); + blobColors[9] = ofColor(127, 255, 0); + blobColors[10]= ofColor(255, 127, 0); + + kinect.setRegistration(true); + kinect.init(); + kinect.open(); + + kpt.loadCalibration("/Users/Gene/Desktop/calibration.xml"); + + secondWindow.setup("main", ofGetScreenWidth(), 0, PROJECTOR_RESOLUTION_X, PROJECTOR_RESOLUTION_Y, true); + + colorImg.allocate(kinect.width, kinect.height); + grayImage.allocate(kinect.width, kinect.height); + + fbo.allocate(kinect.width, kinect.height, GL_RGB); + fbo1.allocate(kinect.width, kinect.height, GL_RGBA); + img.allocate(kinect.width, kinect.height, OF_IMAGE_COLOR_ALPHA); + + shader.load("standard.vert", "edges.frag"); + + // setup gui + gui = new ofxUICanvas(); + gui->setHeight(800); + gui->setName("parameters"); + gui->addLabel("kinect"); + gui->addSpacer(); + gui->addSlider("fade", 0, 255, &fade); + gui->addSlider("minArea", 0, 5000, &minArea); + gui->addSlider("maxArea", 5000, 320000, &maxArea); + gui->addSlider("threshold", 1, 100, &threshold); + gui->addSlider("persistence", 1, 100, &persistence); + gui->addSlider("maxDistance", 1, 100, &maxDistance); + gui->addSlider("numDilate", 0, 8, &numDilate); + gui->addSlider("numErode", 0, 8, &numErode); +} + +//-------------------------------------------------------------- +void ofApp::update() { + + kinect.update(); + + if(kinect.isFrameNew()) { + + // pre-processing depth image + fbo1.begin(); + ofEnableAlphaBlending(); + ofSetColor(255, fade); + kinect.drawDepth(0, 0); + ofDisableAlphaBlending(); + fbo1.end(); + + fbo.begin(); + shader.begin(); + fbo1.draw(0, 0); + shader.end(); + fbo.end(); + + fbo.readToPixels(pixels); + img.setFromPixels(pixels); + img.update(); + + colorImg.setFromPixels(img.getPixelsRef()); + grayImage.setFromColorImage(colorImg); + + // alternative: Canny method + /* + convertColor(kinect, gray, CV_RGB2GRAY); + Canny(gray, edge, mouseX, mouseY, 3); + edge.update(); + colorImg.setFromPixels(edge.getPixelsRef()); + grayImage.setFromColorImage(colorImg); + */ + + // post-processing + for (int i=0; i points = contourFinder.getContour(i); + int label = contourFinder.getLabel(i); + ofPoint center = toOf(contourFinder.getCenter(i)); + int age = tracker.getAge(label); + vector fitPoints = contourFinder.getFitQuad(i); + cv::RotatedRect fitQuad = contourFinder.getFitEllipse(i); + + // draw contours + ofFill(); + ofSetColor(blobColors[label % 11]); + ofBeginShape(); + for (int j=0; j points = contourFinder.getContour(i); + int label = contourFinder.getLabel(i); + ofPoint center = toOf(contourFinder.getCenter(i)); + int age = tracker.getAge(label); + + // map contour using calibration and draw to main window + ofBeginShape(); + ofFill(); + ofSetColor(blobColors[label % 11]); + for (int j=0; j // for the exceptions + +#ifdef __CYGWIN__ +namespace std +{ + typedef std::basic_string wstring; +} +#endif + +#include "platform.h" +#include "windows_magic.h" + + +#include // for std::swap +#include // for std::bad_alloc +#include +#include "assert.h" +#include "error.h" +#include "noncopyable.h" +#include "enable_if.h" +#include "uintn.h" +#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" // for the default memory manager + + + +// ---------------------------------------------------------------------------------------- +/*!A _dT !*/ + +template +inline charT _dTcast (const char a, const wchar_t b); +template <> +inline char _dTcast (const char a, const wchar_t ) { return a; } +template <> +inline wchar_t _dTcast (const char , const wchar_t b) { return b; } + +template +inline const charT* _dTcast ( const char* a, const wchar_t* b); +template <> +inline const char* _dTcast ( const char* a, const wchar_t* ) { return a; } +template <> +inline const wchar_t* _dTcast ( const char* , const wchar_t* b) { return b; } + + +#define _dT(charT,str) _dTcast(str,L##str) +/*! + requires + - charT == char or wchar_t + - str == a string or character literal + ensures + - returns the literal in the form of a charT type literal. +!*/ + +// ---------------------------------------------------------------------------------------- + + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*!A default_memory_manager + + This memory manager just calls new and delete directly. + + !*/ + typedef memory_manager_stateless_kernel_1 default_memory_manager; + +// ---------------------------------------------------------------------------------------- + + /*!A swap !*/ + // make swap available in the dlib namespace + using std::swap; + +// ---------------------------------------------------------------------------------------- + + /*! + Here is where I define my return codes. It is + important that they all be < 0. + !*/ + + enum general_return_codes + { + TIMEOUT = -1, + WOULDBLOCK = -2, + OTHER_ERROR = -3, + SHUTDOWN = -4, + PORTINUSE = -5 + }; + +// ---------------------------------------------------------------------------------------- + + inline unsigned long square_root ( + unsigned long value + ) + /*! + requires + - value <= 2^32 - 1 + ensures + - returns the square root of value. if the square root is not an + integer then it will be rounded up to the nearest integer. + !*/ + { + unsigned long x; + + // set the initial guess for what the root is depending on + // how big value is + if (value < 3) + return value; + else if (value < 4096) // 12 + x = 45; + else if (value < 65536) // 16 + x = 179; + else if (value < 1048576) // 20 + x = 717; + else if (value < 16777216) // 24 + x = 2867; + else if (value < 268435456) // 28 + x = 11469; + else // 32 + x = 45875; + + + + // find the root + x = (x + value/x)>>1; + x = (x + value/x)>>1; + x = (x + value/x)>>1; + x = (x + value/x)>>1; + + + + if (x*x < value) + return x+1; + else + return x; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void median ( + T& one, + T& two, + T& three + ); + /*! + requires + - T implements operator< + - T is swappable by a global swap() + ensures + - #one is the median + - #one, #two, and #three is some permutation of one, two, and three. + !*/ + + + template < + typename T + > + void median ( + T& one, + T& two, + T& three + ) + { + using std::swap; + using dlib::swap; + + if ( one < two ) + { + // one < two + if ( two < three ) + { + // one < two < three : two + swap(one,two); + + } + else + { + // one < two >= three + if ( one < three) + { + // three + swap(three,one); + } + } + + } + else + { + // one >= two + if ( three < one ) + { + // three <= one >= two + if ( three < two ) + { + // two + swap(two,one); + } + else + { + // three + swap(three,one); + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + namespace relational_operators + { + template < + typename A, + typename B + > + bool operator> ( + const A& a, + const B& b + ) { return b < a; } + + // --------------------------------- + + template < + typename A, + typename B + > + bool operator!= ( + const A& a, + const B& b + ) { return !(a == b); } + + // --------------------------------- + + template < + typename A, + typename B + > + bool operator<= ( + const A& a, + const B& b + ) { return !(b < a); } + + // --------------------------------- + + template < + typename A, + typename B + > + bool operator>= ( + const A& a, + const B& b + ) { return !(a < b); } + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void exchange ( + T& a, + T& b + ) + /*! + This function does the exact same thing that global swap does and it does it by + just calling swap. But a lot of compilers have problems doing a Koenig Lookup + and the fact that this has a different name (global swap has the same name as + the member functions called swap) makes them compile right. + + So this is a workaround but not too ugly of one. But hopefully I get get + rid of this in a few years. So this function is alredy deprecated. + + This also means you should NOT use this function in your own code unless + you have to support an old buggy compiler that benefits from this hack. + !*/ + { + using std::swap; + using dlib::swap; + swap(a,b); + } + +// ---------------------------------------------------------------------------------------- + + /*!A is_pointer_type + + This is a template where is_pointer_type::value == true when T is a pointer + type and false otherwise. + !*/ + + template < + typename T + > + class is_pointer_type + { + public: + enum { value = false }; + private: + is_pointer_type(); + }; + + template < + typename T + > + class is_pointer_type + { + public: + enum { value = true }; + private: + is_pointer_type(); + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_const_type + + This is a template where is_const_type::value == true when T is a const + type and false otherwise. + !*/ + + template + struct is_const_type + { + static const bool value = false; + }; + template + struct is_const_type + { + static const bool value = true; + }; + template + struct is_const_type + { + static const bool value = true; + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_reference_type + + This is a template where is_reference_type::value == true when T is a reference + type and false otherwise. + !*/ + + template + struct is_reference_type + { + static const bool value = false; + }; + + template struct is_reference_type { static const bool value = true; }; + template struct is_reference_type { static const bool value = true; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_same_type + + This is a template where is_same_type::value == true when T and U are the + same type and false otherwise. + !*/ + + template < + typename T, + typename U + > + class is_same_type + { + public: + enum {value = false}; + private: + is_same_type(); + }; + + template + class is_same_type + { + public: + enum {value = true}; + private: + is_same_type(); + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_float_type + + This is a template that can be used to determine if a type is one of the built + int floating point types (i.e. float, double, or long double). + !*/ + + template < typename T > struct is_float_type { const static bool value = false; }; + template <> struct is_float_type { const static bool value = true; }; + template <> struct is_float_type { const static bool value = true; }; + template <> struct is_float_type { const static bool value = true; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_convertible + + This is a template that can be used to determine if one type is convertible + into another type. + + For example: + is_convertible::value == true // because ints are convertible to floats + is_convertible::value == false // because int pointers are NOT convertible to floats + !*/ + + template + struct is_convertible + { + struct yes_type { char a; }; + struct no_type { yes_type a[2]; }; + static const from& from_helper(); + static yes_type test(to); + static no_type test(...); + const static bool value = sizeof(test(from_helper())) == sizeof(yes_type); + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_same_object + + This is a templated function which checks if both of its arguments are actually + references to the same object. It returns true if they are and false otherwise. + + !*/ + + // handle the case where T and U are unrelated types. + template < typename T, typename U > + typename disable_if_c::value || is_convertible::value, bool>::type + is_same_object ( + const T& a, + const U& b + ) + { + return ((void*)&a == (void*)&b); + } + + // handle the case where T and U are related types because their pointers can be + // implicitly converted into one or the other. E.g. a derived class and its base class. + // Or where both T and U are just the same type. This way we make sure that if there is a + // valid way to convert between these two pointer types then we will take that route rather + // than the void* approach used otherwise. + template < typename T, typename U > + typename enable_if_c::value || is_convertible::value, bool>::type + is_same_object ( + const T& a, + const U& b + ) + { + return (&a == &b); + } + +// ---------------------------------------------------------------------------------------- + + /*!A is_unsigned_type + + This is a template where is_unsigned_type::value == true when T is an unsigned + integral type and false when T is a signed integral type. + !*/ + template < + typename T + > + struct is_unsigned_type + { + static const bool value = static_cast((static_cast(0)-static_cast(1))) > 0; + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_signed_type + + This is a template where is_signed_type::value == true when T is a signed + integral type and false when T is an unsigned integral type. + !*/ + template < + typename T + > + struct is_signed_type + { + static const bool value = !is_unsigned_type::value; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class copy_functor + { + public: + void operator() ( + const T& source, + T& destination + ) const + { + destination = source; + } + }; + +// ---------------------------------------------------------------------------------------- + + /*!A static_switch + + To use this template you give it some number of boolean expressions and it + tells you which one of them is true. If more than one of them is true then + it causes a compile time error. + + for example: + static_switch<1 + 1 == 2, 4 - 1 == 4>::value == 1 // because the first expression is true + static_switch<1 + 1 == 3, 4 == 4>::value == 2 // because the second expression is true + static_switch<1 + 1 == 3, 4 == 5>::value == 0 // 0 here because none of them are true + static_switch<1 + 1 == 2, 4 == 4>::value == compiler error // because more than one expression is true + !*/ + + template < bool v1 = 0, bool v2 = 0, bool v3 = 0, bool v4 = 0, bool v5 = 0, + bool v6 = 0, bool v7 = 0, bool v8 = 0, bool v9 = 0, bool v10 = 0, + bool v11 = 0, bool v12 = 0, bool v13 = 0, bool v14 = 0, bool v15 = 0 > + struct static_switch; + + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 0; }; + template <> struct static_switch<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 1; }; + template <> struct static_switch<0,1,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 2; }; + template <> struct static_switch<0,0,1,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 3; }; + template <> struct static_switch<0,0,0,1,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 4; }; + template <> struct static_switch<0,0,0,0,1,0,0,0,0,0,0,0,0,0,0> { const static int value = 5; }; + template <> struct static_switch<0,0,0,0,0,1,0,0,0,0,0,0,0,0,0> { const static int value = 6; }; + template <> struct static_switch<0,0,0,0,0,0,1,0,0,0,0,0,0,0,0> { const static int value = 7; }; + template <> struct static_switch<0,0,0,0,0,0,0,1,0,0,0,0,0,0,0> { const static int value = 8; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,1,0,0,0,0,0,0> { const static int value = 9; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,1,0,0,0,0,0> { const static int value = 10; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,1,0,0,0,0> { const static int value = 11; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,1,0,0,0> { const static int value = 12; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,1,0,0> { const static int value = 13; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,1,0> { const static int value = 14; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1> { const static int value = 15; }; + +// ---------------------------------------------------------------------------------------- + /*!A is_built_in_scalar_type + + This is a template that allows you to determine if the given type is a built + in scalar type such as an int, char, float, short, etc. + + For example, is_built_in_scalar_type::value == true + For example, is_built_in_scalar_type::value == false + !*/ + + template struct is_built_in_scalar_type { const static bool value = false; }; + + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + // Don't define one for wchar_t when using a version of visual studio + // older than 8.0 (visual studio 2005) since before then they improperly set + // wchar_t to be a typedef rather than its own type as required by the C++ + // standard. +#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED + template <> struct is_built_in_scalar_type { const static bool value = true; }; +#endif + +// ---------------------------------------------------------------------------------------- + + /*!A promote + + This is a template that takes one of the built in scalar types and gives you another + scalar type that should be big enough to hold sums of values from the original scalar + type. The new scalar type will also always be signed. + + For example, promote::type == int32 + !*/ + + template struct promote; + template struct promote { typedef int32 type; }; + template struct promote { typedef int32 type; }; + template struct promote { typedef int64 type; }; + template struct promote { typedef int64 type; }; + + template <> struct promote { typedef double type; }; + template <> struct promote { typedef double type; }; + template <> struct promote { typedef long double type; }; + +// ---------------------------------------------------------------------------------------- + + /*!A assign_zero_if_built_in_scalar_type + + This function assigns its argument the value of 0 if it is a built in scalar + type according to the is_built_in_scalar_type<> template. If it isn't a + built in scalar type then it does nothing. + !*/ + + template inline typename disable_if,void>::type assign_zero_if_built_in_scalar_type (T&){} + template inline typename enable_if,void>::type assign_zero_if_built_in_scalar_type (T& a){a=0;} + +// ---------------------------------------------------------------------------------------- + + /*!A basic_type + + This is a template that takes a type and strips off any const, volatile, or reference + qualifiers and gives you back the basic underlying type. So for example: + + basic_type::type == int + !*/ + + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + +// ---------------------------------------------------------------------------------------- + + template + T put_in_range ( + const T& a, + const T& b, + const T& val + ) + /*! + requires + - T is a type that looks like double, float, int, or so forth + ensures + - if (val is within the range [a,b]) then + - returns val + - else + - returns the end of the range [a,b] that is closest to val + !*/ + { + if (a < b) + { + if (val < a) + return a; + else if (val > b) + return b; + } + else + { + if (val < b) + return b; + else if (val > a) + return a; + } + + return val; + } + + // overload for double + inline double put_in_range(const double& a, const double& b, const double& val) + { return put_in_range(a,b,val); } + +// ---------------------------------------------------------------------------------------- + + /*!A tabs + + This is a template to compute the absolute value a number at compile time. + + For example, + abs<-4>::value == 4 + abs<4>::value == 4 + !*/ + + template + struct tabs { const static long value = x; }; + template + struct tabs::type> { const static long value = -x; }; + +// ---------------------------------------------------------------------------------------- + + /*!A tmax + + This is a template to compute the max of two values at compile time + + For example, + abs<4,7>::value == 7 + !*/ + + template + struct tmax { const static long value = x; }; + template + struct tmax x)>::type> { const static long value = y; }; + +// ---------------------------------------------------------------------------------------- + + /*!A tmin + + This is a template to compute the min of two values at compile time + + For example, + abs<4,7>::value == 4 + !*/ + + template + struct tmin { const static long value = x; }; + template + struct tmin::type> { const static long value = y; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_function + + This is a template that allows you to determine if the given type is a function. + + For example, + void funct(); + + is_built_in_scalar_type::value == true + is_built_in_scalar_type::value == false + !*/ + + template struct is_function { static const bool value = false; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + + + template class funct_wrap0 + { + public: + funct_wrap0(T (&f_)()):f(f_){} + T operator()() const { return f(); } + private: + T (&f)(); + }; + template class funct_wrap1 + { + public: + funct_wrap1(T (&f_)(A0)):f(f_){} + T operator()(A0 a0) const { return f(a0); } + private: + T (&f)(A0); + }; + template class funct_wrap2 + { + public: + funct_wrap2(T (&f_)(A0,A1)):f(f_){} + T operator()(A0 a0, A1 a1) const { return f(a0,a1); } + private: + T (&f)(A0,A1); + }; + template class funct_wrap3 + { + public: + funct_wrap3(T (&f_)(A0,A1,A2)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2) const { return f(a0,a1,a2); } + private: + T (&f)(A0,A1,A2); + }; + template class funct_wrap4 + { + public: + funct_wrap4(T (&f_)(A0,A1,A2,A3)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return f(a0,a1,a2,a3); } + private: + T (&f)(A0,A1,A2,A3); + }; + template class funct_wrap5 + { + public: + funct_wrap5(T (&f_)(A0,A1,A2,A3,A4)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return f(a0,a1,a2,a3,a4); } + private: + T (&f)(A0,A1,A2,A3,A4); + }; + + /*!A wrap_function + + This is a template that allows you to turn a global function into a + function object. The reason for this template's existance is so you can + do stuff like this: + + template + void call_funct(const T& funct) + { cout << funct(); } + + std::string test() { return "asdfasf"; } + + int main() + { + call_funct(wrap_function(test)); + } + + The above code doesn't work right on some compilers if you don't + use wrap_function. + !*/ + + template + funct_wrap0 wrap_function(T (&f)()) { return funct_wrap0(f); } + template + funct_wrap1 wrap_function(T (&f)(A0)) { return funct_wrap1(f); } + template + funct_wrap2 wrap_function(T (&f)(A0, A1)) { return funct_wrap2(f); } + template + funct_wrap3 wrap_function(T (&f)(A0, A1, A2)) { return funct_wrap3(f); } + template + funct_wrap4 wrap_function(T (&f)(A0, A1, A2, A3)) { return funct_wrap4(f); } + template + funct_wrap5 wrap_function(T (&f)(A0, A1, A2, A3, A4)) { return funct_wrap5(f); } + +// ---------------------------------------------------------------------------------------- + + template + class stack_based_memory_block : noncopyable + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a simple container for a block of memory + of bSIZE bytes. This memory block is located on the stack + and properly aligned to hold any kind of object. + !*/ + public: + static const unsigned long size = bSIZE; + + stack_based_memory_block(): data(mem.data) {} + + void* get () { return data; } + /*! + ensures + - returns a pointer to the block of memory contained in this object + !*/ + + const void* get () const { return data; } + /*! + ensures + - returns a pointer to the block of memory contained in this object + !*/ + + private: + + // You obviously can't have a block of memory that has zero bytes in it. + COMPILE_TIME_ASSERT(bSIZE > 0); + + union mem_block + { + // All of this garbage is to make sure this union is properly aligned + // (a union is always aligned such that everything in it would be properly + // aligned. So the assumption here is that one of these objects has + // a large enough alignment requirement to satisfy any object this + // block of memory might be cast into). + void* void_ptr; + int integer; + struct { + void (stack_based_memory_block::*callback)(); + stack_based_memory_block* o; + } stuff; + long double more_stuff; + + uint64 var1; + uint32 var2; + double var3; + + char data[size]; + } mem; + + // The reason for having this variable is that doing it this way avoids + // warnings from gcc about violations of strict-aliasing rules. + void* const data; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ALGs_ + diff --git a/libs/dlib/dassert.h b/libs/dlib/dassert.h new file mode 100644 index 0000000..c62049d --- /dev/null +++ b/libs/dlib/dassert.h @@ -0,0 +1,140 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ASSERt_ +#define DLIB_ASSERt_ + + +#include +#include +#include "error.h" + +// ----------------------------- + +// Use some stuff from boost here +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Bill Kempf 2002. +// (C) Copyright Jens Maurer 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Gennaro Prota 2003. +// (C) Copyright Eric Friedman 2003. +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef BOOST_JOIN +#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y ) +#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y) +#define BOOST_DO_JOIN2( X, Y ) X##Y +#endif + +// ----------------------------- + +namespace dlib +{ + template struct compile_time_assert; + template <> struct compile_time_assert { enum {value=1}; }; + + template struct assert_are_same_type; + template struct assert_are_same_type {enum{value=1};}; + template struct assert_are_not_same_type {enum{value=1}; }; + template struct assert_are_not_same_type {}; +} +#define COMPILE_TIME_ASSERT(expression) \ + typedef char BOOST_JOIN(DLIB_CTA, __LINE__)[::dlib::compile_time_assert<(bool)(expression)>::value] + +#define ASSERT_ARE_SAME_TYPE(type1, type2) \ + typedef char BOOST_JOIN(DLIB_AAST, __LINE__)[::dlib::assert_are_same_type::value] + +#define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) \ + typedef char BOOST_JOIN(DLIB_AANST, __LINE__)[::dlib::assert_are_not_same_type::value] + +// ----------------------------- + +#if defined DEBUG || defined _DEBUG + // make sure ENABLE_ASSERTS is defined if we are indeed using them. + #ifndef ENABLE_ASSERTS + #define ENABLE_ASSERTS + #endif +#endif + +// ----------------------------- + +#ifdef __GNUC__ +// There is a bug in version 4.4.5 of GCC on Ubuntu which causes GCC to segfault +// when __PRETTY_FUNCTION__ is used within certain templated functions. So just +// don't use it with this version of GCC. +# if !(__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 5) +# define DLIB_FUNCTION_NAME __PRETTY_FUNCTION__ +# else +# define DLIB_FUNCTION_NAME "unknown function" +# endif +#elif _MSC_VER +#define DLIB_FUNCTION_NAME __FUNCSIG__ +#else +#define DLIB_FUNCTION_NAME "unknown function" +#endif + +#define DLIB_CASSERT(_exp,_message) \ + {if ( !(_exp) ) \ + { \ + dlib_assert_breakpoint(); \ + std::ostringstream dlib__out; \ + dlib__out << "\n\nError detected at line " << __LINE__ << ".\n"; \ + dlib__out << "Error detected in file " << __FILE__ << ".\n"; \ + dlib__out << "Error detected in function " << DLIB_FUNCTION_NAME << ".\n\n"; \ + dlib__out << "Failing expression was " << #_exp << ".\n"; \ + dlib__out << std::boolalpha << _message << "\n"; \ + throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib__out.str()); \ + }} + + +#ifdef ENABLE_ASSERTS + #define DLIB_ASSERT(_exp,_message) DLIB_CASSERT(_exp,_message) + #define DLIB_IF_ASSERT(exp) exp +#else + #define DLIB_ASSERT(_exp,_message) + #define DLIB_IF_ASSERT(exp) +#endif + +// ---------------------------------------------------------------------------------------- + + /*!A DLIB_ASSERT_HAS_STANDARD_LAYOUT + + This macro is meant to cause a compiler error if a type doesn't have a simple + memory layout (like a C struct). In particular, types with simple layouts are + ones which can be copied via memcpy(). + + + This was called a POD type in C++03 and in C++0x we are looking to check if + it is a "standard layout type". Once we can use C++0x we can change this macro + to something that uses the std::is_standard_layout type_traits class. + See: http://www2.research.att.com/~bs/C++0xFAQ.html#PODs + !*/ + // Use the fact that in C++03 you can't put non-PODs into a union. +#define DLIB_ASSERT_HAS_STANDARD_LAYOUT(type) \ + union BOOST_JOIN(DAHSL_,__LINE__) { type TYPE_NOT_STANDARD_LAYOUT; }; \ + typedef char BOOST_JOIN(DAHSL2_,__LINE__)[sizeof(BOOST_JOIN(DAHSL_,__LINE__))]; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// breakpoints +extern "C" +{ + inline void dlib_assert_breakpoint( + ) {} + /*! + ensures + - this function does nothing + It exists just so you can put breakpoints on it in a debugging tool. + It is called only when an DLIB_ASSERT or DLIB_CASSERT fails and is about to + throw an exception. + !*/ +} + +// ----------------------------- + +#include "stack_trace.h" + +#endif // DLIB_ASSERt_ + diff --git a/libs/dlib/enable_if.h b/libs/dlib/enable_if.h new file mode 100644 index 0000000..d72ae57 --- /dev/null +++ b/libs/dlib/enable_if.h @@ -0,0 +1,140 @@ +// Boost enable_if library + +// Copyright 2003 (C) The Trustees of Indiana University. + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu) +// Jeremiah Willcock (jewillco at osl.iu.edu) +// Andrew Lumsdaine (lums at osl.iu.edu) + +#ifndef DLIB_BOOST_UTILITY_ENABLE_IF_HPP +#define DLIB_BOOST_UTILITY_ENABLE_IF_HPP + + +#ifndef BOOST_UTILITY_ENABLE_IF_HPP +#define BOOST_UTILITY_ENABLE_IF_HPP + +// Even the definition of enable_if causes problems on some compilers, +// so it's macroed out for all compilers that do not support SFINAE + +#ifndef BOOST_NO_SFINAE + +namespace boost +{ + + template + struct enable_if_c { + typedef T type; + }; + + template + struct enable_if_c {}; + + template + struct enable_if : public enable_if_c {}; + + template + struct lazy_enable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_enable_if_c {}; + + template + struct lazy_enable_if : public lazy_enable_if_c {}; + + + template + struct disable_if_c { + typedef T type; + }; + + template + struct disable_if_c {}; + + template + struct disable_if : public disable_if_c {}; + + template + struct lazy_disable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_disable_if_c {}; + + template + struct lazy_disable_if : public lazy_disable_if_c {}; + +} // namespace boost + +#else + +namespace boost +{ + + namespace detail { typedef void enable_if_default_T; } + + template + struct enable_if_does_not_work_on_this_compiler; + + template + struct enable_if_c : enable_if_does_not_work_on_this_compiler + { }; + + template + struct disable_if_c : enable_if_does_not_work_on_this_compiler + { }; + + template + struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler + { }; + + template + struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler + { }; + + template + struct enable_if : enable_if_does_not_work_on_this_compiler + { }; + + template + struct disable_if : enable_if_does_not_work_on_this_compiler + { }; + + template + struct lazy_enable_if : enable_if_does_not_work_on_this_compiler + { }; + + template + struct lazy_disable_if : enable_if_does_not_work_on_this_compiler + { }; + +} // namespace boost + +#endif // BOOST_NO_SFINAE + +#endif // BOOST_UTILITY_ENABLE_IF_HPP + +namespace dlib +{ + using boost::enable_if_c; + using boost::enable_if_c; + using boost::enable_if; + using boost::lazy_enable_if_c; + using boost::lazy_enable_if_c; + using boost::lazy_enable_if; + using boost::disable_if_c; + using boost::disable_if_c; + using boost::disable_if; + using boost::lazy_disable_if_c; + using boost::lazy_disable_if_c; + using boost::lazy_disable_if; +} + +#endif // DLIB_BOOST_UTILITY_ENABLE_IF_HPP + diff --git a/libs/dlib/error.h b/libs/dlib/error.h new file mode 100644 index 0000000..8ee4241 --- /dev/null +++ b/libs/dlib/error.h @@ -0,0 +1,420 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ERROr_ +#define DLIB_ERROr_ + +#include +#include // for std::bad_alloc +#include +#include +#include +#include + +// ------------------------------- +// ------ exception classes ------ +// ------------------------------- + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + enum error_type + { + EPORT_IN_USE, + ETIMEOUT, + ECONNECTION, + ELISTENER, + ERESOLVE, + EMONITOR, + ECREATE_THREAD, + ECREATE_MUTEX, + ECREATE_SIGNALER, + EUNSPECIFIED, + EGENERAL_TYPE1, + EGENERAL_TYPE2, + EGENERAL_TYPE3, + EINVALID_OPTION, + ETOO_FEW_ARGS, + ETOO_MANY_ARGS, + ESOCKET, + ETHREAD, + EGUI, + EFATAL, + EBROKEN_ASSERT, + EIMAGE_LOAD, + EDIR_CREATE, + EINCOMPATIBLE_OPTIONS, + EMISSING_REQUIRED_OPTION, + EINVALID_OPTION_ARG, + EMULTIPLE_OCCURANCES, + ECONFIG_READER, + EIMAGE_SAVE, + ECAST_TO_STRING, + ESTRING_CAST, + EUTF8_TO_UTF32, + EOPTION_PARSE + }; + +// ---------------------------------------------------------------------------------------- + + // the base exception class + class error : public std::exception + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the base exception class for the dlib library. i.e. all + exceptions in this library inherit from this class. + !*/ + + public: + error( + error_type t, + const std::string& a + ): info(a), type(t) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + error( + error_type t + ): type(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + error( + const std::string& a + ): info(a), type(EUNSPECIFIED) {} + /*! + ensures + - #type == EUNSPECIFIED + - #info == a + !*/ + + error( + ): type(EUNSPECIFIED) {} + /*! + ensures + - #type == EUNSPECIFIED + - #info == "" + !*/ + + virtual ~error( + ) throw() {} + /*! + ensures + - does nothing + !*/ + + const char* what( + ) const throw() + /*! + ensures + - if (info.size() != 0) then + - returns info.c_str() + - else + - returns type_to_string(type) + !*/ + { + if (info.size() > 0) + return info.c_str(); + else + return type_to_string(); + } + + const char* type_to_string ( + ) const throw() + /*! + ensures + - returns a string that names the contents of the type member. + !*/ + { + if ( type == EPORT_IN_USE) return "EPORT_IN_USE"; + else if ( type == ETIMEOUT) return "ETIMEOUT"; + else if ( type == ECONNECTION) return "ECONNECTION"; + else if ( type == ELISTENER) return "ELISTENER"; + else if ( type == ERESOLVE) return "ERESOLVE"; + else if ( type == EMONITOR) return "EMONITOR"; + else if ( type == ECREATE_THREAD) return "ECREATE_THREAD"; + else if ( type == ECREATE_MUTEX) return "ECREATE_MUTEX"; + else if ( type == ECREATE_SIGNALER) return "ECREATE_SIGNALER"; + else if ( type == EUNSPECIFIED) return "EUNSPECIFIED"; + else if ( type == EGENERAL_TYPE1) return "EGENERAL_TYPE1"; + else if ( type == EGENERAL_TYPE2) return "EGENERAL_TYPE2"; + else if ( type == EGENERAL_TYPE3) return "EGENERAL_TYPE3"; + else if ( type == EINVALID_OPTION) return "EINVALID_OPTION"; + else if ( type == ETOO_FEW_ARGS) return "ETOO_FEW_ARGS"; + else if ( type == ETOO_MANY_ARGS) return "ETOO_MANY_ARGS"; + else if ( type == ESOCKET) return "ESOCKET"; + else if ( type == ETHREAD) return "ETHREAD"; + else if ( type == EGUI) return "EGUI"; + else if ( type == EFATAL) return "EFATAL"; + else if ( type == EBROKEN_ASSERT) return "EBROKEN_ASSERT"; + else if ( type == EIMAGE_LOAD) return "EIMAGE_LOAD"; + else if ( type == EDIR_CREATE) return "EDIR_CREATE"; + else if ( type == EINCOMPATIBLE_OPTIONS) return "EINCOMPATIBLE_OPTIONS"; + else if ( type == EMISSING_REQUIRED_OPTION) return "EMISSING_REQUIRED_OPTION"; + else if ( type == EINVALID_OPTION_ARG) return "EINVALID_OPTION_ARG"; + else if ( type == EMULTIPLE_OCCURANCES) return "EMULTIPLE_OCCURANCES"; + else if ( type == ECONFIG_READER) return "ECONFIG_READER"; + else if ( type == EIMAGE_SAVE) return "EIMAGE_SAVE"; + else if ( type == ECAST_TO_STRING) return "ECAST_TO_STRING"; + else if ( type == ESTRING_CAST) return "ESTRING_CAST"; + else if ( type == EUTF8_TO_UTF32) return "EUTF8_TO_UTF32"; + else if ( type == EOPTION_PARSE) return "EOPTION_PARSE"; + else return "undefined error type"; + } + + const std::string info; // info about the error + const error_type type; // the type of the error + + private: + const error& operator=(const error&); + }; + +// ---------------------------------------------------------------------------------------- + + class fatal_error : public error + { + /*! + WHAT THIS OBJECT REPRESENTS + As the name says, this object represents some kind of fatal error. + That is, it represents an unrecoverable error and any program that + throws this exception is, by definition, buggy and needs to be fixed. + + Note that a fatal_error exception can only be thrown once. The second + time an application attempts to construct a fatal_error it will be + immediately aborted and an error message will be printed to std::cerr. + The reason for this is because the first fatal_error was apparently ignored + so the second fatal_error is going to make itself impossible to ignore + by calling abort. The lesson here is that you should not try to ignore + fatal errors. + + This is also the exception thrown by the DLIB_ASSERT and DLIB_CASSERT macros. + !*/ + + public: + fatal_error( + error_type t, + const std::string& a + ): error(t,a) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == t + - #info == a + !*/ + + fatal_error( + error_type t + ): error(t) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == t + - #info == "" + !*/ + + fatal_error( + const std::string& a + ): error(EFATAL,a) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == EFATAL + - #info == a + !*/ + + fatal_error( + ): error(EFATAL) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == EFATAL + - #info == "" + !*/ + + private: + + static inline char* message () + { + static char buf[2000]; + buf[1999] = '\0'; // just to be extra safe + return buf; + } + + static inline void dlib_fatal_error_terminate ( + ) + { + std::cerr << "\n**************************** FATAL ERROR DETECTED ****************************"; + std::cerr << message() << std::endl; + std::cerr << "******************************************************************************\n" << std::endl; + } + + void check_for_previous_fatal_errors() + { + static bool is_first_fatal_error = true; + if (is_first_fatal_error == false) + { + std::cerr << "\n\n ************************** FATAL ERROR DETECTED ************************** " << std::endl; + std::cerr << " ************************** FATAL ERROR DETECTED ************************** " << std::endl; + std::cerr << " ************************** FATAL ERROR DETECTED ************************** \n" << std::endl; + std::cerr << "Two fatal errors have been detected, the first was inappropriately ignored. \n" + << "To prevent further fatal errors from being ignored this application will be \n" + << "terminated immediately and you should go fix this buggy program.\n\n" + << "The error message from this fatal error was:\n" << this->what() << "\n\n" << std::endl; + using namespace std; +// assert(false); + abort(); + } + else + { + // copy the message into the fixed message buffer so that it can be recalled by dlib_fatal_error_terminate + // if needed. + char* msg = message(); + unsigned long i; + for (i = 0; i < 2000-1 && i < this->info.size(); ++i) + msg[i] = info[i]; + msg[i] = '\0'; + + // set this termination handler so that if the user doesn't catch this dlib::fatal_error that is being + // thrown then it will eventually be printed to standard error + std::set_terminate(&dlib_fatal_error_terminate); + } + is_first_fatal_error = false; + } + }; + +// ---------------------------------------------------------------------------------------- + + class gui_error : public error + { + public: + gui_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + gui_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + gui_error( + const std::string& a + ): error(EGUI,a) {} + /*! + ensures + - #type == EGUI + - #info == a + !*/ + + gui_error( + ): error(EGUI) {} + /*! + ensures + - #type == EGUI + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class socket_error : public error + { + public: + socket_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + socket_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + socket_error( + const std::string& a + ): error(ESOCKET,a) {} + /*! + ensures + - #type == ESOCKET + - #info == a + !*/ + + socket_error( + ): error(ESOCKET) {} + /*! + ensures + - #type == ESOCKET + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class thread_error : public error + { + public: + thread_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + thread_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + thread_error( + const std::string& a + ): error(ETHREAD,a) {} + /*! + ensures + - #type == ETHREAD + - #info == a + !*/ + + thread_error( + ): error(ETHREAD) {} + /*! + ensures + - #type == ETHREAD + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ERROr_ + diff --git a/libs/dlib/geometry/border_enumerator.h b/libs/dlib/geometry/border_enumerator.h new file mode 100644 index 0000000..25c56f9 --- /dev/null +++ b/libs/dlib/geometry/border_enumerator.h @@ -0,0 +1,186 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BORDER_EnUMERATOR_H_ +#define DLIB_BORDER_EnUMERATOR_H_ + +#include "border_enumerator_abstract.h" +#include "rectangle.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class border_enumerator + { + public: + border_enumerator( + ) + { + reset(); + } + + border_enumerator( + const rectangle& rect_, + unsigned long border_size + ) : + rect(rect_), + inner_rect(shrink_rect(rect_, border_size)) + { + reset(); + } + + border_enumerator( + const rectangle& rect_, + const rectangle& non_border_region + ) : + rect(rect_), + inner_rect(non_border_region.intersect(rect)) + { + reset(); + } + + void reset ( + ) + { + // make the four rectangles that surround inner_rect and intersect them + // with rect. + bleft = rect.intersect(rectangle(std::numeric_limits::min(), + std::numeric_limits::min(), + inner_rect.left()-1, + std::numeric_limits::max())); + + bright = rect.intersect(rectangle(inner_rect.right()+1, + std::numeric_limits::min(), + std::numeric_limits::max(), + std::numeric_limits::max())); + + btop = rect.intersect(rectangle(inner_rect.left(), + std::numeric_limits::min(), + inner_rect.right(), + inner_rect.top()-1)); + + bbottom = rect.intersect(rectangle(inner_rect.left(), + inner_rect.bottom()+1, + inner_rect.right(), + std::numeric_limits::max())); + + p = bleft.tl_corner(); + p.x() -= 1; + + mode = atleft; + } + + bool at_start ( + ) const + { + point temp = bleft.tl_corner(); + temp.x() -=1; + return temp == p; + } + + bool current_element_valid( + ) const + { + return rect.contains(p); + } + + bool move_next() + { + if (mode == atleft) + { + if (advance_point(bleft, p)) + return true; + + mode = attop; + p = btop.tl_corner(); + p.x() -= 1; + } + if (mode == attop) + { + if (advance_point(btop, p)) + return true; + + mode = atright; + p = bright.tl_corner(); + p.x() -= 1; + } + if (mode == atright) + { + if (advance_point(bright, p)) + return true; + + mode = atbottom; + p = bbottom.tl_corner(); + p.x() -= 1; + } + + if (advance_point(bbottom, p)) + return true; + + // put p outside rect since there are no more points to enumerate + p = rect.br_corner(); + p.x() += 1; + + return false; + } + + unsigned long size ( + ) const + { + return rect.area() - inner_rect.area(); + } + + const point& element ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(current_element_valid(), + "\t point border_enumerator::element()" + << "\n\t This function can't be called unless the element is valid." + << "\n\t this: " << this + ); + + return p; + } + + private: + + bool advance_point ( + const rectangle& r, + point& p + ) const + { + p.x() += 1; + if (p.x() > r.right()) + { + p.x() = r.left(); + p.y() += 1; + } + + return r.contains(p); + } + + point p; + rectangle rect; + rectangle inner_rect; // the non-border regions of rect + + enum emode + { + atleft, + atright, + atbottom, + attop + }; + + emode mode; + + rectangle btop, bleft, bright, bbottom; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BORDER_EnUMERATOR_H_ + diff --git a/libs/dlib/geometry/border_enumerator_abstract.h b/libs/dlib/geometry/border_enumerator_abstract.h new file mode 100644 index 0000000..e61568c --- /dev/null +++ b/libs/dlib/geometry/border_enumerator_abstract.h @@ -0,0 +1,126 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_ +#ifdef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_ + +#include "rectangle_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class border_enumerator + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + All operations on this object other than calling element() invalidate + pointers and references to internal data. + + WHAT THIS OBJECT REPRESENTS + This object is an enumerator over the border points of a rectangle. + !*/ + public: + + border_enumerator( + ); + /*! + ensures + - #move_next() == false + (i.e. this object is "empty" and won't enumerate anything) + - current_element_valid() == false + - at_start() == true + - size() == 0 + !*/ + + border_enumerator( + const rectangle& rect, + unsigned long border_size + ); + /*! + ensures + - This object will enumerate over the border points which are inside rect + but within border_size of the edge. For example, if border_size == 1 + then it enumerates over the single point wide strip of points all around + the interior edge of rect. + - current_element_valid() == false + - at_start() == true + - size() == rect.area() - shrink_rect(rect,border_size).area() + (i.e. the number of points in the border area of rect) + !*/ + + border_enumerator( + const rectangle& rect, + const rectangle& non_border_region + ); + /*! + ensures + - This object will enumerate over all points which are in rect but + not in non_border_region. + - current_element_valid() == false + - at_start() == true + - size() == rect.area() - rect.intersect(non_border_region).area() + !*/ + + bool at_start ( + ) const; + /*! + ensures + - returns true if *this represents one position before the first point + (this would also make the current element invalid) else returns false + !*/ + + void reset ( + ); + /*! + ensures + - #current_element_valid() == false + - #at_start() == true + !*/ + + bool current_element_valid( + ) const; + /*! + ensures + - returns true if we are currently at a valid element else + returns false + !*/ + + bool move_next( + ); + /*! + ensures + - moves to the next element. i.e. #element() will now + return the next border point. + - the return value will be equal to #current_element_valid() + - #at_start() == false + + - returns true if there is another element + - returns false if there are no more elements in the container + !*/ + + unsigned long size ( + ) const; + /*! + ensures + - returns the number of border points + !*/ + + const point& element ( + ) const; + /*! + requires + - current_element_valid() == true + ensures + - returns the current border point + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BORDER_EnUMERATOR_ABSTRACT_H_ + + diff --git a/libs/dlib/geometry/rectangle.h b/libs/dlib/geometry/rectangle.h new file mode 100644 index 0000000..61f42db --- /dev/null +++ b/libs/dlib/geometry/rectangle.h @@ -0,0 +1,653 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_RECTANGLe_ +#define DLIB_RECTANGLe_ + +#include "rectangle_abstract.h" +#include "../algs.h" +#include +#include +#include "../serialize.h" +#include "vector.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class rectangle + { + /*! + INITIAL VALUE + The initial value of this object is defined by its constructor. + + CONVENTION + left() == l + top() == t + right() == r + bottom() == b + !*/ + + public: + + rectangle ( + long l_, + long t_, + long r_, + long b_ + ) : + l(l_), + t(t_), + r(r_), + b(b_) + {} + + rectangle ( + unsigned long w, + unsigned long h + ) : + l(0), + t(0), + r(static_cast(w)-1), + b(static_cast(h)-1) + { + DLIB_ASSERT((w > 0 && h > 0) || (w == 0 && h == 0), + "\trectangle(width,height)" + << "\n\twidth and height must be > 0 or both == 0" + << "\n\twidth: " << w + << "\n\theight: " << h + << "\n\tthis: " << this + ); + } + + rectangle ( + const point& p + ) : + l(p.x()), + t(p.y()), + r(p.x()), + b(p.y()) + { + } + + rectangle ( + const point& p1, + const point& p2 + ) + { + *this = rectangle(p1) + rectangle(p2); + } + + template + rectangle ( + const vector& p1, + const vector& p2 + ) + { + *this = rectangle(p1) + rectangle(p2); + } + + rectangle ( + ) : + l(0), + t(0), + r(-1), + b(-1) + {} + + long top ( + ) const { return t; } + + long& top ( + ) { return t; } + + void set_top ( + long top_ + ) { t = top_; } + + long left ( + ) const { return l; } + + long& left ( + ) { return l; } + + void set_left ( + long left_ + ) { l = left_; } + + long right ( + ) const { return r; } + + long& right ( + ) { return r; } + + void set_right ( + long right_ + ) { r = right_; } + + long bottom ( + ) const { return b; } + + long& bottom ( + ) { return b; } + + void set_bottom ( + long bottom_ + ) { b = bottom_; } + + const point tl_corner ( + ) const { return point(left(), top()); } + + const point bl_corner ( + ) const { return point(left(), bottom()); } + + const point tr_corner ( + ) const { return point(right(), top()); } + + const point br_corner ( + ) const { return point(right(), bottom()); } + + unsigned long width ( + ) const + { + if (is_empty()) + return 0; + else + return r - l + 1; + } + + unsigned long height ( + ) const + { + if (is_empty()) + return 0; + else + return b - t + 1; + } + + unsigned long area ( + ) const + { + return width()*height(); + } + + bool is_empty ( + ) const { return (t > b || l > r); } + + rectangle operator + ( + const rectangle& rhs + ) const + { + if (rhs.is_empty()) + return *this; + else if (is_empty()) + return rhs; + + return rectangle ( + std::min(l,rhs.l), + std::min(t,rhs.t), + std::max(r,rhs.r), + std::max(b,rhs.b) + ); + } + + rectangle intersect ( + const rectangle& rhs + ) const + { + return rectangle ( + std::max(l,rhs.l), + std::max(t,rhs.t), + std::min(r,rhs.r), + std::min(b,rhs.b) + ); + } + + bool contains ( + const point& p + ) const + { + if (p.x() < l || p.x() > r || p.y() < t || p.y() > b) + return false; + return true; + } + + bool contains ( + long x, + long y + ) const + { + if (x < l || x > r || y < t || y > b) + return false; + return true; + } + + bool contains ( + const rectangle& rect + ) const + { + return (rect + *this == *this); + } + + rectangle& operator+= ( + const point& p + ) + { + *this = *this + rectangle(p); + return *this; + } + + rectangle& operator+= ( + const rectangle& rect + ) + { + *this = *this + rect; + return *this; + } + + bool operator== ( + const rectangle& rect + ) const + { + return (l == rect.l) && (t == rect.t) && (r == rect.r) && (b == rect.b); + } + + bool operator!= ( + const rectangle& rect + ) const + { + return !(*this == rect); + } + + private: + long l; + long t; + long r; + long b; + }; + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const rectangle& item, + std::ostream& out + ) + { + try + { + serialize(item.left(),out); + serialize(item.top(),out); + serialize(item.right(),out); + serialize(item.bottom(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type rectangle"); + } + } + + inline void deserialize ( + rectangle& item, + std::istream& in + ) + { + try + { + deserialize(item.left(),in); + deserialize(item.top(),in); + deserialize(item.right(),in); + deserialize(item.bottom(),in); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type rectangle"); + } + } + + inline std::ostream& operator<< ( + std::ostream& out, + const rectangle& item + ) + { + out << "[(" << item.left() << ", " << item.top() << ") (" << item.right() << ", " << item.bottom() << ")]"; + return out; + } + + inline std::istream& operator>>( + std::istream& in, + rectangle& item + ) + { + // ignore any whitespace + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') + in.get(); + // now eat the leading '[' character + if (in.get() != '[') + { + in.setstate(in.rdstate() | std::ios::failbit); + return in; + } + + point p1, p2; + in >> p1; + in >> p2; + item = rectangle(p1) + rectangle(p2); + + // ignore any whitespace + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') + in.get(); + // now eat the trailing ']' character + if (in.get() != ']') + { + in.setstate(in.rdstate() | std::ios::failbit); + } + return in; + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle centered_rect ( + long x, + long y, + unsigned long width, + unsigned long height + ) + { + rectangle result; + result.set_left ( x - static_cast(width) / 2 ); + result.set_top ( y - static_cast(height) / 2 ); + result.set_right ( result.left() + width - 1 ); + result.set_bottom ( result.top() + height - 1 ); + return result; + } + +// ---------------------------------------------------------------------------------------- + + inline point center ( + const dlib::rectangle& rect + ) + { + point temp(rect.left() + rect.right() + 1, + rect.top() + rect.bottom() + 1); + + if (temp.x() < 0) + temp.x() -= 1; + + if (temp.y() < 0) + temp.y() -= 1; + + return temp/2; + } + +// ---------------------------------------------------------------------------------------- + + inline dlib::vector dcenter ( + const dlib::rectangle& rect + ) + { + dlib::vector temp(rect.left() + rect.right(), + rect.top() + rect.bottom()); + + return temp/2.0; + } + +// ---------------------------------------------------------------------------------------- + + inline long distance_to_rect_edge ( + const rectangle& rect, + const point& p + ) + { + using std::max; + using std::min; + using std::abs; + + const long dist_x = min(abs(p.x()-rect.left()), abs(p.x()-rect.right())); + const long dist_y = min(abs(p.y()-rect.top()), abs(p.y()-rect.bottom())); + + if (rect.contains(p)) + return min(dist_x,dist_y); + else if (rect.left() <= p.x() && p.x() <= rect.right()) + return dist_y; + else if (rect.top() <= p.y() && p.y() <= rect.bottom()) + return dist_x; + else + return dist_x + dist_y; + } + +// ---------------------------------------------------------------------------------------- + + inline const point nearest_point ( + const rectangle& rect, + const point& p + ) + { + point temp(p); + if (temp.x() < rect.left()) + temp.x() = rect.left(); + else if (temp.x() > rect.right()) + temp.x() = rect.right(); + + if (temp.y() < rect.top()) + temp.y() = rect.top(); + else if (temp.y() > rect.bottom()) + temp.y() = rect.bottom(); + + return temp; + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle centered_rect ( + const point& p, + unsigned long width, + unsigned long height + ) + { + return centered_rect(p.x(),p.y(),width,height); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle centered_rect ( + const rectangle& rect, + unsigned long width, + unsigned long height + ) + { + return centered_rect((rect.left()+rect.right())/2, (rect.top()+rect.bottom())/2, width, height); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle shrink_rect ( + const rectangle& rect, + long num + ) + { + return rectangle(rect.left()+num, rect.top()+num, rect.right()-num, rect.bottom()-num); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle grow_rect ( + const rectangle& rect, + long num + ) + { + return shrink_rect(rect, -num); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle shrink_rect ( + const rectangle& rect, + long width, + long height + ) + { + return rectangle(rect.left()+width, rect.top()+height, rect.right()-width, rect.bottom()-height); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle grow_rect ( + const rectangle& rect, + long width, + long height + ) + { + return shrink_rect(rect, -width, -height); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle translate_rect ( + const rectangle& rect, + const point& p + ) + { + rectangle result; + result.set_top ( rect.top() + p.y() ); + result.set_bottom ( rect.bottom() + p.y() ); + result.set_left ( rect.left() + p.x() ); + result.set_right ( rect.right() + p.x() ); + return result; + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle translate_rect ( + const rectangle& rect, + long x, + long y + ) + { + rectangle result; + result.set_top ( rect.top() + y ); + result.set_bottom ( rect.bottom() + y ); + result.set_left ( rect.left() + x ); + result.set_right ( rect.right() + x ); + return result; + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle resize_rect ( + const rectangle& rect, + unsigned long width, + unsigned long height + ) + { + return rectangle(rect.left(),rect.top(), + rect.left()+width-1, + rect.top()+height-1); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle resize_rect_width ( + const rectangle& rect, + unsigned long width + ) + { + return rectangle(rect.left(),rect.top(), + rect.left()+width-1, + rect.bottom()); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle resize_rect_height ( + const rectangle& rect, + unsigned long height + ) + { + return rectangle(rect.left(),rect.top(), + rect.right(), + rect.top()+height-1); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle move_rect ( + const rectangle& rect, + const point& p + ) + { + return rectangle(p.x(), p.y(), p.x()+rect.width()-1, p.y()+rect.height()-1); + } + +// ---------------------------------------------------------------------------------------- + + inline const rectangle move_rect ( + const rectangle& rect, + long x, + long y + ) + { + return rectangle(x, y, x+rect.width()-1, y+rect.height()-1); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline const rectangle get_rect ( + const T& m + ) + { + return rectangle(0, 0, m.nc()-1, m.nr()-1); + } + +// ---------------------------------------------------------------------------------------- + + inline rectangle operator+ ( + const rectangle& r, + const point& p + ) + { + return r + rectangle(p); + } + +// ---------------------------------------------------------------------------------------- + + inline rectangle operator+ ( + const point& p, + const rectangle& r + ) + { + return r + rectangle(p); + } + +// ---------------------------------------------------------------------------------------- + +} + +namespace std +{ + /*! + Define std::less so that you can use rectangles in the associative containers. + !*/ + template<> + struct less : public binary_function + { + inline bool operator() (const dlib::rectangle& a, const dlib::rectangle& b) const + { + if (a.left() < b.left()) return true; + else if (a.left() > b.left()) return false; + else if (a.top() < b.top()) return true; + else if (a.top() > b.top()) return false; + else if (a.right() < b.right()) return true; + else if (a.right() > b.right()) return false; + else if (a.bottom() < b.bottom()) return true; + else if (a.bottom() > b.bottom()) return false; + else return false; + } + }; +} + +#endif // DLIB_RECTANGLe_ + + diff --git a/libs/dlib/geometry/rectangle_abstract.h b/libs/dlib/geometry/rectangle_abstract.h new file mode 100644 index 0000000..aab8a37 --- /dev/null +++ b/libs/dlib/geometry/rectangle_abstract.h @@ -0,0 +1,738 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_RECTANGLe_ABSTRACT_ +#ifdef DLIB_RECTANGLe_ABSTRACT_ + +#include "vector_abstract.h" +#include +#include "../serialize.h" + +namespace dlib +{ + + class rectangle + { + /*! + INITIAL VALUE + The initial value of this object is defined by its constructor. + + WHAT THIS OBJECT REPRESENTS + This object represents a rectangular region inside a Cartesian + coordinate system. The region is the rectangle with its top + left corner at position (left(),top()) and its bottom right corner + at (right(),bottom()). + + Note that the origin of the coordinate system, i.e. (0,0), is located + at the upper left corner. That is, points such as (1,1) or (3,5) + represent locations that are below and to the right of the origin. + + Also note that rectangles where top() > bottom() or left() > right() + represent empty rectangles. + !*/ + + public: + + rectangle ( + const rectangle& rect + ); + /*! + ensures + - #*this represents the same rectangle as rect + !*/ + + rectangle ( + ); + /*! + ensures + - #left() == 0 + - #top() == 0 + - #right() == -1 + - #bottom() == -1 + - #is_empty() == true + !*/ + + rectangle ( + long left_, + long top_, + long right_, + long bottom_ + ); + /*! + ensures + - #left() == left_ + - #top() == top_ + - #right() == right_ + - #bottom() == bottom_ + !*/ + + rectangle ( + unsigned long width_, + unsigned long height_ + ); + /*! + requires + - (width_ > 0 && height_ > 0) || (width_ == 0 && height_ == 0) + ensures + - #left() == 0 + - #top() == 0 + - #width() == width_ + - #height() == height_ + !*/ + + rectangle ( + const point& p + ); + /*! + ensures + - #left() == p.x() + - #top() == p.y() + - #right() == p.x() + - #bottom() == p.y() + !*/ + + template + rectangle ( + const vector& p1, + const vector& p2 + ); + /*! + ensures + - #*this == rectangle(p1) + rectangle(p2) + !*/ + + long left ( + ) const; + /*! + ensures + - returns the x coordinate for the left side of this rectangle + !*/ + + long& left ( + ); + /*! + ensures + - returns a non-const reference to the x coordinate for the left side + of this rectangle + !*/ + + void set_left ( + long left_ + ); + /*! + ensures + - #left() == left_ + !*/ + + long top ( + ) const; + /*! + ensures + - returns the y coordinate for the top of this rectangle + !*/ + + long& top ( + ); + /*! + ensures + - returns a non-const reference to the y coordinate for the + top of this rectangle + !*/ + + void set_top ( + long top_ + ); + /*! + ensures + - #top() == top_ + !*/ + + long right ( + ) const; + /*! + ensures + - returns the x coordinate for the right side of this rectangle + !*/ + + long& right ( + ); + /*! + ensures + - returns a non-const reference to the x coordinate for the right + side of this rectangle + !*/ + + void set_right ( + long right_ + ); + /*! + ensures + - #right() == right_ + !*/ + + long bottom ( + ) const; + /*! + ensures + - returns the y coordinate for the bottom of this rectangle + !*/ + + long& bottom ( + ); + /*! + ensures + - returns a non-const reference to the y coordinate for the bottom + of this rectangle + !*/ + + void set_bottom ( + long bottom_ + ); + /*! + ensures + - #bottom() == bottom_ + !*/ + + const point tl_corner ( + ) const; + /*! + ensures + - returns point(left(), top()) + (i.e. returns the top left corner point for this rectangle) + !*/ + + const point bl_corner ( + ) const; + /*! + ensures + - returns point(left(), bottom()) + (i.e. returns the bottom left corner point for this rectangle) + !*/ + + const point tr_corner ( + ) const; + /*! + ensures + - returns point(right(), top()) + (i.e. returns the top right corner point for this rectangle) + !*/ + + const point br_corner ( + ) const; + /*! + ensures + - returns point(right(), bottom()) + (i.e. returns the bottom right corner point for this rectangle) + !*/ + + bool is_empty ( + ) const; + /*! + ensures + - if (top() > bottom() || left() > right()) then + - returns true + - else + - returns false + !*/ + + unsigned long width ( + ) const; + /*! + ensures + - if (is_empty()) then + - returns 0 + - else + - returns the width of this rectangle. + (i.e. right() - left() + 1) + !*/ + + unsigned long height ( + ) const; + /*! + ensures + - if (is_empty()) then + - returns 0 + - else + - returns the height of this rectangle. + (i.e. bottom() - top() + 1) + !*/ + + unsigned long area ( + ) const; + /*! + ensures + - returns width()*height() + !*/ + + rectangle operator + ( + const rectangle& rhs + ) const; + /*! + ensures + - if (rhs.is_empty() == false && this->is_empty() == false) then + - returns the smallest rectangle that contains both *this and + rhs. + - if (rhs.is_empty() == true && this->is_empty() == false) then + - returns *this + - if (rhs.is_empty() == false && this->is_empty() == true) then + - returns rhs + - if (rhs.is_empty() == true && this->is_empty() == true) then + - returns a rectangle that has is_empty() == true + !*/ + + rectangle intersect ( + const rectangle& rhs + ) const; + /*! + ensures + - if (there is a region of intersection between *this and rhs) then + - returns a rectangle that represents the intersection of *this + and rhs. + - else + - returns a rectangle where is_empty() == true + !*/ + + bool contains ( + long x, + long y + ) const; + /*! + ensures + - if (the point (x,y) is contained in this rectangle) then + - returns true + - else + - returns false + !*/ + + bool contains ( + const point& p + ) const; + /*! + ensures + - if (the point (p.x(),p.y()) is contained in this rectangle) then + - returns true + - else + - returns false + !*/ + + bool contains ( + const rectangle& rect + ) const; + /*! + ensures + - if (rect + *this == *this) then + - returns true + (i.e. returns true if *this contains the given rectangle) + - else + - returns false + !*/ + + rectangle& operator= ( + const rectangle& rect + ); + /*! + ensures + - #*this represents the same rectangle as rect + - returns #*this + !*/ + + rectangle& operator+= ( + const rectangle& rect + ); + /*! + ensures + - #*this == *this + rect + - returns #*this + !*/ + + bool operator== ( + const rectangle& rect + ) const; + /*! + ensures + - if (top() == rect.top() && left() == rect.left() && + right() == rect.right() && bottom() == rect.bottom()) then + - returns true + - else + - returns false + !*/ + + bool operator!= ( + const rectangle& rect + ) const; + /*! + ensures + - returns !(*this == rect) + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + void serialize ( + const rectangle& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + + void deserialize ( + rectangle& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + + std::ostream& operator<< ( + std::ostream& out, + const rectangle& item + ); + /*! + ensures + - writes item to out in the form "[(left, top) (right, bottom)]" + !*/ + + std::istream& operator>>( + std::istream& in, + rectangle& item + ); + /*! + ensures + - reads a rectangle from the input stream in and stores it in #item. + The data in the input stream should be of the form [(left, top) (right, bottom)] + !*/ + +// ---------------------------------------------------------------------------------------- + + point center ( + const dlib::rectangle& rect + ); + /*! + ensures + - returns the center of the given rectangle + !*/ + +// ---------------------------------------------------------------------------------------- + + dlib::vector dcenter ( + const dlib::rectangle& rect + ); + /*! + ensures + - returns the center of the given rectangle using a real valued vector. + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle centered_rect ( + const point& p, + unsigned long width, + unsigned long height + ); + /*! + ensures + - returns a rectangle R such that: + - center(R) == p + - if (width == 0 || height == 0) + - R.width() == 0 + - R.height() == 0 + - else + - R.width() == width + - R.height() == height + - R.tl_corner() == point(p.x()-width/2, p.y()-height/2) + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle centered_rect ( + long x, + long y, + unsigned long width, + unsigned long height + ); + /*! + ensures + - returns a rectangle R such that: + - center(R) == p + - if (width == 0 || height == 0) + - R.width() == 0 + - R.height() == 0 + - else + - R.width() == width + - R.height() == height + - R.tl_corner() == point(x-width/2, y-height/2) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle centered_rect ( + const rectangle& rect, + unsigned long width, + unsigned long height + ); + /*! + ensures + - returns centered_rect( (rect.tl_corner() + rect.br_corner())/2, width, height) + (i.e. returns a rectangle centered on rect but with the given width + and height) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle shrink_rect ( + const rectangle& rect, + long num + ); + /*! + ensures + - returns rectangle(rect.left()+num, rect.top()+num, rect.right()-num, rect.bottom()-num) + (i.e. shrinks the given rectangle by shrinking its border by num) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle grow_rect ( + const rectangle& rect, + long num + ); + /*! + ensures + - return shrink_rect(rect, -num) + (i.e. grows the given rectangle by expanding its border by num) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle shrink_rect ( + const rectangle& rect, + long width, + long height + ); + /*! + ensures + - returns rectangle(rect.left()+width, rect.top()+height, rect.right()-width, rect.bottom()-height) + (i.e. shrinks the given rectangle by shrinking its left and right borders by width + and its top and bottom borders by height. ) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const rectangle grow_rect ( + const rectangle& rect, + long width, + long height + ); + /*! + ensures + - return shrink_rect(rect, -width, -height) + (i.e. grows the given rectangle by expanding its border) + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle translate_rect ( + const rectangle& rect, + const point& p + ); + /*! + ensures + - returns a rectangle R such that: + - R.left() == rect.left() + p.x() + - R.right() == rect.right() + p.x() + - R.top() == rect.top() + p.y() + - R.bottom() == rect.bottom() + p.y() + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle translate_rect ( + const rectangle& rect, + long x, + long y + ); + /*! + ensures + - returns a rectangle R such that: + - R.left() == rect.left() + x + - R.right() == rect.right() + x + - R.top() == rect.top() + y + - R.bottom() == rect.bottom() + y + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle resize_rect ( + const rectangle& rect, + unsigned long width, + unsigned long height + ); + /*! + ensures + - returns a rectangle R such that: + - if (width == 0 || height == 0) + - R.width() == 0 + - R.height() == 0 + - else + - R.width() == width + - R.height() == height + - R.left() == rect.left() + - R.top() == rect.top() + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle resize_rect_width ( + const rectangle& rect, + unsigned long width + ); + /*! + ensures + - returns a rectangle R such that: + - R.width() == width + - R.left() == rect.left() + - R.top() == rect.top() + - R.bottom() == rect.bottom() + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle resize_rect_height ( + const rectangle& rect, + unsigned long height + ); + /*! + ensures + - returns a rectangle R such that: + - R.height() == height + - R.left() == rect.left() + - R.top() == rect.top() + - R.right() == rect.right() + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle move_rect ( + const rectangle& rect, + const point& p + ); + /*! + ensures + - returns a rectangle R such that: + - R.width() == rect.width() + - R.height() == rect.height() + - R.left() == p.x() + - R.top() == p.y() + !*/ + +// ---------------------------------------------------------------------------------------- + + const rectangle move_rect ( + const rectangle& rect, + long x, + long y + ); + /*! + ensures + - returns a rectangle R such that: + - R.width() == rect.width() + - R.height() == rect.height() + - R.left() == x + - R.top() == y + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const point nearest_point ( + const rectangle& rect, + const point& p + ); + /*! + ensures + - if (rect.contains(p)) then + - returns p + - else + - returns the point in rect that is closest to p + !*/ + +// ---------------------------------------------------------------------------------------- + + inline long distance_to_rect_edge ( + const rectangle& rect, + const point& p + ); + /*! + ensures + - returns the Manhattan distance between the edge of rect and p. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const rectangle get_rect ( + const T& m + ); + /*! + requires + - T has nr() and nc() functions that return longs + ensures + - returns rectangle(0, 0, m.nc()-1, m.nr()-1) + (i.e. assuming T represents some kind of rectangular grid, such as + the dlib::matrix or dlib::array2d objects, this function returns the + bounding rectangle for that gridded object.) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline rectangle operator+ ( + const rectangle& r, + const point& p + ); + /*! + ensures + - returns r + rectangle(p) + (i.e. returns the rectangle that contains both r and p) + !*/ + +// ---------------------------------------------------------------------------------------- + + inline rectangle operator+ ( + const point& p, + const rectangle& r + ); + /*! + ensures + - returns r + rectangle(p) + (i.e. returns the rectangle that contains both r and p) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +namespace std +{ + /*! + Define std::less so that you can use rectangles in the associative containers. + !*/ + template<> + struct less : public binary_function + { + inline bool operator() (const dlib::rectangle& a, const dlib::rectangle& b) const + { + if (a.left() < b.left()) return true; + else if (a.left() > b.left()) return false; + else if (a.top() < b.top()) return true; + else if (a.top() > b.top()) return false; + else if (a.right() < b.right()) return true; + else if (a.right() > b.right()) return false; + else if (a.bottom() < b.bottom()) return true; + else if (a.bottom() > b.bottom()) return false; + else return false; + } + }; +} + +#endif // DLIB_RECTANGLe_ABSTRACT_ + diff --git a/libs/dlib/geometry/vector.h b/libs/dlib/geometry/vector.h new file mode 100644 index 0000000..957477c --- /dev/null +++ b/libs/dlib/geometry/vector.h @@ -0,0 +1,1421 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_VECTOr_H_ +#define DLIB_VECTOr_H_ + +#include +#include "vector_abstract.h" +#include "../algs.h" +#include "../serialize.h" +#include +#include +#include "../matrix/matrix.h" +#include + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// Despite my efforts to disabuse visual studio of its usual nonsense I can't find a +// way to make this warning go away without just disabling it. This is the warning: +// dlib\geometry\vector.h(129) : warning C4805: '==' : unsafe mix of type 'std::numeric_limits<_Ty>::is_integer' and type 'bool' in operation +// +#pragma warning(disable:4805) +#endif + +namespace dlib +{ + + template < + typename T, + long NR = 3 + > + class vector; + +// ---------------------------------------------------------------------------------------- + + template + struct vect_promote; + + template + struct largest_type + { + typedef T type; + }; + template + struct largest_type + { + typedef U type; + }; + + template + struct vect_promote::is_integer == std::numeric_limits::is_integer>::type> + { + // If both T and U are both either integral or non-integral then just + // use the biggest one + typedef typename largest_type::type type; + }; + + template + struct vect_promote::is_integer != std::numeric_limits::is_integer>::type> + { + typedef double type; + }; + +// ---------------------------------------------------------------------------------------- + + // This insanity here is to work around a bug in visual studio 8. These two rebind + // structures are actually declared at a few points in this file because just having the + // one declaration here isn't enough for visual studio. It takes the three spread around + // to avoid all its bugs. + template + struct vc_rebind + { + typedef vector type; + }; + template + struct vc_rebind_promote + { + typedef vector::type,N> type; + }; + +// ---------------------------------------------------------------------------------------- + + template + struct vector_assign_helper + { + template + static void assign ( + vector& dest, + const vector& src + ) + { + dest.x() = static_cast(src.x()); + dest.y() = static_cast(src.y()); + } + + template + static void assign ( + vector& dest, + const vector& src + ) + { + dest.x() = static_cast(src.x()); + dest.y() = static_cast(src.y()); + dest.z() = static_cast(src.z()); + } + + template + static void assign ( + vector& dest, + const matrix_exp& m + ) + { + T x = static_cast(m(0)); + T y = static_cast(m(1)); + dest.x() = x; + dest.y() = y; + } + + template + static void assign ( + vector& dest, + const matrix_exp& m + ) + { + T x = static_cast(m(0)); + T y = static_cast(m(1)); + T z = static_cast(m(2)); + + dest.x() = x; + dest.y() = y; + dest.z() = z; + } + }; + + // This is an overload for the case where you are converting from a floating point + // type to an integral type. These overloads make sure values are rounded to + // the nearest integral value. + template + struct vector_assign_helper::is_integer == true && + std::numeric_limits::is_integer == false>::type> + { + template + static void assign ( + vector& dest, + const vector& src + ) + { + dest.x() = static_cast(std::floor(src.x() + 0.5)); + dest.y() = static_cast(std::floor(src.y() + 0.5)); + } + + template + static void assign ( + vector& dest, + const vector& src + ) + { + dest.x() = static_cast(std::floor(src.x() + 0.5)); + dest.y() = static_cast(std::floor(src.y() + 0.5)); + dest.z() = static_cast(std::floor(src.z() + 0.5)); + } + + template + static void assign ( + vector& dest, + const matrix_exp& m + ) + { + dest.x() = static_cast(std::floor(m(0) + 0.5)); + dest.y() = static_cast(std::floor(m(1) + 0.5)); + dest.z() = static_cast(std::floor(m(2) + 0.5)); + } + + template + static void assign ( + vector& dest, + const matrix_exp& m + ) + { + dest.x() = static_cast(std::floor(m(0) + 0.5)); + dest.y() = static_cast(std::floor(m(1) + 0.5)); + } + + }; + +// ---------------------------------------------------------------------------------------- + + template + class vector : public matrix + { + /*! + INITIAL VALUE + - x() == 0 + - y() == 0 + - z() == 0 + + CONVENTION + - (*this)(0) == x() + - (*this)(1) == y() + - (*this)(2) == z() + + !*/ + + // This insanity here is to work around a bug in visual studio 8. + template + struct vc_rebind + { + typedef vector type; + }; + template + struct vc_rebind_promote + { + typedef vector::type,N> type; + }; + + public: + + typedef T type; + + vector ( + ) + { + x() = 0; + y() = 0; + z() = 0; + } + + // --------------------------------------- + + vector ( + const T _x, + const T _y, + const T _z + ) + { + x() = _x; + y() = _y; + z() = _z; + } + + // --------------------------------------- + + vector ( + const vector& item + ) : matrix(item) + { + } + + // --------------------------------------- + + template + vector ( + const vector& item + ) + { + // Do this so that we get the appropriate rounding depending on the relative + // type of T and U. + vector temp(item); + x() = temp.x(); + y() = temp.y(); + z() = 0; + } + + // --------------------------------------- + + vector ( + const vector& item + ) + { + x() = item.x(); + y() = item.y(); + z() = 0; + } + + // --------------------------------------- + + template + vector ( + const vector& item + ) + { + (*this) = item; + } + + // --------------------------------------- + + template + vector ( const matrix_exp& m) + { + (*this) = m; + } + + // --------------------------------------- + + template + vector& operator = ( + const matrix_exp& m + ) + { + // you can only assign vectors with 3 elements to a dlib::vector object + COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 3 || EXP::NR*EXP::NC == 0); + + // make sure requires clause is not broken + DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && (m.size() == 3), + "\t vector(const matrix_exp& m)" + << "\n\t the given matrix is of the wrong size" + << "\n\t m.nr(): " << m.nr() + << "\n\t m.nc(): " << m.nc() + << "\n\t m.size(): " << m.size() + << "\n\t this: " << this + ); + + vector_assign_helper::assign(*this, m); + return *this; + } + + // --------------------------------------- + + template + vector& operator = ( + const vector& item + ) + { + vector_assign_helper::assign(*this, item); + return *this; + } + + // --------------------------------------- + + vector& operator= ( + const vector& item + ) + { + x() = item.x(); + y() = item.y(); + z() = item.z(); + return *this; + } + + // --------------------------------------- + + double length( + ) const + { + return std::sqrt((double)(x()*x() + y()*y() + z()*z())); + } + + // --------------------------------------- + + typename vc_rebind::type normalize ( + ) const + { + const double tmp = std::sqrt((double)(x()*x() + y()*y() + z()*z())); + return vector ( x()/tmp, + y()/tmp, + z()/tmp + ); + } + + // --------------------------------------- + + T& x ( + ) + { + return (*this)(0); + } + + // --------------------------------------- + + T& y ( + ) + { + return (*this)(1); + } + + // --------------------------------------- + + T& z ( + ) + { + return (*this)(2); + } + + // --------------------------------------- + + const T& x ( + ) const + { + return (*this)(0); + } + + // --------------------------------------- + + const T& y ( + ) const + { + return (*this)(1); + } + + // --------------------------------------- + + const T& z ( + ) const + { + return (*this)(2); + } + + // --------------------------------------- + + T dot ( + const vector& rhs + ) const + { + return x()*rhs.x() + y()*rhs.y() + z()*rhs.z(); + } + + // --------------------------------------- + + template + typename vect_promote::type dot ( + const vector& rhs + ) const + { + return x()*rhs.x() + y()*rhs.y() + z()*rhs.z(); + } + + // --------------------------------------- + + template + typename vc_rebind_promote::type cross ( + const vector& rhs + ) const + { + typedef vector::type,3> ret_type; + + return ret_type ( + y()*rhs.z() - z()*rhs.y(), + z()*rhs.x() - x()*rhs.z(), + x()*rhs.y() - y()*rhs.x() + ); + } + + // --------------------------------------- + + vector& operator += ( + const vector& rhs + ) + { + x() += rhs.x(); + y() += rhs.y(); + z() += rhs.z(); + return *this; + } + + // --------------------------------------- + + vector& operator -= ( + const vector& rhs + ) + { + x() -= rhs.x(); + y() -= rhs.y(); + z() -= rhs.z(); + return *this; + } + + // --------------------------------------- + + vector& operator /= ( + const T& rhs + ) + { + x() /= rhs; + y() /= rhs; + z() /= rhs; + return *this; + } + + // --------------------------------------- + + vector& operator *= ( + const T& rhs + ) + { + x() *= rhs; + y() *= rhs; + z() *= rhs; + return *this; + } + + // --------------------------------------- + + vector operator - ( + ) const + { + return vector(-x(), -y(), -z()); + } + + // --------------------------------------- + + template + typename vc_rebind_promote::type operator / ( + const U& val + ) const + { + typedef vector::type,3> ret_type; + return ret_type(x()/val, y()/val, z()/val); + } + + // --------------------------------------- + + template + bool operator== ( + const vector& rhs + ) const + { + return x()==rhs.x() && y()==rhs.y() && z()==rhs.z(); + } + + // --------------------------------------- + + template + bool operator!= ( + const vector& rhs + ) const + { + return !(*this == rhs); + } + + // --------------------------------------- + + void swap ( + vector& item + ) + { + dlib::exchange(x(), item.x()); + dlib::exchange(y(), item.y()); + dlib::exchange(z(), item.z()); + } + + // --------------------------------------- + + }; + +// ---------------------------------------------------------------------------------------- + + template + class vector : public matrix + { + /*! + INITIAL VALUE + - x() == 0 + - y() == 0 + + CONVENTION + - (*this)(0) == x() + - (*this)(1) == y() + - z() == 0 + !*/ + + // This insanity here is to work around a bug in visual studio 8. + template + struct vc_rebind + { + typedef vector type; + }; + template + struct vc_rebind_promote + { + typedef vector::type,N> type; + }; + + + public: + + typedef T type; + + vector ( + ) + { + x() = 0; + y() = 0; + } + + // --------------------------------------- + + vector ( + const T _x, + const T _y + ) + { + x() = _x; + y() = _y; + } + + // --------------------------------------- + + template + vector ( + const vector& item + ) + { + // Do this so that we get the appropriate rounding depending on the relative + // type of T and U. + vector temp(item); + x() = temp.x(); + y() = temp.y(); + } + + // --------------------------------------- + + vector ( + const vector& item + ) : matrix(item) + { + } + + // --------------------------------------- + + vector ( + const vector& item + ) + { + x() = item.x(); + y() = item.y(); + } + + // --------------------------------------- + + template + vector ( + const vector& item + ) + { + (*this) = item; + } + + // --------------------------------------- + + template + vector ( const matrix_exp& m) + { + (*this) = m; + } + + // --------------------------------------- + + template + vector& operator = ( + const matrix_exp& m + ) + { + // you can only assign vectors with 2 elements to a dlib::vector object + COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 2 || EXP::NR*EXP::NC == 0); + + // make sure requires clause is not broken + DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && (m.size() == 2), + "\t vector(const matrix_exp& m)" + << "\n\t the given matrix is of the wrong size" + << "\n\t m.nr(): " << m.nr() + << "\n\t m.nc(): " << m.nc() + << "\n\t m.size(): " << m.size() + << "\n\t this: " << this + ); + + vector_assign_helper::assign(*this, m); + return *this; + } + + // --------------------------------------- + + template + vector& operator = ( + const vector& item + ) + { + vector_assign_helper::assign(*this, item); + return *this; + } + + // --------------------------------------- + + vector& operator= ( + const vector& item + ) + { + x() = item.x(); + y() = item.y(); + return *this; + } + + // --------------------------------------- + + double length( + ) const + { + return std::sqrt((double)(x()*x() + y()*y())); + } + + // --------------------------------------- + + + typename vc_rebind::type normalize ( + ) const + { + const double tmp = std::sqrt((double)(x()*x() + y()*y())); + return vector ( x()/tmp, + y()/tmp + ); + } + + // --------------------------------------- + + T& x ( + ) + { + return (*this)(0); + } + + // --------------------------------------- + + T& y ( + ) + { + return (*this)(1); + } + + // --------------------------------------- + + const T& x ( + ) const + { + return (*this)(0); + } + + // --------------------------------------- + + const T& y ( + ) const + { + return (*this)(1); + } + + // --------------------------------------- + + const T z ( + ) const + { + return 0; + } + + // --------------------------------------- + + T dot ( + const vector& rhs + ) const + { + return x()*rhs.x() + y()*rhs.y(); + } + + // --------------------------------------- + + template + typename vect_promote::type dot ( + const vector& rhs + ) const + { + return x()*rhs.x() + y()*rhs.y() + z()*rhs.z(); + } + + // --------------------------------------- + + vector& operator += ( + const vector& rhs + ) + { + x() += rhs.x(); + y() += rhs.y(); + return *this; + } + + // --------------------------------------- + + vector& operator -= ( + const vector& rhs + ) + { + x() -= rhs.x(); + y() -= rhs.y(); + return *this; + } + + // --------------------------------------- + + vector& operator /= ( + const T& rhs + ) + { + x() /= rhs; + y() /= rhs; + return *this; + } + + // --------------------------------------- + + vector& operator *= ( + const T& rhs + ) + { + x() *= rhs; + y() *= rhs; + return *this; + } + + // --------------------------------------- + + vector operator - ( + ) const + { + return vector(-x(), -y()); + } + + // --------------------------------------- + + template + typename vc_rebind_promote::type operator / ( + const U& val + ) const + { + typedef vector::type,2> ret_type; + return ret_type(x()/val, y()/val); + } + + // --------------------------------------- + + template + bool operator== ( + const vector& rhs + ) const + { + return x()==rhs.x() && y()==rhs.y() && z()==rhs.z(); + } + + // --------------------------------------- + + bool operator== ( + const vector& rhs + ) const + { + return x()==rhs.x() && y()==rhs.y(); + } + + // --------------------------------------- + + template + bool operator!= ( + const vector& rhs + ) const + { + return !(*this == rhs); + } + + // --------------------------------------- + + bool operator!= ( + const vector& rhs + ) const + { + return !(*this == rhs); + } + + // --------------------------------------- + + void swap ( + vector& item + ) + { + dlib::exchange(x(), item.x()); + dlib::exchange(y(), item.y()); + } + + // --------------------------------------- + + template + typename vc_rebind_promote::type cross ( + const vector& rhs + ) const + { + typedef vector::type,3> ret_type; + return ret_type ( + y()*rhs.z(), + - x()*rhs.z(), + x()*rhs.y() - y()*rhs.x() + ); + } + + // --------------------------------------- + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator+ ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator+ ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), lhs.z()+rhs.z()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator+ ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), rhs.z()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator+ ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), lhs.z()); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator- ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator- ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), lhs.z()-rhs.z()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator- ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), -rhs.z()); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const typename vc_rebind_promote::type operator- ( + const vector& lhs, + const vector& rhs + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), lhs.z()); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if, const typename vc_rebind_promote::type >::type operator* ( + const vector& v, + const U& s + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(v.x()*s, v.y()*s); + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if, const typename vc_rebind_promote::type >::type operator* ( + const U& s, + const vector& v + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(v.x()*s, v.y()*s); + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if, const typename vc_rebind_promote::type >::type operator* ( + const vector& v, + const U& s + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(v.x()*s, v.y()*s, v.z()*s); + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if, const typename vc_rebind_promote::type >::type operator* ( + const U& s, + const vector& v + ) + { + typedef typename vc_rebind_promote::type ret_type; + return ret_type(v.x()*s, v.y()*s, v.z()*s); + } + +// ---------------------------------------------------------------------------------------- + + template + inline void swap ( + vector & a, + vector & b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + + template + inline void serialize ( + const vector& item, + std::ostream& out + ) + { + try + { + serialize(item.x(),out); + serialize(item.y(),out); + serialize(item.z(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type vector"); + } + } + + template + inline void deserialize ( + vector& item, + std::istream& in + ) + { + try + { + deserialize(item.x(),in); + deserialize(item.y(),in); + deserialize(item.z(),in); + } + catch (serialization_error& e) + { + item.x() = 0; + item.y() = 0; + item.z() = 0; + throw serialization_error(e.info + "\n while deserializing object of type vector"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + inline void serialize ( + const vector& item, + std::ostream& out + ) + { + try + { + serialize(item.x(),out); + serialize(item.y(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type vector"); + } + } + + template + inline void deserialize ( + vector& item, + std::istream& in + ) + { + try + { + deserialize(item.x(),in); + deserialize(item.y(),in); + } + catch (serialization_error& e) + { + item.x() = 0; + item.y() = 0; + throw serialization_error(e.info + "\n while deserializing object of type vector"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + std::ostream& operator<< ( + std::ostream& out, + const vector& item + ) + { + out << "(" << item.x() << ", " << item.y() << ", " << item.z() << ")"; + return out; + } + + template + std::istream& operator>>( + std::istream& in, + vector& item + ) + { + + // eat all the crap up to the '(' + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') + in.get(); + + // there should be a '(' if not then this is an error + if (in.get() != '(') + { + in.setstate(in.rdstate() | std::ios::failbit); + return in; + } + + // eat all the crap up to the first number + while (in.peek() == ' ' || in.peek() == '\t') + in.get(); + in >> item.x(); + + if (!in.good()) + return in; + + // eat all the crap up to the next number + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') + in.get(); + in >> item.y(); + + if (!in.good()) + return in; + + // eat all the crap up to the next number + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') + in.get(); + in >> item.z(); + + if (!in.good()) + return in; + + // eat all the crap up to the ')' + while (in.peek() == ' ' || in.peek() == '\t') + in.get(); + + // there should be a ')' if not then this is an error + if (in.get() != ')') + in.setstate(in.rdstate() | std::ios::failbit); + return in; + } + +// ---------------------------------------------------------------------------------------- + + + template + std::ostream& operator<< ( + std::ostream& out, + const vector& item + ) + { + out << "(" << item.x() << ", " << item.y() << ")"; + return out; + } + + template + std::istream& operator>>( + std::istream& in, + vector& item + ) + { + + // eat all the crap up to the '(' + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') + in.get(); + + // there should be a '(' if not then this is an error + if (in.get() != '(') + { + in.setstate(in.rdstate() | std::ios::failbit); + return in; + } + + // eat all the crap up to the first number + while (in.peek() == ' ' || in.peek() == '\t') + in.get(); + in >> item.x(); + + if (!in.good()) + return in; + + // eat all the crap up to the next number + while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') + in.get(); + in >> item.y(); + + if (!in.good()) + return in; + + // eat all the crap up to the ')' + while (in.peek() == ' ' || in.peek() == '\t') + in.get(); + + // there should be a ')' if not then this is an error + if (in.get() != ')') + in.setstate(in.rdstate() | std::ios::failbit); + return in; + } + +// ---------------------------------------------------------------------------------------- + + typedef vector point; + +// ---------------------------------------------------------------------------------------- + + class point_rotator + { + public: + point_rotator ( + const double& angle + ) + { + sin_angle = std::sin(angle); + cos_angle = std::cos(angle); + } + + template + const dlib::vector operator() ( + const dlib::vector& p + ) const + { + double x = cos_angle*p.x() - sin_angle*p.y(); + double y = sin_angle*p.x() + cos_angle*p.y(); + + return dlib::vector(x,y); + } + + private: + double sin_angle; + double cos_angle; + }; + +// ---------------------------------------------------------------------------------------- + + class point_transform + { + public: + point_transform ( + const double& angle, + const dlib::vector& translate_ + ) + { + sin_angle = std::sin(angle); + cos_angle = std::cos(angle); + translate = translate_; + } + + template + const dlib::vector operator() ( + const dlib::vector& p + ) const + { + double x = cos_angle*p.x() - sin_angle*p.y(); + double y = sin_angle*p.x() + cos_angle*p.y(); + + return dlib::vector(x,y) + translate; + } + + private: + double sin_angle; + double cos_angle; + dlib::vector translate; + }; + +// ---------------------------------------------------------------------------------------- + + class point_transform_affine + { + public: + point_transform_affine ( + const matrix& m_, + const dlib::vector& b_ + ) :m(m_), b(b_) + { + } + + const dlib::vector operator() ( + const dlib::vector& p + ) const + { + return m*p + b; + } + + private: + matrix m; + dlib::vector b; + }; + +// ---------------------------------------------------------------------------------------- + + template + const dlib::vector rotate_point ( + const dlib::vector& center, + const dlib::vector& p, + double angle + ) + { + point_rotator rot(angle); + return rot(p-center)+center; + } + +// ---------------------------------------------------------------------------------------- + + inline matrix rotation_matrix ( + double angle + ) + { + const double ca = std::cos(angle); + const double sa = std::sin(angle); + + matrix m; + m = ca, -sa, + sa, ca; + return m; + } + +// ---------------------------------------------------------------------------------------- + +} + +namespace std +{ + /*! + Define std::less > so that you can use vectors in the associative containers. + !*/ + template + struct less > : public binary_function ,dlib::vector ,bool> + { + inline bool operator() (const dlib::vector & a, const dlib::vector & b) const + { + if (a.x() < b.x()) return true; + else if (a.x() > b.x()) return false; + else if (a.y() < b.y()) return true; + else if (a.y() > b.y()) return false; + else if (a.z() < b.z()) return true; + else if (a.z() > b.z()) return false; + else return false; + } + }; + + /*! + Define std::less > so that you can use vectors in the associative containers. + !*/ + template + struct less > : public binary_function ,dlib::vector ,bool> + { + inline bool operator() (const dlib::vector & a, const dlib::vector & b) const + { + if (a.x() < b.x()) return true; + else if (a.x() > b.x()) return false; + else if (a.y() < b.y()) return true; + else if (a.y() > b.y()) return false; + else return false; + } + }; +} + +#if defined(_MSC_VER) && _MSC_VER < 1400 +// turn this warning back on +#pragma warning(default:4805) +#endif + +#endif // DLIB_VECTOr_H_ + diff --git a/libs/dlib/geometry/vector_abstract.h b/libs/dlib/geometry/vector_abstract.h new file mode 100644 index 0000000..9cf9804 --- /dev/null +++ b/libs/dlib/geometry/vector_abstract.h @@ -0,0 +1,610 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_VECTOR_ABSTRACT_ +#ifdef DLIB_VECTOR_ABSTRACT_ + +#include "../serialize.h" +#include +#include +#include "../matrix/matrix_abstract.h" + +namespace dlib +{ + template < + typename T, + long NR = 3 + > + class vector : public matrix + { + /*! + REQUIREMENTS ON T + T should be some object that provides an interface that is + compatible with double, float, int, long and the like. + + REQUIREMENTS ON NR + NR == 3 || NR == 2 + + INITIAL VALUE + x() == 0 + y() == 0 + z() == 0 + + WHAT THIS OBJECT REPRESENTS + This object represents a three dimensional vector. If NR == 2 then + this object is limited to representing points on the XY plane where + Z is set to 0. + + Also note that this object performs the appropriate integer and + floating point conversions and promotions when vectors of mixed + type are used together. For example: + vector vi; + vector vd; + vd + vi == a vector object type since that is what + is needed to contain the result of vi+vd without + any loss of information. + !*/ + + public: + + typedef T type; + + vector ( + ); + /*! + ensures + - #*this has been properly initialized + !*/ + + vector ( + const T _x, + const T _y, + const T _z + ); + /*! + requires + - NR == 3 + ensures + - #x() == _x + - #y() == _y + - #z() == _z + !*/ + + vector ( + const T _x, + const T _y + ); + /*! + requires + - NR == 2 + ensures + - #x() == _x + - #y() == _y + - #z() == 0 + !*/ + + template + vector ( + const vector& v + ); + /*! + ensures + - Initializes *this with the contents of v and does any rounding if necessary and also + takes care of converting between 2 and 3 dimensional vectors. + - if (U is a real valued type like float or double and T is an integral type like long) then + - if (NR == 3) then + - #x() == floor(v.x() + 0.5) + - #y() == floor(v.y() + 0.5) + - #z() == floor(v.z() + 0.5) + - else // NR == 2 + - #x() == floor(v.x() + 0.5) + - #y() == floor(v.y() + 0.5) + - #z() == 0 + - else + - if (NR == 3) then + - #x() == v.x() + - #y() == v.y() + - #z() == v.z() + - else // NR == 2 + - #x() == v.x() + - #y() == v.y() + - #z() == 0 + !*/ + + template + vector ( + const matrix_exp& m + ); + /*! + requires + - m.size() == NR + - m.nr() == 1 || m.nc() == 1 (i.e. m must be a row or column matrix) + ensures + - Initializes *this with the contents of m and does any rounding if necessary and also + takes care of converting between 2 and 3 dimensional vectors. + - if (m contains real valued values like float or double and T is an integral type like long) then + - #x() == floor(m(0) + 0.5) + - #y() == floor(m(1) + 0.5) + - if (NR == 3) then + - #z() == floor(m(2) + 0.5) + - else + - #z() == 0 + - else + - #x() == m(0) + - #y() == m(1) + - if (NR == 3) then + - #z() == m(2) + - else + - #z() == 0 + !*/ + + ~vector ( + ); + /*! + ensures + - all resources associated with *this have been released + !*/ + + + double length( + ) const; + /*! + ensures + - returns the length of the vector + !*/ + + T& x ( + ); + /*! + ensures + - returns a reference to the x component of the vector + !*/ + + T& y ( + ); + /*! + ensures + - returns a reference to the y component of the vector + !*/ + + T& z ( + ); + /*! + requires + - NR == 3 (this function actually doesn't exist when NR != 3) + ensures + - returns a reference to the z component of the vector + !*/ + + const T& x ( + ) const; + /*! + ensures + - returns a const reference to the x component of the vector + !*/ + + const T& y ( + ) const; + /*! + ensures + - returns a const reference to the y component of the vector + !*/ + + const T& z ( + ) const; + /*! + ensures + - if (NR == 3) then + - returns a const reference to the z component of the vector + - else + - return 0 + (there isn't really a z in this case so we just return 0) + !*/ + + T dot ( + const vector& rhs + ) const; + /*! + ensures + - returns the result of the dot product between *this and rhs + !*/ + + vector cross ( + const vector& rhs + ) const; + /*! + ensures + - returns the result of the cross product between *this and rhs + !*/ + + vector normalize ( + ) const; + /*! + ensures + - returns a vector with length() == 1 and in the same direction as *this + !*/ + + vector operator+ ( + const vector& rhs + ) const; + /*! + ensures + - returns the result of adding *this to rhs + !*/ + + vector operator- ( + const vector& rhs + ) const; + /*! + ensures + - returns the result of subtracting rhs from *this + !*/ + + vector operator- ( + ) const; + /*! + ensures + - returns -1*(*this) + !*/ + + vector operator/ ( + const T rhs + ) const; + /*! + ensures + - returns the result of dividing *this by rhs + !*/ + + vector& operator= ( + const vector& rhs + ); + /*! + ensures + - #x() == rhs.x() + - #y() == rhs.y() + - #z() == rhs.z() + - returns #*this + !*/ + + vector& operator += ( + const vector& rhs + ); + /*! + ensures + - #*this == *this + rhs + - returns #*this + !*/ + + vector& operator -= ( + const vector& rhs + ); + /*! + ensures + - #*this == *this - rhs + - returns #*this + !*/ + + vector& operator *= ( + const T rhs + ); + /*! + ensures + - #*this == *this * rhs + - returns #*this + !*/ + + vector& operator /= ( + const T rhs + ); + /*! + ensures + - #*this == *this / rhs + - returns #*this + !*/ + + template + bool operator== ( + const vector& rhs + ) const; + /*! + ensures + - if (x() == rhs.x() && y() == rhs.y() && z() == rhs.z()) then + - returns true + - else + - returns false + !*/ + + template + bool operator!= ( + const vector& rhs + ) const; + /*! + ensures + - returns !((*this) == rhs) + !*/ + + void swap ( + vector& item + ); + /*! + ensures + - swaps *this and item + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template + vector operator* ( + const vector & lhs, + const U rhs + ); + /*! + ensures + - returns the result of multiplying the scalar rhs by lhs + !*/ + + template + vector operator* ( + const U lhs, + const vector & rhs + ); + /*! + ensures + - returns the result of multiplying the scalar lhs by rhs + !*/ + + template + inline void swap ( + vector & a, + vector & b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template + void serialize ( + const vector& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + + template + void deserialize ( + vector& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + + template + std::ostream& operator<< ( + std::ostream& out, + const vector& item + ); + /*! + ensures + - writes item to out in the form "(x, y, z)" + !*/ + + template + std::istream& operator>>( + std::istream& in, + vector& item + ); + /*! + ensures + - reads a vector from the input stream in and stores it in #item. + The data in the input stream should be of the form (x, y, z) + !*/ + + template + std::ostream& operator<< ( + std::ostream& out, + const vector& item + ); + /*! + ensures + - writes item to out in the form "(x, y)" + !*/ + + template + std::istream& operator>>( + std::istream& in, + vector& item + ); + /*! + ensures + - reads a vector from the input stream in and stores it in #item. + The data in the input stream should be of the form (x, y) + !*/ + +// ---------------------------------------------------------------------------------------- + + /*!A point + This is just a typedef of the vector object. + !*/ + + typedef vector point; + +// ---------------------------------------------------------------------------------------- + + class point_transform_affine + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an object that takes 2D points or vectors and + applies an affine transformation to them. + !*/ + public: + point_transform_affine ( + const matrix& m, + const dlib::vector& b + ); + /*! + ensures + - When (*this)(p) is invoked it will return a point P such that: + - P == m*p + b + !*/ + + const dlib::vector operator() ( + const dlib::vector& p + ) const; + /*! + ensures + - applies the affine transformation defined by this object's constructor + to p and returns the result. + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + class point_transform + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an object that takes 2D points or vectors and + rotates them around the origin by a given angle and then + translates them. + !*/ + public: + point_transform ( + const double& angle, + const dlib::vector& translate + ) + /*! + ensures + - When (*this)(p) is invoked it will return a point P such that: + - P is the point p rotated counter-clockwise around the origin + angle radians and then shifted by having translate added to it. + (Note that this is counter clockwise with respect to the normal + coordinate system with positive y going up and positive x going + to the right) + !*/ + + template + const dlib::vector operator() ( + const dlib::vector& p + ) const; + /*! + ensures + - rotates p, then translates it and returns the result + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class point_rotator + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an object that takes 2D points or vectors and + rotates them around the origin by a given angle. + !*/ + public: + point_rotator ( + const double& angle + ); + /*! + ensures + - When (*this)(p) is invoked it will return a point P such that: + - P is the point p rotated counter-clockwise around the origin + angle radians. + (Note that this is counter clockwise with respect to the normal + coordinate system with positive y going up and positive x going + to the right) + !*/ + + template + const dlib::vector operator() ( + const dlib::vector& p + ) const; + /*! + ensures + - rotates p and returns the result + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + const dlib::vector rotate_point ( + const dlib::vector center, + const dlib::vector p, + double angle + ); + /*! + ensures + - returns a point P such that: + - P is the point p rotated counter-clockwise around the given + center point by angle radians. + (Note that this is counter clockwise with respect to the normal + coordinate system with positive y going up and positive x going + to the right) + !*/ + +// ---------------------------------------------------------------------------------------- + + matrix rotation_matrix ( + double angle + ); + /*! + ensures + - returns a rotation matrix which rotates points around the origin in a + counter-clockwise direction by angle radians. + (Note that this is counter clockwise with respect to the normal + coordinate system with positive y going up and positive x going + to the right) + Or in other words, this function returns a matrix M such that, given a + point P, M*P gives a point which is P rotated by angle radians around + the origin in a counter-clockwise direction. + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +namespace std +{ + /*! + Define std::less > so that you can use vectors in the associative containers. + !*/ + template + struct less > : public binary_function ,dlib::vector ,bool> + { + inline bool operator() (const dlib::vector & a, const dlib::vector & b) const + { + if (a.x() < b.x()) return true; + else if (a.x() > b.x()) return false; + else if (a.y() < b.y()) return true; + else if (a.y() > b.y()) return false; + else if (a.z() < b.z()) return true; + else if (a.z() > b.z()) return false; + else return false; + } + }; + + /*! + Define std::less > so that you can use vectors in the associative containers. + !*/ + template + struct less > : public binary_function ,dlib::vector ,bool> + { + inline bool operator() (const dlib::vector & a, const dlib::vector & b) const + { + if (a.x() < b.x()) return true; + else if (a.x() > b.x()) return false; + else if (a.y() < b.y()) return true; + else if (a.y() > b.y()) return false; + else return false; + } + }; +} + +#endif // DLIB_VECTOR_ABSTRACT_ + diff --git a/libs/dlib/interfaces/cmd_line_parser_option.h b/libs/dlib/interfaces/cmd_line_parser_option.h new file mode 100644 index 0000000..19a2590 --- /dev/null +++ b/libs/dlib/interfaces/cmd_line_parser_option.h @@ -0,0 +1,99 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CMD_LINE_PARSER_OPTIOn_ +#define DLIB_CMD_LINE_PARSER_OPTIOn_ + +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT + > + class cmd_line_parser_option + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + None of the functions in cmd_line_parser_option will invalidate + pointers or references to internal data when called. + + WHAT THIS OBJECT REPRESENTS + This object represents a command line option. + !*/ + + public: + + typedef charT char_type; + typedef std::basic_string string_type; + + virtual ~cmd_line_parser_option ( + ) = 0; + + virtual const string_type& name ( + ) const = 0; + /*! + ensures + - returns the name of this option + !*/ + + virtual const string_type& description ( + ) const = 0; + /*! + ensures + - returns the description for this option + !*/ + + virtual unsigned long number_of_arguments( + ) const = 0; + /*! + ensures + - returns the number of arguments for this option + !*/ + + virtual unsigned long count( + ) const = 0; + /*! + ensures + - returns the number of times this option appears on the command line. + !*/ + + virtual const string_type& argument ( + unsigned long arg = 0, + unsigned long N = 0 + ) const = 0; + /*! + requires + - arg < number_of_arguments() + - N < count() + ensures + - returns the argth argument to the Nth occurance of this + option on the command line. + !*/ + + inline operator bool ( + ) const { return count() > 0; } + /*! + ensures + - returns true if this option appears on the command line at all + !*/ + + protected: + + // restricted functions + cmd_line_parser_option& operator=(const cmd_line_parser_option&){return *this;} + + }; + + // destructor does nothing + template < typename charT > + cmd_line_parser_option::~cmd_line_parser_option() {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_OPTIOn_ + diff --git a/libs/dlib/interfaces/enumerable.h b/libs/dlib/interfaces/enumerable.h new file mode 100644 index 0000000..0cd827b --- /dev/null +++ b/libs/dlib/interfaces/enumerable.h @@ -0,0 +1,130 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ENUMERABLe_INTERFACE_ +#define DLIB_ENUMERABLe_INTERFACE_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class enumerable + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + - if (at_start()) then + - all pointers and references to data returned via element() are + invalid. + - calling move_next() or reset() invalidates pointers and references to + data returned via element() and only data returned via element(). + - calling at_start(), current_element_valid(), size(), or element() + does NOT invalidate pointers or references to any internal data. + + INITIAL VALUE + current_element_valid() == false + at_start() == true + + WHAT THIS OBJECT REPRESENTS + This object represent an interface for iterating through the + elements in a container. It starts out one before the first element + in the container. + + + EXAMPLE: The following loops though all elements in the container + and prints them to cout. + + container.reset(); + while(container.move_next()) { + cout << container.element(); + } + !*/ + + public: + typedef T type; + + inline virtual ~enumerable( + ) = 0; + + virtual bool at_start ( + ) const = 0; + /*! + ensures + - returns true if *this represents one position before the first element + in the container (this would also make the current element invalid) + else returns false + !*/ + + virtual void reset ( + ) const = 0; + /*! + ensures + - #current_element_valid() == false + - #at_start() == true + !*/ + + virtual bool current_element_valid ( + ) const = 0; + /*! + ensures + - returns true if we are currently at a valid element else + returns false + !*/ + + virtual const T& element ( + ) const = 0; + /*! + requires + - current_element_valid() == true + ensures + - returns a const reference to the current element + !*/ + + virtual T& element ( + ) = 0; + /*! + requires + - current_element_valid() == true + ensures + - returns a non-const reference to the current element + !*/ + + virtual bool move_next ( + ) const = 0; + /*! + ensures + - moves to the next element. i.e. #element() will now + return the next element in the container + - the return value will be equal to #current_element_valid() + - #at_start() == false + + - returns true if there is another element + - returns false if there are no more elements in the container + !*/ + + virtual unsigned long size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + protected: + + // restricted functions + enumerable& operator=(const enumerable&) {return *this;} // no assignment operator + + }; + + // destructor does nothing + template + enumerable::~enumerable() {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ENUMERABLe_INTERFACE_ + diff --git a/libs/dlib/interfaces/map_pair.h b/libs/dlib/interfaces/map_pair.h new file mode 100644 index 0000000..6431015 --- /dev/null +++ b/libs/dlib/interfaces/map_pair.h @@ -0,0 +1,74 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAP_PAIr_INTERFACE_ +#define DLIB_MAP_PAIr_INTERFACE_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T1, + typename T2 + > + class map_pair + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + None of the functions in map_pair will invalidate + pointers or references to internal data when called. + + WHAT THIS OBJECT REPRESENTS + this object is used to return the key/value pair used in the + map and hash_map containers when using the enumerable interface. + + note that the enumerable interface is defined in + interfaces/enumerable.h + !*/ + + public: + typedef T1 key_type; + typedef T2 value_type; + + virtual ~map_pair( + )=0; + + virtual const T1& key( + ) const =0; + /*! + ensures + - returns a const reference to the key + !*/ + + virtual const T2& value( + ) const =0; + /*! + ensures + - returns a const reference to the value associated with key + !*/ + + virtual T2& value( + )=0; + /*! + ensures + - returns a non-const reference to the value associated with key + !*/ + + protected: + + // restricted functions + map_pair& operator=(const map_pair&) {return *this;} // no assignment operator + + }; + + // destructor does nothing + template + map_pair::~map_pair () {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAP_PAIr_INTERFACE_ + diff --git a/libs/dlib/interfaces/remover.h b/libs/dlib/interfaces/remover.h new file mode 100644 index 0000000..d41c23a --- /dev/null +++ b/libs/dlib/interfaces/remover.h @@ -0,0 +1,220 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_REMOVER_KERNEl_INTERFACE_ +#define DLIB_REMOVER_KERNEl_INTERFACE_ + +#include + + +namespace dlib +{ + + template < + typename T + > + class remover + { + + /*! + REQUIREMENTS ON T + T is swappable by a global swap() and + T must have a default constructor + + POINTERS AND REFERENCES TO INTERNAL DATA + The size() function does not invalidate pointers or + references to internal data. All other functions have no such + guarantee. + + WHAT THIS OBJECT REPRESENTS + This object represents some generalized interface for removing + single items from container classes. + !*/ + + + public: + typedef T type; + + virtual ~remover( + ); + /*! + ensures + - all resources associated with *this have been released. + !*/ + + virtual void remove_any ( + T& item + ) = 0; + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - removes an element from *this and swaps it into item. + - if (*this implements the enumerable interface) then + - #at_start() == true + !*/ + + virtual unsigned long size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + protected: + + // restricted functions + remover& operator=(const remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + class asc_remover : public remover + { + /*! + REQUIREMENTS ON T + T is swappable by a global swap() and + T must have a default constructor and + T must be comparable by compare where compare is a functor compatible with std::less + + WHAT THIS OBJECT REPRESENTS + This object represents the same thing as remover except + that remove_any() will remove elements in ascending order + according to the compare functor. + !*/ + public: + typedef compare compare_type; + + protected: + // restricted functions + asc_remover& operator=(const asc_remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range + > + class pair_remover + { + + /*! + REQUIREMENTS ON domain + domain is swappable by a global swap() and + domain must have a default constructor + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + POINTERS AND REFERENCES TO INTERNAL DATA + The size() function does not invalidate pointers or + references to internal data. All other functions have no such + guarantee. + + WHAT THIS OBJECT REPRESENTS + This object represents some generalized interface for removing + pairs from container classes which enforce some kind of pairing on + the elements that they contain. + !*/ + + public: + typedef domain domain_type; + typedef range range_type; + + virtual ~pair_remover( + ); + /*! + ensures + - all resources associated with *this have been released. + !*/ + + virtual void remove_any ( + domain& d, + range& r + ) = 0; + /*! + requires + - &d != &r (i.e. d and r cannot be the same variable) + - size() != 0 + ensures + - #size() == size() - 1 + - removes an element from the domain of *this and swaps it + into d. + - removes the element in *this's range that is associated + with #d and swaps it into r. + - if (*this implements the enumerable interface) then + - #at_start() == true + !*/ + + virtual unsigned long size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + + protected: + + // restricted functions + pair_remover& operator=(const pair_remover&) {return *this;} // assignment operator + + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename compare + > + class asc_pair_remover : public pair_remover + { + /*! + REQUIREMENTS ON domain + domain is swappable by a global swap() and + domain must have a default constructor and + domain must be comparable by compare where compare is a functor compatible with std::less + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + WHAT THIS OBJECT REPRESENTS + This object represents the same thing as pair_remover except + that remove_any() will remove domain elements in ascending + order according to the compare functor. + !*/ + public: + typedef compare compare_type; + + protected: + // restricted functions + asc_pair_remover& operator=(const asc_pair_remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + // destructor does nothing + template + remover::~remover() {} + + // destructor does nothing + template + pair_remover::~pair_remover() {} + + +// ---------------------------------------------------------------------------------------- + + +} + +#endif // DLIB_REMOVER_KERNEl_INTERFACE_ + diff --git a/libs/dlib/is_kind.h b/libs/dlib/is_kind.h new file mode 100644 index 0000000..e8dcb63 --- /dev/null +++ b/libs/dlib/is_kind.h @@ -0,0 +1,162 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_IS_KINd_H_ +#define DLIB_IS_KINd_H_ + +#include + +namespace dlib +{ + /*! + This file contains a set of templates that enable you to determine if + a given type implements an abstract interface defined in one of the + dlib *_abstract.h files. + !*/ + +// ---------------------------------------------------------------------------------------- + + struct default_is_kind_value { static const bool value = false; }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_graph : public default_is_kind_value + { + /*! + - if (T is an implementation of graph/graph_kernel_abstract.h) then + - is_graph::value == true + - else + - is_graph::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_directed_graph : public default_is_kind_value + { + /*! + - if (T is an implementation of directed_graph/directed_graph_kernel_abstract.h) then + - is_directed_graph::value == true + - else + - is_directed_graph::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_matrix : public default_is_kind_value + { + /*! + - if (T is some kind of matrix expression from the matrix/matrix_exp_abstract.h component) then + - is_matrix::value == true + - else + - is_matrix::value == false + !*/ + + // Don't set the helper to anything. Just let it be void. + ASSERT_ARE_SAME_TYPE(helper,void); + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_array2d : public default_is_kind_value + { + /*! + - if (T is an implementation of array2d/array2d_kernel_abstract.h) then + - is_array2d::value == true + - else + - is_array2d::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_array : public default_is_kind_value + { + /*! + - if (T is an implementation of array/array_kernel_abstract.h) then + - is_array::value == true + - else + - is_array::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_std_vector : public default_is_kind_value + { + /*! + - if (T is an implementation of the standard C++ std::vector object) then + - is_std_vector::value == true + - else + - is_std_vector::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_pair : public default_is_kind_value + { + /*! + - if (T is a std::pair object) then + - is_std_vector::value == true + - else + - is_std_vector::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_rand : public default_is_kind_value + { + /*! + - if (T is an implementation of rand/rand_kernel_abstract.h) then + - is_rand::value == true + - else + - is_rand::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_config_reader : public default_is_kind_value + { + /*! + - if (T is an implementation of config_reader/config_reader_kernel_abstract.h) then + - is_config_reader::value == true + - else + - is_config_reader::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Implementation details +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + struct is_std_vector > { const static bool value = true; }; + template struct is_std_vector { const static bool value = is_std_vector::value; }; + template struct is_std_vector{ const static bool value = is_std_vector::value; }; + template struct is_std_vector { const static bool value = is_std_vector::value; }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_pair > { const static bool value = true; }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_IS_KINd_H_ + diff --git a/libs/dlib/matrix.h b/libs/dlib/matrix.h new file mode 100644 index 0000000..658ea6b --- /dev/null +++ b/libs/dlib/matrix.h @@ -0,0 +1,21 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_HEADER +#define DLIB_MATRIx_HEADER + +#include "matrix/matrix.h" +//#include "matrix/matrix_utilities.h" +//#include "matrix/matrix_subexp.h" +//#include "matrix/matrix_math_functions.h" +//#include "matrix/matrix_assign.h" +//#include "matrix/matrix_la.h" +//#include "matrix/symmetric_matrix_cache.h" +//#include "matrix/matrix_conv.h" +// +//#ifdef DLIB_USE_BLAS +//#include "matrix/matrix_blas_bindings.h" +//#endif + +#endif // DLIB_MATRIx_HEADER + + diff --git a/libs/dlib/matrix/cblas_constants.h b/libs/dlib/matrix/cblas_constants.h new file mode 100644 index 0000000..d60ef76 --- /dev/null +++ b/libs/dlib/matrix/cblas_constants.h @@ -0,0 +1,20 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CBLAS_CONSTAnTS_H__ +#define DLIB_CBLAS_CONSTAnTS_H__ + +namespace dlib +{ + namespace blas_bindings + { + enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; + enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; + enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; + enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; + enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; + + } +} + +#endif // DLIB_CBLAS_CONSTAnTS_H__ + diff --git a/libs/dlib/matrix/lapack/fortran_id.h b/libs/dlib/matrix/lapack/fortran_id.h new file mode 100644 index 0000000..a5cd638 --- /dev/null +++ b/libs/dlib/matrix/lapack/fortran_id.h @@ -0,0 +1,58 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H +#define DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// FORTRAN BINDING STUFF FROM BOOST +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// Copyright (C) 2002, 2003 Si-Lab b.v.b.a., Toon Knapen and Kresimir Fresl + + +// First we need to know what the conventions for linking +// C with Fortran is on this platform/toolset +#if defined(__GNUC__) || defined(__ICC) || defined(__sgi) || defined(__COMO__) || defined(__KCC) +#define DLIB_BIND_FORTRAN_LOWERCASE_UNDERSCORE +#elif defined(__IBMCPP__) || defined(_MSC_VER) +#define DLIB_BIND_FORTRAN_LOWERCASE +#else +#error do not know how to link with fortran for the given platform +#endif + +// Next we define macros to convert our symbols to +// the current convention +#if defined(DLIB_BIND_FORTRAN_LOWERCASE_UNDERSCORE) +#define DLIB_FORTRAN_ID( id ) id##_ +#elif defined(DLIB_BIND_FORTRAN_LOWERCASE) +#define DLIB_FORTRAN_ID( id ) id +#else +#error do not know how to bind to fortran calling convention +#endif + + + +namespace dlib +{ + namespace lapack + { + // stuff from f2c used to define what exactly is an integer in fortran +#if defined(__alpha__) || defined(__sparc64__) || defined(__x86_64__) || defined(__ia64__) + typedef int integer; + typedef unsigned int uinteger; +#else + typedef long int integer; + typedef unsigned long int uinteger; +#endif + + } +} + +#endif // DLIB_BOOST_NUMERIC_BINDINGS_TRAITS_FORTRAN_H + diff --git a/libs/dlib/matrix/lapack/gees.h b/libs/dlib/matrix/lapack/gees.h new file mode 100644 index 0000000..bc68589 --- /dev/null +++ b/libs/dlib/matrix/lapack/gees.h @@ -0,0 +1,264 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_ES_H__ +#define DLIB_LAPACk_ES_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { +#if defined(__alpha__) || defined(__sparc64__) || defined(__x86_64__) || defined(__ia64__) + typedef int logical; +#else + typedef long int logical; +#endif + typedef logical (*L_fp)(...); + + extern "C" + { + void DLIB_FORTRAN_ID(dgees) (char *jobvs, char *sort, L_fp select, integer *n, + double *a, integer *lda, integer *sdim, double *wr, + double *wi, double *vs, integer *ldvs, double *work, + integer *lwork, logical *bwork, integer *info); + + void DLIB_FORTRAN_ID(sgees) (char *jobvs, char *sort, L_fp select, integer *n, + float *a, integer *lda, integer *sdim, float *wr, + float *wi, float *vs, integer *ldvs, float *work, + integer *lwork, logical *bwork, integer *info); + + } + + inline int gees (char jobvs, integer n, + double *a, integer lda, double *wr, + double *wi, double *vs, integer ldvs, double *work, + integer lwork) + { + // No sorting allowed + integer info = 0; + char sort = 'N'; + L_fp fnil = 0; + logical nil = 0; + integer sdim = 0; + DLIB_FORTRAN_ID(dgees)(&jobvs, &sort, fnil, &n, + a, &lda, &sdim, wr, + wi, vs, &ldvs, work, + &lwork, &nil, &info); + return info; + } + + + inline int gees (char jobvs, integer n, + float *a, integer lda, float *wr, + float *wi, float *vs, integer ldvs, float *work, + integer lwork) + { + // No sorting allowed + integer info = 0; + char sort = 'N'; + L_fp fnil = 0; + logical nil = 0; + integer sdim = 0; + DLIB_FORTRAN_ID(sgees)(&jobvs, &sort, fnil, &n, + a, &lda, &sdim, wr, + wi, vs, &ldvs, work, + &lwork, &nil, &info); + return info; + } + + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK driver routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ +/* .. Function Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGEES computes for an N-by-N real nonsymmetric matrix A, the */ +/* eigenvalues, the real Schur form T, and, optionally, the matrix of */ +/* Schur vectors Z. This gives the Schur factorization A = Z*T*(Z**T). */ + +/* Optionally, it also orders the eigenvalues on the diagonal of the */ +/* real Schur form so that selected eigenvalues are at the top left. */ +/* The leading columns of Z then form an orthonormal basis for the */ +/* invariant subspace corresponding to the selected eigenvalues. */ + +/* A matrix is in real Schur form if it is upper quasi-triangular with */ +/* 1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the */ +/* form */ +/* [ a b ] */ +/* [ c a ] */ + +/* where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc). */ + +/* Arguments */ +/* ========= */ + +/* JOBVS (input) CHARACTER*1 */ +/* = 'N': Schur vectors are not computed; */ +/* = 'V': Schur vectors are computed. */ + +/* SORT (input) CHARACTER*1 */ +/* Specifies whether or not to order the eigenvalues on the */ +/* diagonal of the Schur form. */ +/* = 'N': Eigenvalues are not ordered; */ +/* = 'S': Eigenvalues are ordered (see SELECT). */ + +/* SELECT (external procedure) LOGICAL FUNCTION of two DOUBLE PRECISION arguments */ +/* SELECT must be declared EXTERNAL in the calling subroutine. */ +/* If SORT = 'S', SELECT is used to select eigenvalues to sort */ +/* to the top left of the Schur form. */ +/* If SORT = 'N', SELECT is not referenced. */ +/* An eigenvalue WR(j)+sqrt(-1)*WI(j) is selected if */ +/* SELECT(WR(j),WI(j)) is true; i.e., if either one of a complex */ +/* conjugate pair of eigenvalues is selected, then both complex */ +/* eigenvalues are selected. */ +/* Note that a selected complex eigenvalue may no longer */ +/* satisfy SELECT(WR(j),WI(j)) = .TRUE. after ordering, since */ +/* ordering may change the value of complex eigenvalues */ +/* (especially if the eigenvalue is ill-conditioned); in this */ +/* case INFO is set to N+2 (see INFO below). */ + +/* N (input) INTEGER */ +/* The order of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the N-by-N matrix A. */ +/* On exit, A has been overwritten by its real Schur form T. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,N). */ + +/* SDIM (output) INTEGER */ +/* If SORT = 'N', SDIM = 0. */ +/* If SORT = 'S', SDIM = number of eigenvalues (after sorting) */ +/* for which SELECT is true. (Complex conjugate */ +/* pairs for which SELECT is true for either */ +/* eigenvalue count as 2.) */ + +/* WR (output) DOUBLE PRECISION array, dimension (N) */ +/* WI (output) DOUBLE PRECISION array, dimension (N) */ +/* WR and WI contain the real and imaginary parts, */ +/* respectively, of the computed eigenvalues in the same order */ +/* that they appear on the diagonal of the output Schur form T. */ +/* Complex conjugate pairs of eigenvalues will appear */ +/* consecutively with the eigenvalue having the positive */ +/* imaginary part first. */ + +/* VS (output) DOUBLE PRECISION array, dimension (LDVS,N) */ +/* If JOBVS = 'V', VS contains the orthogonal matrix Z of Schur */ +/* vectors. */ +/* If JOBVS = 'N', VS is not referenced. */ + +/* LDVS (input) INTEGER */ +/* The leading dimension of the array VS. LDVS >= 1; if */ +/* JOBVS = 'V', LDVS >= N. */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) contains the optimal LWORK. */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. LWORK >= max(1,3*N). */ +/* For good performance, LWORK must generally be larger. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* BWORK (workspace) LOGICAL array, dimension (N) */ +/* Not referenced if SORT = 'N'. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value. */ +/* > 0: if INFO = i, and i is */ +/* <= N: the QR algorithm failed to compute all the */ +/* eigenvalues; elements 1:ILO-1 and i+1:N of WR and WI */ +/* contain those eigenvalues which have converged; if */ +/* JOBVS = 'V', VS contains the matrix which reduces A */ +/* to its partially converged Schur form. */ +/* = N+1: the eigenvalues could not be reordered because some */ +/* eigenvalues were too close to separate (the problem */ +/* is very ill-conditioned); */ +/* = N+2: after reordering, roundoff changed values of some */ +/* complex eigenvalues so that leading eigenvalues in */ +/* the Schur form no longer satisfy SELECT=.TRUE. This */ +/* could also be caused by underflow due to scaling. */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM, + typename layout + > + int gees ( + const char jobz, + matrix& a, + matrix& wr, + matrix& wi, + matrix& vs + ) + { + matrix work; + + const long n = a.nr(); + + wr.set_size(n,1); + wi.set_size(n,1); + + if (jobz == 'V') + vs.set_size(n,n); + else + vs.set_size(NR4?NR4:1, NC4?NC4:1); + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::gees(jobz, n, + &a(0,0), a.nr(), &wr(0,0), + &wi(0,0), &vs(0,0), vs.nr(), &work_size, + -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual decomposition + info = binding::gees(jobz, n, + &a(0,0), a.nr(), &wr(0,0), + &wi(0,0), &vs(0,0), vs.nr(), &work(0,0), + work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_ES_H__ + diff --git a/libs/dlib/matrix/lapack/geev.h b/libs/dlib/matrix/lapack/geev.h new file mode 100644 index 0000000..9e50186 --- /dev/null +++ b/libs/dlib/matrix/lapack/geev.h @@ -0,0 +1,234 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_GEEV_H__ +#define DLIB_LAPACk_GEEV_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dgeev) (char *jobvl, char *jobvr, integer *n, double * a, + integer *lda, double *wr, double *wi, double *vl, + integer *ldvl, double *vr, integer *ldvr, double *work, + integer *lwork, integer *info); + + void DLIB_FORTRAN_ID(sgeev) (char *jobvl, char *jobvr, integer *n, float * a, + integer *lda, float *wr, float *wi, float *vl, + integer *ldvl, float *vr, integer *ldvr, float *work, + integer *lwork, integer *info); + + } + + inline int geev (char jobvl, char jobvr, integer n, double *a, + integer lda, double *wr, double *wi, double *vl, + integer ldvl, double *vr, integer ldvr, double *work, + integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dgeev)(&jobvl, &jobvr, &n, a, + &lda, wr, wi, vl, + &ldvl, vr, &ldvr, work, + &lwork, &info); + return info; + } + + inline int geev (char jobvl, char jobvr, integer n, float *a, + integer lda, float *wr, float *wi, float *vl, + integer ldvl, float *vr, integer ldvr, float *work, + integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(sgeev)(&jobvl, &jobvr, &n, a, + &lda, wr, wi, vl, + &ldvl, vr, &ldvr, work, + &lwork, &info); + return info; + } + + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK driver routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGEEV computes for an N-by-N real nonsymmetric matrix A, the */ +/* eigenvalues and, optionally, the left and/or right eigenvectors. */ + +/* The right eigenvector v(j) of A satisfies */ +/* A * v(j) = lambda(j) * v(j) */ +/* where lambda(j) is its eigenvalue. */ +/* The left eigenvector u(j) of A satisfies */ +/* u(j)**H * A = lambda(j) * u(j)**H */ +/* where u(j)**H denotes the conjugate transpose of u(j). */ + +/* The computed eigenvectors are normalized to have Euclidean norm */ +/* equal to 1 and largest component real. */ + +/* Arguments */ +/* ========= */ + +/* JOBVL (input) CHARACTER*1 */ +/* = 'N': left eigenvectors of A are not computed; */ +/* = 'V': left eigenvectors of A are computed. */ + +/* JOBVR (input) CHARACTER*1 */ +/* = 'N': right eigenvectors of A are not computed; */ +/* = 'V': right eigenvectors of A are computed. */ + +/* N (input) INTEGER */ +/* The order of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the N-by-N matrix A. */ +/* On exit, A has been overwritten. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,N). */ + +/* WR (output) DOUBLE PRECISION array, dimension (N) */ +/* WI (output) DOUBLE PRECISION array, dimension (N) */ +/* WR and WI contain the real and imaginary parts, */ +/* respectively, of the computed eigenvalues. Complex */ +/* conjugate pairs of eigenvalues appear consecutively */ +/* with the eigenvalue having the positive imaginary part */ +/* first. */ + +/* VL (output) DOUBLE PRECISION array, dimension (LDVL,N) */ +/* If JOBVL = 'V', the left eigenvectors u(j) are stored one */ +/* after another in the columns of VL, in the same order */ +/* as their eigenvalues. */ +/* If JOBVL = 'N', VL is not referenced. */ +/* If the j-th eigenvalue is real, then u(j) = VL(:,j), */ +/* the j-th column of VL. */ +/* If the j-th and (j+1)-st eigenvalues form a complex */ +/* conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and */ +/* u(j+1) = VL(:,j) - i*VL(:,j+1). */ + +/* LDVL (input) INTEGER */ +/* The leading dimension of the array VL. LDVL >= 1; if */ +/* JOBVL = 'V', LDVL >= N. */ + +/* VR (output) DOUBLE PRECISION array, dimension (LDVR,N) */ +/* If JOBVR = 'V', the right eigenvectors v(j) are stored one */ +/* after another in the columns of VR, in the same order */ +/* as their eigenvalues. */ +/* If JOBVR = 'N', VR is not referenced. */ +/* If the j-th eigenvalue is real, then v(j) = VR(:,j), */ +/* the j-th column of VR. */ +/* If the j-th and (j+1)-st eigenvalues form a complex */ +/* conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and */ +/* v(j+1) = VR(:,j) - i*VR(:,j+1). */ + +/* LDVR (input) INTEGER */ +/* The leading dimension of the array VR. LDVR >= 1; if */ +/* JOBVR = 'V', LDVR >= N. */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. LWORK >= max(1,3*N), and */ +/* if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N. For good */ +/* performance, LWORK must generally be larger. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value. */ +/* > 0: if INFO = i, the QR algorithm failed to compute all the */ +/* eigenvalues, and no eigenvectors have been computed; */ +/* elements i+1:N of WR and WI contain eigenvalues which */ +/* have converged. */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, long NR5, + long NC1, long NC2, long NC3, long NC4, long NC5, + typename MM, + typename layout + > + int geev ( + const char jobvl, + const char jobvr, + matrix& a, + matrix& wr, + matrix& wi, + matrix& vl, + matrix& vr + ) + { + matrix work; + + const long n = a.nr(); + + wr.set_size(n,1); + wi.set_size(n,1); + + if (jobvl == 'V') + vl.set_size(n,n); + else + vl.set_size(NR4?NR4:1, NC4?NC4:1); + + if (jobvr == 'V') + vr.set_size(n,n); + else + vr.set_size(NR5?NR5:1, NC5?NC5:1); + + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::geev(jobvl, jobvr, n, &a(0,0), + a.nr(), &wr(0,0), &wi(0,0), &vl(0,0), + vl.nr(), &vr(0,0), vr.nr(), &work_size, + -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual decomposition + info = binding::geev(jobvl, jobvr, n, &a(0,0), + a.nr(), &wr(0,0), &wi(0,0), &vl(0,0), + vl.nr(), &vr(0,0), vr.nr(), &work(0,0), + work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_GEEV_H__ + + diff --git a/libs/dlib/matrix/lapack/geqrf.h b/libs/dlib/matrix/lapack/geqrf.h new file mode 100644 index 0000000..d8b9265 --- /dev/null +++ b/libs/dlib/matrix/lapack/geqrf.h @@ -0,0 +1,168 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_GEQRF_H__ +#define DLIB_LAPACk_GEQRF_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dgeqrf) (integer *m, integer *n, double *a, integer * + lda, double *tau, double *work, integer *lwork, + integer *info); + + void DLIB_FORTRAN_ID(sgeqrf) (integer *m, integer *n, float *a, integer * + lda, float *tau, float *work, integer *lwork, + integer *info); + } + + inline int geqrf (integer m, integer n, double *a, integer lda, + double *tau, double *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dgeqrf)(&m, &n, a, &lda, + tau, work, &lwork, &info); + return info; + } + + inline int geqrf (integer m, integer n, float *a, integer lda, + float *tau, float *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(sgeqrf)(&m, &n, a, &lda, + tau, work, &lwork, &info); + return info; + } + + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGEQRF computes a QR factorization of a real M-by-N matrix A: */ +/* A = Q * R. */ + +/* Arguments */ +/* ========= */ + +/* M (input) INTEGER */ +/* The number of rows of the matrix A. M >= 0. */ + +/* N (input) INTEGER */ +/* The number of columns of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the M-by-N matrix A. */ +/* On exit, the elements on and above the diagonal of the array */ +/* contain the min(M,N)-by-N upper trapezoidal matrix R (R is */ +/* upper triangular if m >= n); the elements below the diagonal, */ +/* with the array TAU, represent the orthogonal matrix Q as a */ +/* product of min(m,n) elementary reflectors (see Further */ +/* Details). */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,M). */ + +/* TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) */ +/* The scalar factors of the elementary reflectors (see Further */ +/* Details). */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. LWORK >= max(1,N). */ +/* For optimum performance LWORK >= N*NB, where NB is */ +/* the optimal blocksize. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value */ + +/* Further Details */ +/* =============== */ + +/* The matrix Q is represented as a product of elementary reflectors */ + +/* Q = H(1) H(2) . . . H(k), where k = min(m,n). */ + +/* Each H(i) has the form */ + +/* H(i) = I - tau * v * v' */ + +/* where tau is a real scalar, and v is a real vector with */ +/* v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i), */ +/* and tau in TAU(i). */ + + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + int geqrf ( + matrix& a, + matrix& tau + ) + { + matrix work; + + tau.set_size(std::min(a.nr(), a.nc()), 1); + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::geqrf(a.nr(), a.nc(), &a(0,0), a.nr(), + &tau(0,0), &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual decomposition + info = binding::geqrf(a.nr(), a.nc(), &a(0,0), a.nr(), + &tau(0,0), &work(0,0), work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_GEQRF_H__ + + + diff --git a/libs/dlib/matrix/lapack/gesdd.h b/libs/dlib/matrix/lapack/gesdd.h new file mode 100644 index 0000000..1055979 --- /dev/null +++ b/libs/dlib/matrix/lapack/gesdd.h @@ -0,0 +1,364 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_SDD_H__ +#define DLIB_LAPACk_SDD_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dgesdd) (char const* jobz, + const integer* m, const integer* n, double* a, const integer* lda, + double* s, double* u, const integer* ldu, + double* vt, const integer* ldvt, + double* work, const integer* lwork, integer* iwork, integer* info); + + void DLIB_FORTRAN_ID(sgesdd) (char const* jobz, + const integer* m, const integer* n, float* a, const integer* lda, + float* s, float* u, const integer* ldu, + float* vt, const integer* ldvt, + float* work, const integer* lwork, integer* iwork, integer* info); + + } + + inline integer gesdd (const char jobz, + const integer m, const integer n, double* a, const integer lda, + double* s, double* u, const integer ldu, + double* vt, const integer ldvt, + double* work, const integer lwork, integer* iwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dgesdd)(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info); + return info; + } + + inline integer gesdd (const char jobz, + const integer m, const integer n, float* a, const integer lda, + float* s, float* u, const integer ldu, + float* vt, const integer ldvt, + float* work, const integer lwork, integer* iwork) + { + integer info = 0; + DLIB_FORTRAN_ID(sgesdd)(&jobz, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, iwork, &info); + return info; + } + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK driver routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGESDD computes the singular value decomposition (SVD) of a real */ +/* M-by-N matrix A, optionally computing the left and right singular */ +/* vectors. If singular vectors are desired, it uses a */ +/* divide-and-conquer algorithm. */ + +/* The SVD is written */ + +/* A = U * SIGMA * transpose(V) */ + +/* where SIGMA is an M-by-N matrix which is zero except for its */ +/* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and */ +/* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA */ +/* are the singular values of A; they are real and non-negative, and */ +/* are returned in descending order. The first min(m,n) columns of */ +/* U and V are the left and right singular vectors of A. */ + +/* Note that the routine returns VT = V**T, not V. */ + +/* The divide and conquer algorithm makes very mild assumptions about */ +/* floating point arithmetic. It will work on machines with a guard */ +/* digit in add/subtract, or on those binary machines without guard */ +/* digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or */ +/* Cray-2. It could conceivably fail on hexadecimal or decimal machines */ +/* without guard digits, but we know of none. */ + +/* Arguments */ +/* ========= */ + +/* JOBZ (input) CHARACTER*1 */ +/* Specifies options for computing all or part of the matrix U: */ +/* = 'A': all M columns of U and all N rows of V**T are */ +/* returned in the arrays U and VT; */ +/* = 'S': the first min(M,N) columns of U and the first */ +/* min(M,N) rows of V**T are returned in the arrays U */ +/* and VT; */ +/* = 'O': If M >= N, the first N columns of U are overwritten */ +/* on the array A and all rows of V**T are returned in */ +/* the array VT; */ +/* otherwise, all columns of U are returned in the */ +/* array U and the first M rows of V**T are overwritten */ +/* in the array A; */ +/* = 'N': no columns of U or rows of V**T are computed. */ + +/* M (input) INTEGER */ +/* The number of rows of the input matrix A. M >= 0. */ + +/* N (input) INTEGER */ +/* The number of columns of the input matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the M-by-N matrix A. */ +/* On exit, */ +/* if JOBZ = 'O', A is overwritten with the first N columns */ +/* of U (the left singular vectors, stored */ +/* columnwise) if M >= N; */ +/* A is overwritten with the first M rows */ +/* of V**T (the right singular vectors, stored */ +/* rowwise) otherwise. */ +/* if JOBZ .ne. 'O', the contents of A are destroyed. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,M). */ + +/* S (output) DOUBLE PRECISION array, dimension (min(M,N)) */ +/* The singular values of A, sorted so that S(i) >= S(i+1). */ + +/* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL) */ +/* UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N; */ +/* UCOL = min(M,N) if JOBZ = 'S'. */ +/* If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M */ +/* orthogonal matrix U; */ +/* if JOBZ = 'S', U contains the first min(M,N) columns of U */ +/* (the left singular vectors, stored columnwise); */ +/* if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced. */ + +/* LDU (input) INTEGER */ +/* The leading dimension of the array U. LDU >= 1; if */ +/* JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M. */ + +/* VT (output) DOUBLE PRECISION array, dimension (LDVT,N) */ +/* If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the */ +/* N-by-N orthogonal matrix V**T; */ +/* if JOBZ = 'S', VT contains the first min(M,N) rows of */ +/* V**T (the right singular vectors, stored rowwise); */ +/* if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced. */ + +/* LDVT (input) INTEGER */ +/* The leading dimension of the array VT. LDVT >= 1; if */ +/* JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N; */ +/* if JOBZ = 'S', LDVT >= min(M,N). */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK; */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. LWORK >= 1. */ +/* If JOBZ = 'N', */ +/* LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)). */ +/* If JOBZ = 'O', */ +/* LWORK >= 3*min(M,N)*min(M,N) + */ +/* max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)). */ +/* If JOBZ = 'S' or 'A' */ +/* LWORK >= 3*min(M,N)*min(M,N) + */ +/* max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)). */ +/* For good performance, LWORK should generally be larger. */ +/* If LWORK = -1 but other input arguments are legal, WORK(1) */ +/* returns the optimal LWORK. */ + +/* IWORK (workspace) INTEGER array, dimension (8*min(M,N)) */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit. */ +/* < 0: if INFO = -i, the i-th argument had an illegal value. */ +/* > 0: DBDSDC did not converge, updating process failed. */ + +/* Further Details */ +/* =============== */ + +/* Based on contributions by */ +/* Ming Gu and Huan Ren, Computer Science Division, University of */ +/* California at Berkeley, USA */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int gesdd ( + const char jobz, + matrix& a, + matrix& s, + matrix& u, + matrix& vt + ) + { + matrix work; + matrix iwork; + + const long m = a.nr(); + const long n = a.nc(); + s.set_size(std::min(m,n), 1); + + // make sure the iwork memory block is big enough + if (iwork.size() < 8*std::min(m,n)) + iwork.set_size(8*std::min(m,n), 1); + + if (jobz == 'A') + { + u.set_size(m,m); + vt.set_size(n,n); + } + else if (jobz == 'S') + { + u.set_size(m, std::min(m,n)); + vt.set_size(std::min(m,n), n); + } + else if (jobz == 'O') + { + DLIB_CASSERT(false, "jobz == 'O' not supported"); + } + else + { + u.set_size(NR3?NR3:1, NC3?NC3:1); + vt.set_size(NR4?NR4:1, NC4?NC4:1); + } + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::gesdd(jobz, a.nr(), a.nc(), &a(0,0), a.nr(), + &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), + &work_size, -1, &iwork(0,0)); + + if (info != 0) + return info; + + // There is a bug in an older version of LAPACK in Debian etch + // that causes the gesdd to return the wrong value for work_size + // when jobz == 'N'. So verify the value of work_size. + if (jobz == 'N') + { + using std::min; + using std::max; + const T min_work_size = 3*min(m,n) + max(max(m,n),7*min(m,n)); + if (work_size < min_work_size) + work_size = min_work_size; + } + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual SVD + info = binding::gesdd(jobz, a.nr(), a.nc(), &a(0,0), a.nr(), + &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), + &work(0,0), work.size(), &iwork(0,0)); + + return info; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int gesdd ( + const char jobz, + matrix& a, + matrix& s, + matrix& u_, + matrix& vt_ + ) + { + matrix work; + matrix iwork; + + // Row major order matrices are transposed from LAPACK's point of view. + matrix& u = vt_; + matrix& vt = u_; + + + const long m = a.nc(); + const long n = a.nr(); + s.set_size(std::min(m,n), 1); + + // make sure the iwork memory block is big enough + if (iwork.size() < 8*std::min(m,n)) + iwork.set_size(8*std::min(m,n), 1); + + if (jobz == 'A') + { + u.set_size(m,m); + vt.set_size(n,n); + } + else if (jobz == 'S') + { + u.set_size(std::min(m,n), m); + vt.set_size(n, std::min(m,n)); + } + else if (jobz == 'O') + { + DLIB_CASSERT(false, "jobz == 'O' not supported"); + } + else + { + u.set_size(NR4?NR4:1, NC4?NC4:1); + vt.set_size(NR3?NR3:1, NC3?NC3:1); + } + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::gesdd(jobz, m, n, &a(0,0), a.nc(), + &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), + &work_size, -1, &iwork(0,0)); + + if (info != 0) + return info; + + // There is a bug in an older version of LAPACK in Debian etch + // that causes the gesdd to return the wrong value for work_size + // when jobz == 'N'. So verify the value of work_size. + if (jobz == 'N') + { + using std::min; + using std::max; + const T min_work_size = 3*min(m,n) + max(max(m,n),7*min(m,n)); + if (work_size < min_work_size) + work_size = min_work_size; + } + + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual SVD + info = binding::gesdd(jobz, m, n, &a(0,0), a.nc(), + &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), + &work(0,0), work.size(), &iwork(0,0)); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_SDD_H__ + + diff --git a/libs/dlib/matrix/lapack/gesvd.h b/libs/dlib/matrix/lapack/gesvd.h new file mode 100644 index 0000000..dbcb04c --- /dev/null +++ b/libs/dlib/matrix/lapack/gesvd.h @@ -0,0 +1,323 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_SVD_H__ +#define DLIB_LAPACk_SVD_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dgesvd) (const char* jobu, const char* jobvt, + const integer* m, const integer* n, double* a, const integer* lda, + double* s, double* u, const integer* ldu, + double* vt, const integer* ldvt, + double* work, const integer* lwork, integer* info); + + void DLIB_FORTRAN_ID(sgesvd) (const char* jobu, const char* jobvt, + const integer* m, const integer* n, float* a, const integer* lda, + float* s, float* u, const integer* ldu, + float* vt, const integer* ldvt, + float* work, const integer* lwork, integer* info); + + } + + inline integer gesvd (const char jobu, const char jobvt, + const integer m, const integer n, double* a, const integer lda, + double* s, double* u, const integer ldu, + double* vt, const integer ldvt, + double* work, const integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dgesvd)(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info); + return info; + } + + inline integer gesvd (const char jobu, const char jobvt, + const integer m, const integer n, float* a, const integer lda, + float* s, float* u, const integer ldu, + float* vt, const integer ldvt, + float* work, const integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(sgesvd)(&jobu, &jobvt, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info); + return info; + } + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK driver routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGESVD computes the singular value decomposition (SVD) of a real */ +/* M-by-N matrix A, optionally computing the left and/or right singular */ +/* vectors. The SVD is written */ + +/* A = U * SIGMA * transpose(V) */ + +/* where SIGMA is an M-by-N matrix which is zero except for its */ +/* min(m,n) diagonal elements, U is an M-by-M orthogonal matrix, and */ +/* V is an N-by-N orthogonal matrix. The diagonal elements of SIGMA */ +/* are the singular values of A; they are real and non-negative, and */ +/* are returned in descending order. The first min(m,n) columns of */ +/* U and V are the left and right singular vectors of A. */ + +/* Note that the routine returns V**T, not V. */ + +/* Arguments */ +/* ========= */ + +/* JOBU (input) CHARACTER*1 */ +/* Specifies options for computing all or part of the matrix U: */ +/* = 'A': all M columns of U are returned in array U: */ +/* = 'S': the first min(m,n) columns of U (the left singular */ +/* vectors) are returned in the array U; */ +/* = 'O': the first min(m,n) columns of U (the left singular */ +/* vectors) are overwritten on the array A; */ +/* = 'N': no columns of U (no left singular vectors) are */ +/* computed. */ + +/* JOBVT (input) CHARACTER*1 */ +/* Specifies options for computing all or part of the matrix */ +/* V**T: */ +/* = 'A': all N rows of V**T are returned in the array VT; */ +/* = 'S': the first min(m,n) rows of V**T (the right singular */ +/* vectors) are returned in the array VT; */ +/* = 'O': the first min(m,n) rows of V**T (the right singular */ +/* vectors) are overwritten on the array A; */ +/* = 'N': no rows of V**T (no right singular vectors) are */ +/* computed. */ + +/* JOBVT and JOBU cannot both be 'O'. */ + +/* M (input) INTEGER */ +/* The number of rows of the input matrix A. M >= 0. */ + +/* N (input) INTEGER */ +/* The number of columns of the input matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the M-by-N matrix A. */ +/* On exit, */ +/* if JOBU = 'O', A is overwritten with the first min(m,n) */ +/* columns of U (the left singular vectors, */ +/* stored columnwise); */ +/* if JOBVT = 'O', A is overwritten with the first min(m,n) */ +/* rows of V**T (the right singular vectors, */ +/* stored rowwise); */ +/* if JOBU .ne. 'O' and JOBVT .ne. 'O', the contents of A */ +/* are destroyed. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,M). */ + +/* S (output) DOUBLE PRECISION array, dimension (min(M,N)) */ +/* The singular values of A, sorted so that S(i) >= S(i+1). */ + +/* U (output) DOUBLE PRECISION array, dimension (LDU,UCOL) */ +/* (LDU,M) if JOBU = 'A' or (LDU,min(M,N)) if JOBU = 'S'. */ +/* If JOBU = 'A', U contains the M-by-M orthogonal matrix U; */ +/* if JOBU = 'S', U contains the first min(m,n) columns of U */ +/* (the left singular vectors, stored columnwise); */ +/* if JOBU = 'N' or 'O', U is not referenced. */ + +/* LDU (input) INTEGER */ +/* The leading dimension of the array U. LDU >= 1; if */ +/* JOBU = 'S' or 'A', LDU >= M. */ + +/* VT (output) DOUBLE PRECISION array, dimension (LDVT,N) */ +/* If JOBVT = 'A', VT contains the N-by-N orthogonal matrix */ +/* V**T; */ +/* if JOBVT = 'S', VT contains the first min(m,n) rows of */ +/* V**T (the right singular vectors, stored rowwise); */ +/* if JOBVT = 'N' or 'O', VT is not referenced. */ + +/* LDVT (input) INTEGER */ +/* The leading dimension of the array VT. LDVT >= 1; if */ +/* JOBVT = 'A', LDVT >= N; if JOBVT = 'S', LDVT >= min(M,N). */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK; */ +/* if INFO > 0, WORK(2:MIN(M,N)) contains the unconverged */ +/* superdiagonal elements of an upper bidiagonal matrix B */ +/* whose diagonal is in S (not necessarily sorted). B */ +/* satisfies A = U * B * VT, so it has the same singular values */ +/* as A, and singular vectors related by U and VT. */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. */ +/* LWORK >= MAX(1,3*MIN(M,N)+MAX(M,N),5*MIN(M,N)). */ +/* For good performance, LWORK should generally be larger. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit. */ +/* < 0: if INFO = -i, the i-th argument had an illegal value. */ +/* > 0: if DBDSQR did not converge, INFO specifies how many */ +/* superdiagonals of an intermediate bidiagonal form B */ +/* did not converge to zero. See the description of WORK */ +/* above for details. */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int gesvd ( + const char jobu, + const char jobvt, + matrix& a, + matrix& s, + matrix& u, + matrix& vt + ) + { + matrix work; + + const long m = a.nr(); + const long n = a.nc(); + s.set_size(std::min(m,n), 1); + + if (jobu == 'A') + u.set_size(m,m); + else if (jobu == 'S') + u.set_size(m, std::min(m,n)); + else + u.set_size(NR3?NR3:1, NC3?NC3:1); + + if (jobvt == 'A') + vt.set_size(n,n); + else if (jobvt == 'S') + vt.set_size(std::min(m,n), n); + else + vt.set_size(NR4?NR4:1, NC4?NC4:1); + + + if (jobu == 'O' || jobvt == 'O') + { + DLIB_CASSERT(false, "job == 'O' not supported"); + } + + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::gesvd(jobu, jobvt, a.nr(), a.nc(), &a(0,0), a.nr(), + &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), + &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual SVD + info = binding::gesvd(jobu, jobvt, a.nr(), a.nc(), &a(0,0), a.nr(), + &s(0,0), &u(0,0), u.nr(), &vt(0,0), vt.nr(), + &work(0,0), work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int gesvd ( + char jobu, + char jobvt, + matrix& a, + matrix& s, + matrix& u_, + matrix& vt_ + ) + { + matrix work; + + // Row major order matrices are transposed from LAPACK's point of view. + matrix& u = vt_; + matrix& vt = u_; + std::swap(jobu, jobvt); + + const long m = a.nc(); + const long n = a.nr(); + s.set_size(std::min(m,n), 1); + + if (jobu == 'A') + u.set_size(m,m); + else if (jobu == 'S') + u.set_size(std::min(m,n), m); + else + u.set_size(NR4?NR4:1, NC4?NC4:1); + + if (jobvt == 'A') + vt.set_size(n,n); + else if (jobvt == 'S') + vt.set_size(n, std::min(m,n)); + else + vt.set_size(NR3?NR3:1, NC3?NC3:1); + + if (jobu == 'O' || jobvt == 'O') + { + DLIB_CASSERT(false, "job == 'O' not supported"); + } + + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::gesvd(jobu, jobvt, m, n, &a(0,0), a.nc(), + &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), + &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual SVD + info = binding::gesvd(jobu, jobvt, m, n, &a(0,0), a.nc(), + &s(0,0), &u(0,0), u.nc(), &vt(0,0), vt.nc(), + &work(0,0), work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_SVD_H__ + diff --git a/libs/dlib/matrix/lapack/getrf.h b/libs/dlib/matrix/lapack/getrf.h new file mode 100644 index 0000000..c81d698 --- /dev/null +++ b/libs/dlib/matrix/lapack/getrf.h @@ -0,0 +1,132 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_GETRF_H__ +#define DLIB_LAPACk_GETRF_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dgetrf) (integer* m, integer *n, double *a, + integer* lda, integer *ipiv, integer *info); + + void DLIB_FORTRAN_ID(sgetrf) (integer* m, integer *n, float *a, + integer* lda, integer *ipiv, integer *info); + + } + + inline int getrf (integer m, integer n, double *a, + integer lda, integer *ipiv) + { + integer info = 0; + DLIB_FORTRAN_ID(dgetrf)(&m, &n, a, &lda, ipiv, &info); + return info; + } + + inline int getrf (integer m, integer n, float *a, + integer lda, integer *ipiv) + { + integer info = 0; + DLIB_FORTRAN_ID(sgetrf)(&m, &n, a, &lda, ipiv, &info); + return info; + } + + + } + + // ------------------------------------------------------------------------------------ + + +/* -- LAPACK routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DGETRF computes an LU factorization of a general M-by-N matrix A */ +/* using partial pivoting with row interchanges. */ + +/* The factorization has the form */ +/* A = P * L * U */ +/* where P is a permutation matrix, L is lower triangular with unit */ +/* diagonal elements (lower trapezoidal if m > n), and U is upper */ +/* triangular (upper trapezoidal if m < n). */ + +/* This is the right-looking Level 3 BLAS version of the algorithm. */ + +/* Arguments */ +/* ========= */ + +/* M (input) INTEGER */ +/* The number of rows of the matrix A. M >= 0. */ + +/* N (input) INTEGER */ +/* The number of columns of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the M-by-N matrix to be factored. */ +/* On exit, the factors L and U from the factorization */ +/* A = P*L*U; the unit diagonal elements of L are not stored. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,M). */ + +/* IPIV (output) INTEGER array, dimension (min(M,N)) */ +/* The pivot indices; for 1 <= i <= min(M,N), row i of the */ +/* matrix was interchanged with row IPIV(i). */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value */ +/* > 0: if INFO = i, U(i,i) is exactly zero. The factorization */ +/* has been completed, but the factor U is exactly */ +/* singular, and division by zero will occur if it is used */ +/* to solve a system of equations. */ + + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM, + typename layout + > + int getrf ( + matrix& a, + matrix& ipiv + ) + { + const long m = a.nr(); + const long n = a.nc(); + + ipiv.set_size(std::min(m,n), 1); + + // compute the actual decomposition + return binding::getrf(m, n, &a(0,0), a.nr(), &ipiv(0,0)); + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_GETRF_H__ + diff --git a/libs/dlib/matrix/lapack/ormqr.h b/libs/dlib/matrix/lapack/ormqr.h new file mode 100644 index 0000000..8faa0a2 --- /dev/null +++ b/libs/dlib/matrix/lapack/ormqr.h @@ -0,0 +1,199 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_ORMQR_H__ +#define DLIB_LAPACk_ORMQR_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dormqr) (char *side, char *trans, integer *m, integer *n, + integer *k, const double *a, integer *lda, const double *tau, + double * c__, integer *ldc, double *work, integer *lwork, + integer *info); + + void DLIB_FORTRAN_ID(sormqr) (char *side, char *trans, integer *m, integer *n, + integer *k, const float *a, integer *lda, const float *tau, + float * c__, integer *ldc, float *work, integer *lwork, + integer *info); + + } + + inline int ormqr (char side, char trans, integer m, integer n, + integer k, const double *a, integer lda, const double *tau, + double *c__, integer ldc, double *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dormqr)(&side, &trans, &m, &n, + &k, a, &lda, tau, + c__, &ldc, work, &lwork, &info); + return info; + } + + inline int ormqr (char side, char trans, integer m, integer n, + integer k, const float *a, integer lda, const float *tau, + float *c__, integer ldc, float *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(sormqr)(&side, &trans, &m, &n, + &k, a, &lda, tau, + c__, &ldc, work, &lwork, &info); + return info; + } + + + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DORMQR overwrites the general real M-by-N matrix C with */ + +/* SIDE = 'L' SIDE = 'R' */ +/* TRANS = 'N': Q * C C * Q */ +/* TRANS = 'T': Q**T * C C * Q**T */ + +/* where Q is a real orthogonal matrix defined as the product of k */ +/* elementary reflectors */ + +/* Q = H(1) H(2) . . . H(k) */ + +/* as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N */ +/* if SIDE = 'R'. */ + +/* Arguments */ +/* ========= */ + +/* SIDE (input) CHARACTER*1 */ +/* = 'L': apply Q or Q**T from the Left; */ +/* = 'R': apply Q or Q**T from the Right. */ + +/* TRANS (input) CHARACTER*1 */ +/* = 'N': No transpose, apply Q; */ +/* = 'T': Transpose, apply Q**T. */ + +/* M (input) INTEGER */ +/* The number of rows of the matrix C. M >= 0. */ + +/* N (input) INTEGER */ +/* The number of columns of the matrix C. N >= 0. */ + +/* K (input) INTEGER */ +/* The number of elementary reflectors whose product defines */ +/* the matrix Q. */ +/* If SIDE = 'L', M >= K >= 0; */ +/* if SIDE = 'R', N >= K >= 0. */ + +/* A (input) DOUBLE PRECISION array, dimension (LDA,K) */ +/* The i-th column must contain the vector which defines the */ +/* elementary reflector H(i), for i = 1,2,...,k, as returned by */ +/* DGEQRF in the first k columns of its array argument A. */ +/* A is modified by the routine but restored on exit. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. */ +/* If SIDE = 'L', LDA >= max(1,M); */ +/* if SIDE = 'R', LDA >= max(1,N). */ + +/* TAU (input) DOUBLE PRECISION array, dimension (K) */ +/* TAU(i) must contain the scalar factor of the elementary */ +/* reflector H(i), as returned by DGEQRF. */ + +/* C (input/output) DOUBLE PRECISION array, dimension (LDC,N) */ +/* On entry, the M-by-N matrix C. */ +/* On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q. */ + +/* LDC (input) INTEGER */ +/* The leading dimension of the array C. LDC >= max(1,M). */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ + +/* LWORK (input) INTEGER */ +/* The dimension of the array WORK. */ +/* If SIDE = 'L', LWORK >= max(1,N); */ +/* if SIDE = 'R', LWORK >= max(1,M). */ +/* For optimum performance LWORK >= N*NB if SIDE = 'L', and */ +/* LWORK >= M*NB if SIDE = 'R', where NB is the optimal */ +/* blocksize. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, + long NC1, long NC2, long NC3, + typename MM + > + int ormqr ( + char side, + char trans, + const matrix& a, + const matrix& tau, + matrix& c + ) + { + const long m = c.nr(); + const long n = c.nc(); + const long k = a.nc(); + + matrix work; + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::ormqr(side, trans, m, n, + k, &a(0,0), a.nr(), &tau(0,0), + &c(0,0), c.nr(), &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual result + info = binding::ormqr(side, trans, m, n, + k, &a(0,0), a.nr(), &tau(0,0), + &c(0,0), c.nr(), &work(0,0), work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_ORMQR_H__ + diff --git a/libs/dlib/matrix/lapack/potrf.h b/libs/dlib/matrix/lapack/potrf.h new file mode 100644 index 0000000..7afbd18 --- /dev/null +++ b/libs/dlib/matrix/lapack/potrf.h @@ -0,0 +1,174 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_POTRF_H__ +#define DLIB_LAPACk_POTRF_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dpotrf) (char *uplo, integer *n, double *a, + integer* lda, integer *info); + + void DLIB_FORTRAN_ID(spotrf) (char *uplo, integer *n, float *a, + integer* lda, integer *info); + + } + + inline int potrf (char uplo, integer n, double *a, integer lda) + { + integer info = 0; + DLIB_FORTRAN_ID(dpotrf)(&uplo, &n, a, &lda, &info); + return info; + } + + inline int potrf (char uplo, integer n, float *a, integer lda) + { + integer info = 0; + DLIB_FORTRAN_ID(spotrf)(&uplo, &n, a, &lda, &info); + return info; + } + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DPOTRF computes the Cholesky factorization of a real symmetric */ +/* positive definite matrix A. */ + +/* The factorization has the form */ +/* A = U**T * U, if UPLO = 'U', or */ +/* A = L * L**T, if UPLO = 'L', */ +/* where U is an upper triangular matrix and L is lower triangular. */ + +/* This is the block version of the algorithm, calling Level 3 BLAS. */ + +/* Arguments */ +/* ========= */ + +/* UPLO (input) CHARACTER*1 */ +/* = 'U': Upper triangle of A is stored; */ +/* = 'L': Lower triangle of A is stored. */ + +/* N (input) INTEGER */ +/* The order of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA,N) */ +/* On entry, the symmetric matrix A. If UPLO = 'U', the leading */ +/* N-by-N upper triangular part of A contains the upper */ +/* triangular part of the matrix A, and the strictly lower */ +/* triangular part of A is not referenced. If UPLO = 'L', the */ +/* leading N-by-N lower triangular part of A contains the lower */ +/* triangular part of the matrix A, and the strictly upper */ +/* triangular part of A is not referenced. */ + +/* On exit, if INFO = 0, the factor U or L from the Cholesky */ +/* factorization A = U**T*U or A = L*L**T. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,N). */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value */ +/* > 0: if INFO = i, the leading minor of order i is not */ +/* positive definite, and the factorization could not be */ +/* completed. */ + + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, + long NC1, + typename MM + > + int potrf ( + char uplo, + matrix& a + ) + { + // compute the actual decomposition + int info = binding::potrf(uplo, a.nr(), &a(0,0), a.nr()); + + // If it fails part way though the factorization then make sure + // the end of the matrix gets properly initialized with zeros. + if (info > 0) + { + if (uplo == 'L') + set_colm(a, range(info-1, a.nc()-1)) = 0; + else + set_rowm(a, range(info-1, a.nr()-1)) = 0; + } + + return info; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, + long NC1, + typename MM + > + int potrf ( + char uplo, + matrix& a + ) + { + // since we are working on a row major order matrix we need to ask + // LAPACK for the transpose of whatever the user asked for. + + if (uplo == 'L') + uplo = 'U'; + else + uplo = 'L'; + + // compute the actual decomposition + int info = binding::potrf(uplo, a.nr(), &a(0,0), a.nr()); + + // If it fails part way though the factorization then make sure + // the end of the matrix gets properly initialized with zeros. + if (info > 0) + { + if (uplo == 'U') + set_colm(a, range(info-1, a.nc()-1)) = 0; + else + set_rowm(a, range(info-1, a.nr()-1)) = 0; + } + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_POTRF_H__ + + diff --git a/libs/dlib/matrix/lapack/syev.h b/libs/dlib/matrix/lapack/syev.h new file mode 100644 index 0000000..103dc66 --- /dev/null +++ b/libs/dlib/matrix/lapack/syev.h @@ -0,0 +1,218 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_EV_H__ +#define DLIB_LAPACk_EV_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dsyev) (char *jobz, char *uplo, integer *n, double *a, + integer *lda, double *w, double *work, integer *lwork, + integer *info); + + void DLIB_FORTRAN_ID(ssyev) (char *jobz, char *uplo, integer *n, float *a, + integer *lda, float *w, float *work, integer *lwork, + integer *info); + + } + + inline int syev (char jobz, char uplo, integer n, double *a, + integer lda, double *w, double *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dsyev)(&jobz, &uplo, &n, a, + &lda, w, work, &lwork, &info); + return info; + } + + inline int syev (char jobz, char uplo, integer n, float *a, + integer lda, float *w, float *work, integer lwork) + { + integer info = 0; + DLIB_FORTRAN_ID(ssyev)(&jobz, &uplo, &n, a, + &lda, w, work, &lwork, &info); + return info; + } + + + } + + // ------------------------------------------------------------------------------------ + +/* -- LAPACK driver routine (version 3.1) -- */ +/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ +/* November 2006 */ + +/* .. Scalar Arguments .. */ +/* .. */ +/* .. Array Arguments .. */ +/* .. */ + +/* Purpose */ +/* ======= */ + +/* DSYEV computes all eigenvalues and, optionally, eigenvectors of a */ +/* real symmetric matrix A. */ + +/* Arguments */ +/* ========= */ + +/* JOBZ (input) CHARACTER*1 */ +/* = 'N': Compute eigenvalues only; */ +/* = 'V': Compute eigenvalues and eigenvectors. */ + +/* UPLO (input) CHARACTER*1 */ +/* = 'U': Upper triangle of A is stored; */ +/* = 'L': Lower triangle of A is stored. */ + +/* N (input) INTEGER */ +/* The order of the matrix A. N >= 0. */ + +/* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) */ +/* On entry, the symmetric matrix A. If UPLO = 'U', the */ +/* leading N-by-N upper triangular part of A contains the */ +/* upper triangular part of the matrix A. If UPLO = 'L', */ +/* the leading N-by-N lower triangular part of A contains */ +/* the lower triangular part of the matrix A. */ +/* On exit, if JOBZ = 'V', then if INFO = 0, A contains the */ +/* orthonormal eigenvectors of the matrix A. */ +/* If JOBZ = 'N', then on exit the lower triangle (if UPLO='L') */ +/* or the upper triangle (if UPLO='U') of A, including the */ +/* diagonal, is destroyed. */ + +/* LDA (input) INTEGER */ +/* The leading dimension of the array A. LDA >= max(1,N). */ + +/* W (output) DOUBLE PRECISION array, dimension (N) */ +/* If INFO = 0, the eigenvalues in ascending order. */ + +/* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) */ +/* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ + +/* LWORK (input) INTEGER */ +/* The length of the array WORK. LWORK >= max(1,3*N-1). */ +/* For optimal efficiency, LWORK >= (NB+2)*N, */ +/* where NB is the blocksize for DSYTRD returned by ILAENV. */ + +/* If LWORK = -1, then a workspace query is assumed; the routine */ +/* only calculates the optimal size of the WORK array, returns */ +/* this value as the first entry of the WORK array, and no error */ +/* message related to LWORK is issued by XERBLA. */ + +/* INFO (output) INTEGER */ +/* = 0: successful exit */ +/* < 0: if INFO = -i, the i-th argument had an illegal value */ +/* > 0: if INFO = i, the algorithm failed to converge; i */ +/* off-diagonal elements of an intermediate tridiagonal */ +/* form did not converge to zero. */ + + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + int syev ( + const char jobz, + const char uplo, + matrix& a, + matrix& w + ) + { + matrix work; + + const long n = a.nr(); + + w.set_size(n,1); + + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::syev(jobz, uplo, n, &a(0,0), + a.nr(), &w(0,0), &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual decomposition + info = binding::syev(jobz, uplo, n, &a(0,0), + a.nr(), &w(0,0), &work(0,0), work.size()); + + return info; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + int syev ( + char jobz, + char uplo, + matrix& a, + matrix& w + ) + { + matrix work; + + if (uplo == 'L') + uplo = 'U'; + else + uplo = 'L'; + + const long n = a.nr(); + + w.set_size(n,1); + + + // figure out how big the workspace needs to be. + T work_size = 1; + int info = binding::syev(jobz, uplo, n, &a(0,0), + a.nc(), &w(0,0), &work_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + + // compute the actual decomposition + info = binding::syev(jobz, uplo, n, &a(0,0), + a.nc(), &w(0,0), &work(0,0), work.size()); + + + a = trans(a); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_EV_H__ + + + + diff --git a/libs/dlib/matrix/lapack/syevr.h b/libs/dlib/matrix/lapack/syevr.h new file mode 100644 index 0000000..f3954a2 --- /dev/null +++ b/libs/dlib/matrix/lapack/syevr.h @@ -0,0 +1,445 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LAPACk_EVR_H__ +#define DLIB_LAPACk_EVR_H__ + +#include "fortran_id.h" +#include "../matrix.h" + +namespace dlib +{ + namespace lapack + { + namespace binding + { + extern "C" + { + void DLIB_FORTRAN_ID(dsyevr) (char *jobz, char *range, char *uplo, integer *n, + double *a, integer *lda, double *vl, double *vu, integer * il, + integer *iu, double *abstol, integer *m, double *w, + double *z__, integer *ldz, integer *isuppz, double *work, + integer *lwork, integer *iwork, integer *liwork, integer *info); + + void DLIB_FORTRAN_ID(ssyevr) (char *jobz, char *range, char *uplo, integer *n, + float *a, integer *lda, float *vl, float *vu, integer * il, + integer *iu, float *abstol, integer *m, float *w, + float *z__, integer *ldz, integer *isuppz, float *work, + integer *lwork, integer *iwork, integer *liwork, integer *info); + } + + inline int syevr (char jobz, char range, char uplo, integer n, + double* a, integer lda, double vl, double vu, integer il, + integer iu, double abstol, integer *m, double *w, + double *z, integer ldz, integer *isuppz, double *work, + integer lwork, integer *iwork, integer liwork) + { + integer info = 0; + DLIB_FORTRAN_ID(dsyevr)(&jobz, &range, &uplo, &n, + a, &lda, &vl, &vu, &il, + &iu, &abstol, m, w, + z, &ldz, isuppz, work, + &lwork, iwork, &liwork, &info); + return info; + } + + inline int syevr (char jobz, char range, char uplo, integer n, + float* a, integer lda, float vl, float vu, integer il, + integer iu, float abstol, integer *m, float *w, + float *z, integer ldz, integer *isuppz, float *work, + integer lwork, integer *iwork, integer liwork) + { + integer info = 0; + DLIB_FORTRAN_ID(ssyevr)(&jobz, &range, &uplo, &n, + a, &lda, &vl, &vu, &il, + &iu, &abstol, m, w, + z, &ldz, isuppz, work, + &lwork, iwork, &liwork, &info); + return info; + } + + } + + // ------------------------------------------------------------------------------------ + + /* + +* -- LAPACK driver routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + CHARACTER JOBZ, RANGE, UPLO + INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LWORK, M, N + DOUBLE PRECISION ABSTOL, VL, VU +* .. +* .. Array Arguments .. + INTEGER ISUPPZ( * ), IWORK( * ) + DOUBLE PRECISION A( LDA, * ), W( * ), WORK( * ), Z( LDZ, * ) +* .. +* +* Purpose +* ======= +* +* DSYEVR computes selected eigenvalues and, optionally, eigenvectors +* of a real symmetric matrix A. Eigenvalues and eigenvectors can be +* selected by specifying either a range of values or a range of +* indices for the desired eigenvalues. +* +* DSYEVR first reduces the matrix A to tridiagonal form T with a call +* to DSYTRD. Then, whenever possible, DSYEVR calls DSTEMR to compute +* the eigenspectrum using Relatively Robust Representations. DSTEMR +* computes eigenvalues by the dqds algorithm, while orthogonal +* eigenvectors are computed from various "good" L D L^T representations +* (also known as Relatively Robust Representations). Gram-Schmidt +* orthogonalization is avoided as far as possible. More specifically, +* the various steps of the algorithm are as follows. +* +* For each unreduced block (submatrix) of T, +* (a) Compute T - sigma I = L D L^T, so that L and D +* define all the wanted eigenvalues to high relative accuracy. +* This means that small relative changes in the entries of D and L +* cause only small relative changes in the eigenvalues and +* eigenvectors. The standard (unfactored) representation of the +* tridiagonal matrix T does not have this property in general. +* (b) Compute the eigenvalues to suitable accuracy. +* If the eigenvectors are desired, the algorithm attains full +* accuracy of the computed eigenvalues only right before +* the corresponding vectors have to be computed, see steps c) and d). +* (c) For each cluster of close eigenvalues, select a new +* shift close to the cluster, find a new factorization, and refine +* the shifted eigenvalues to suitable accuracy. +* (d) For each eigenvalue with a large enough relative separation compute +* the corresponding eigenvector by forming a rank revealing twisted +* factorization. Go back to (c) for any clusters that remain. +* +* The desired accuracy of the output can be specified by the input +* parameter ABSTOL. +* +* For more details, see DSTEMR's documentation and: +* - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations +* to compute orthogonal eigenvectors of symmetric tridiagonal matrices," +* Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. +* - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and +* Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, +* 2004. Also LAPACK Working Note 154. +* - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric +* tridiagonal eigenvalue/eigenvector problem", +* Computer Science Division Technical Report No. UCB/CSD-97-971, +* UC Berkeley, May 1997. +* +* +* Note 1 : DSYEVR calls DSTEMR when the full spectrum is requested +* on machines which conform to the ieee-754 floating point standard. +* DSYEVR calls DSTEBZ and SSTEIN on non-ieee machines and +* when partial spectrum requests are made. +* +* Normal execution of DSTEMR may create NaNs and infinities and +* hence may abort due to a floating point exception in environments +* which do not handle NaNs and infinities in the ieee standard default +* manner. +* +* Arguments +* ========= +* +* JOBZ (input) CHARACTER*1 +* = 'N': Compute eigenvalues only; +* = 'V': Compute eigenvalues and eigenvectors. +* +* RANGE (input) CHARACTER*1 +* = 'A': all eigenvalues will be found. +* = 'V': all eigenvalues in the half-open interval (VL,VU] +* will be found. +* = 'I': the IL-th through IU-th eigenvalues will be found. +********** For RANGE = 'V' or 'I' and IU - IL < N - 1, DSTEBZ and +********** DSTEIN are called +* +* UPLO (input) CHARACTER*1 +* = 'U': Upper triangle of A is stored; +* = 'L': Lower triangle of A is stored. +* +* N (input) INTEGER +* The order of the matrix A. N >= 0. +* +* A (input/output) DOUBLE PRECISION array, dimension (LDA, N) +* On entry, the symmetric matrix A. If UPLO = 'U', the +* leading N-by-N upper triangular part of A contains the +* upper triangular part of the matrix A. If UPLO = 'L', +* the leading N-by-N lower triangular part of A contains +* the lower triangular part of the matrix A. +* On exit, the lower triangle (if UPLO='L') or the upper +* triangle (if UPLO='U') of A, including the diagonal, is +* destroyed. +* +* LDA (input) INTEGER +* The leading dimension of the array A. LDA >= max(1,N). +* +* VL (input) DOUBLE PRECISION +* VU (input) DOUBLE PRECISION +* If RANGE='V', the lower and upper bounds of the interval to +* be searched for eigenvalues. VL < VU. +* Not referenced if RANGE = 'A' or 'I'. +* +* IL (input) INTEGER +* IU (input) INTEGER +* If RANGE='I', the indices (in ascending order) of the +* smallest and largest eigenvalues to be returned. +* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. +* Not referenced if RANGE = 'A' or 'V'. +* +* ABSTOL (input) DOUBLE PRECISION +* The absolute error tolerance for the eigenvalues. +* An approximate eigenvalue is accepted as converged +* when it is determined to lie in an interval [a,b] +* of width less than or equal to +* +* ABSTOL + EPS * max( |a|,|b| ) , +* +* where EPS is the machine precision. If ABSTOL is less than +* or equal to zero, then EPS*|T| will be used in its place, +* where |T| is the 1-norm of the tridiagonal matrix obtained +* by reducing A to tridiagonal form. +* +* See "Computing Small Singular Values of Bidiagonal Matrices +* with Guaranteed High Relative Accuracy," by Demmel and +* Kahan, LAPACK Working Note #3. +* +* If high relative accuracy is important, set ABSTOL to +* DLAMCH( 'Safe minimum' ). Doing so will guarantee that +* eigenvalues are computed to high relative accuracy when +* possible in future releases. The current code does not +* make any guarantees about high relative accuracy, but +* future releases will. See J. Barlow and J. Demmel, +* "Computing Accurate Eigensystems of Scaled Diagonally +* Dominant Matrices", LAPACK Working Note #7, for a discussion +* of which matrices define their eigenvalues to high relative +* accuracy. +* +* M (output) INTEGER +* The total number of eigenvalues found. 0 <= M <= N. +* If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. +* +* W (output) DOUBLE PRECISION array, dimension (N) +* The first M elements contain the selected eigenvalues in +* ascending order. +* +* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M)) +* If JOBZ = 'V', then if INFO = 0, the first M columns of Z +* contain the orthonormal eigenvectors of the matrix A +* corresponding to the selected eigenvalues, with the i-th +* column of Z holding the eigenvector associated with W(i). +* If JOBZ = 'N', then Z is not referenced. +* Note: the user must ensure that at least max(1,M) columns are +* supplied in the array Z; if RANGE = 'V', the exact value of M +* is not known in advance and an upper bound must be used. +* Supplying N columns is always safe. +* +* LDZ (input) INTEGER +* The leading dimension of the array Z. LDZ >= 1, and if +* JOBZ = 'V', LDZ >= max(1,N). +* +* ISUPPZ (output) INTEGER array, dimension ( 2*max(1,M) ) +* The support of the eigenvectors in Z, i.e., the indices +* indicating the nonzero elements in Z. The i-th eigenvector +* is nonzero only in elements ISUPPZ( 2*i-1 ) through +* ISUPPZ( 2*i ). +********** Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1 +* +* WORK (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK)) +* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. +* +* LWORK (input) INTEGER +* The dimension of the array WORK. LWORK >= max(1,26*N). +* For optimal efficiency, LWORK >= (NB+6)*N, +* where NB is the max of the blocksize for DSYTRD and DORMTR +* returned by ILAENV. +* +* If LWORK = -1, then a workspace query is assumed; the routine +* only calculates the optimal size of the WORK array, returns +* this value as the first entry of the WORK array, and no error +* message related to LWORK is issued by XERBLA. +* +* IWORK (workspace/output) INTEGER array, dimension (MAX(1,LIWORK)) +* On exit, if INFO = 0, IWORK(1) returns the optimal LWORK. +* +* LIWORK (input) INTEGER +* The dimension of the array IWORK. LIWORK >= max(1,10*N). +* +* If LIWORK = -1, then a workspace query is assumed; the +* routine only calculates the optimal size of the IWORK array, +* returns this value as the first entry of the IWORK array, and +* no error message related to LIWORK is issued by XERBLA. +* +* INFO (output) INTEGER +* = 0: successful exit +* < 0: if INFO = -i, the i-th argument had an illegal value +* > 0: Internal error +* +* Further Details +* =============== +* +* Based on contributions by +* Inderjit Dhillon, IBM Almaden, USA +* Osni Marques, LBNL/NERSC, USA +* Ken Stanley, Computer Science Division, University of +* California at Berkeley, USA +* Jason Riedy, Computer Science Division, University of +* California at Berkeley, USA +* +* ===================================================================== + + */ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int syevr ( + const char jobz, + const char range, + const char uplo, + matrix& a, + const double vl, + const double vu, + const integer il, + const integer iu, + const double abstol, + integer& num_eigenvalues_found, + matrix& w, + matrix& z, + matrix& isuppz + ) + { + matrix work; + matrix iwork; + + const long n = a.nr(); + + w.set_size(n,1); + + isuppz.set_size(2*n, 1); + + if (jobz == 'V') + { + z.set_size(n,n); + } + else + { + z.set_size(NR3?NR3:1, NC3?NC3:1); + } + + // figure out how big the workspace needs to be. + T work_size = 1; + integer iwork_size = 1; + int info = binding::syevr(jobz, range, uplo, n, &a(0,0), + a.nr(), vl, vu, il, iu, abstol, &num_eigenvalues_found, + &w(0,0), &z(0,0), z.nr(), &isuppz(0,0), &work_size, -1, + &iwork_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + if (iwork.size() < iwork_size) + iwork.set_size(iwork_size, 1); + + // compute the actual decomposition + info = binding::syevr(jobz, range, uplo, n, &a(0,0), + a.nr(), vl, vu, il, iu, abstol, &num_eigenvalues_found, + &w(0,0), &z(0,0), z.nr(), &isuppz(0,0), &work(0,0), work.size(), + &iwork(0,0), iwork.size()); + + + return info; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, long NR3, long NR4, + long NC1, long NC2, long NC3, long NC4, + typename MM + > + int syevr ( + const char jobz, + const char range, + char uplo, + matrix& a, + const double vl, + const double vu, + const integer il, + const integer iu, + const double abstol, + integer& num_eigenvalues_found, + matrix& w, + matrix& z, + matrix& isuppz + ) + { + matrix work; + matrix iwork; + + if (uplo == 'L') + uplo = 'U'; + else + uplo = 'L'; + + const long n = a.nr(); + + w.set_size(n,1); + + isuppz.set_size(2*n, 1); + + if (jobz == 'V') + { + z.set_size(n,n); + } + else + { + z.set_size(NR3?NR3:1, NC3?NC3:1); + } + + // figure out how big the workspace needs to be. + T work_size = 1; + integer iwork_size = 1; + int info = binding::syevr(jobz, range, uplo, n, &a(0,0), + a.nc(), vl, vu, il, iu, abstol, &num_eigenvalues_found, + &w(0,0), &z(0,0), z.nc(), &isuppz(0,0), &work_size, -1, + &iwork_size, -1); + + if (info != 0) + return info; + + if (work.size() < work_size) + work.set_size(static_cast(work_size), 1); + if (iwork.size() < iwork_size) + iwork.set_size(iwork_size, 1); + + // compute the actual decomposition + info = binding::syevr(jobz, range, uplo, n, &a(0,0), + a.nc(), vl, vu, il, iu, abstol, &num_eigenvalues_found, + &w(0,0), &z(0,0), z.nc(), &isuppz(0,0), &work(0,0), work.size(), + &iwork(0,0), iwork.size()); + + z = trans(z); + + return info; + } + + // ------------------------------------------------------------------------------------ + + } + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_LAPACk_EVR_H__ + + + diff --git a/libs/dlib/matrix/matrix.h b/libs/dlib/matrix/matrix.h new file mode 100644 index 0000000..84fbb24 --- /dev/null +++ b/libs/dlib/matrix/matrix.h @@ -0,0 +1,1841 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_ +#define DLIB_MATRIx_ + +#include "matrix_exp.h" +#include "matrix_abstract.h" +#include "../algs.h" +#include "../serialize.h" +#include "../enable_if.h" +#include +#include +//#include "../memory_manager.h" +#include "../is_kind.h" +#include "matrix_data_layout.h" +#include "matrix_assign_fwd.h" +#include "matrix_op.h" + +#ifdef _MSC_VER +// Disable the following warnings for Visual Studio + +// This warning is: +// "warning C4355: 'this' : used in base member initializer list" +// Which we get from this code but it is not an error so I'm turning this +// warning off and then turning it back on at the end of the file. +#pragma warning(disable : 4355) + +#endif + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // This template will perform the needed loop for element multiplication using whichever + // dimension is provided as a compile time constant (if one is at all). + template < + typename LHS, + typename RHS, + long lhs_nc = LHS::NC, + long rhs_nr = RHS::NR + > + struct matrix_multiply_helper + { + typedef typename LHS::type type; + template + inline const static type eval ( + const RHS_& rhs, + const LHS_& lhs, + const long r, + const long c + ) + { + type temp = lhs(r,0)*rhs(0,c); + for (long i = 1; i < rhs.nr(); ++i) + { + temp += lhs(r,i)*rhs(i,c); + } + return temp; + } + }; + + template < + typename LHS, + typename RHS, + long lhs_nc + > + struct matrix_multiply_helper + { + typedef typename LHS::type type; + template + inline const static type eval ( + const RHS_& rhs, + const LHS_& lhs, + const long r, + const long c + ) + { + type temp = lhs(r,0)*rhs(0,c); + for (long i = 1; i < lhs.nc(); ++i) + { + temp += lhs(r,i)*rhs(i,c); + } + return temp; + } + }; + + template + class matrix_multiply_exp; + + template + struct matrix_traits > + { + typedef typename LHS::type type; + typedef typename LHS::type const_ret_type; + typedef typename LHS::mem_manager_type mem_manager_type; + typedef typename LHS::layout_type layout_type; + const static long NR = LHS::NR; + const static long NC = RHS::NC; + +#ifdef DLIB_USE_BLAS + // if there are BLAS functions to be called then we want to make sure we + // always evaluate any complex expressions so that the BLAS bindings can happen. + const static bool lhs_is_costly = (LHS::cost > 2)&&(RHS::NC != 1 || LHS::cost >= 10000); + const static bool rhs_is_costly = (RHS::cost > 2)&&(LHS::NR != 1 || RHS::cost >= 10000); +#else + const static bool lhs_is_costly = (LHS::cost > 4)&&(RHS::NC != 1); + const static bool rhs_is_costly = (RHS::cost > 4)&&(LHS::NR != 1); +#endif + + // Note that if we decide that one of the matrices is too costly we will evaluate it + // into a temporary. Doing this resets its cost back to 1. + const static long lhs_cost = ((lhs_is_costly==true)? 1 : (LHS::cost)); + const static long rhs_cost = ((rhs_is_costly==true)? 1 : (RHS::cost)); + + // The cost of evaluating an element of a matrix multiply is the cost of evaluating elements from + // RHS and LHS times the number of rows/columns in the RHS/LHS matrix. If we don't know the matrix + // dimensions then just assume it is really large. + const static long cost = ((tmax::value!=0)? ((lhs_cost+rhs_cost)*tmax::value):(10000)); + }; + + template struct conditional_matrix_temp { typedef typename T::matrix_type type; }; + template struct conditional_matrix_temp { typedef T& type; }; + + template < + typename LHS, + typename RHS + > + class matrix_multiply_exp : public matrix_exp > + { + /*! + REQUIREMENTS ON LHS AND RHS + - must be matrix_exp objects. + !*/ + public: + + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + + const static bool lhs_is_costly = matrix_traits::lhs_is_costly; + const static bool rhs_is_costly = matrix_traits::rhs_is_costly; + const static bool either_is_costly = lhs_is_costly || rhs_is_costly; + const static bool both_are_costly = lhs_is_costly && rhs_is_costly; + + typedef typename conditional_matrix_temp::type LHS_ref_type; + typedef typename conditional_matrix_temp::type RHS_ref_type; + + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of objects. + template + matrix_multiply_exp (T1,T2); + + inline matrix_multiply_exp ( + const LHS& lhs_, + const RHS& rhs_ + ) : + lhs(lhs_), + rhs(rhs_) + { + // You are trying to multiply two incompatible matrices together. The number of columns + // in the matrix on the left must match the number of rows in the matrix on the right. + COMPILE_TIME_ASSERT(LHS::NC == RHS::NR || LHS::NC*RHS::NR == 0); + DLIB_ASSERT(lhs.nc() == rhs.nr() && lhs.size() > 0 && rhs.size() > 0, + "\tconst matrix_exp operator*(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to multiply two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + // You can't multiply matrices together if they don't both contain the same type of elements. + COMPILE_TIME_ASSERT((is_same_type::value == true)); + } + + inline const type operator() ( + const long r, + const long c + ) const + { + return matrix_multiply_helper::eval(rhs,lhs,r,c); + } + + inline const type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + long nr ( + ) const { return lhs.nr(); } + + long nc ( + ) const { return rhs.nc(); } + + template + bool aliases ( + const matrix_exp& item + ) const { return lhs.aliases(item) || rhs.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return aliases(item); } + + LHS_ref_type lhs; + RHS_ref_type rhs; + }; + + template < typename EXP1, typename EXP2 > + inline const matrix_multiply_exp operator* ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + return matrix_multiply_exp(m1.ref(), m2.ref()); + } + + template + class matrix_mul_scal_exp; + + // ------------------------- + + // Now we declare some overloads that cause any scalar multiplications to percolate + // up and outside of any matrix multiplies. Note that we are using the non-reference containing + // mode of the matrix_mul_scal_exp object since we are passing in locally constructed matrix_multiply_exp + // objects. So the matrix_mul_scal_exp object will contain copies of matrix_multiply_exp objects + // rather than references to them. This could result in extra matrix copies if the matrix_multiply_exp + // decided it should evaluate any of its arguments. So we also try to not apply this percolating operation + // if the matrix_multiply_exp would contain a fully evaluated copy of the original matrix_mul_scal_exp + // expression. + // + // Also, the reason we want to apply this transformation in the first place is because it (1) makes + // the expressions going into matrix multiply expressions simpler and (2) it makes it a lot more + // straightforward to bind BLAS calls to matrix expressions involving scalar multiplies. + template < typename EXP1, typename EXP2 > + inline const typename disable_if_c< matrix_multiply_exp, matrix_mul_scal_exp >::both_are_costly , + matrix_mul_scal_exp,false> >::type operator* ( + const matrix_mul_scal_exp& m1, + const matrix_mul_scal_exp& m2 + ) + { + typedef matrix_multiply_exp exp1; + typedef matrix_mul_scal_exp exp2; + return exp2(exp1(m1.m, m2.m), m1.s*m2.s); + } + + template < typename EXP1, typename EXP2 > + inline const typename disable_if_c< matrix_multiply_exp, EXP2 >::lhs_is_costly , + matrix_mul_scal_exp,false> >::type operator* ( + const matrix_mul_scal_exp& m1, + const matrix_exp& m2 + ) + { + typedef matrix_multiply_exp exp1; + typedef matrix_mul_scal_exp exp2; + return exp2(exp1(m1.m, m2.ref()), m1.s); + } + + template < typename EXP1, typename EXP2 > + inline const typename disable_if_c< matrix_multiply_exp >::rhs_is_costly , + matrix_mul_scal_exp,false> >::type operator* ( + const matrix_exp& m1, + const matrix_mul_scal_exp& m2 + ) + { + typedef matrix_multiply_exp exp1; + typedef matrix_mul_scal_exp exp2; + return exp2(exp1(m1.ref(), m2.m), m2.s); + } + +// ---------------------------------------------------------------------------------------- + + template + class matrix_add_exp; + + template + struct matrix_traits > + { + typedef typename LHS::type type; + typedef typename LHS::type const_ret_type; + typedef typename LHS::mem_manager_type mem_manager_type; + typedef typename LHS::layout_type layout_type; + const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR; + const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC; + const static long cost = LHS::cost+RHS::cost+1; + }; + + template < + typename LHS, + typename RHS + > + class matrix_add_exp : public matrix_exp > + { + /*! + REQUIREMENTS ON LHS AND RHS + - must be matrix_exp objects. + !*/ + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of objects. + template + matrix_add_exp (T1,T2); + + matrix_add_exp ( + const LHS& lhs_, + const RHS& rhs_ + ) : + lhs(lhs_), + rhs(rhs_) + { + // You can only add matrices together if they both have the same number of rows and columns. + COMPILE_TIME_ASSERT(LHS::NR == RHS::NR || LHS::NR == 0 || RHS::NR == 0); + COMPILE_TIME_ASSERT(LHS::NC == RHS::NC || LHS::NC == 0 || RHS::NC == 0); + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + // You can only add matrices together if they both contain the same types of elements. + COMPILE_TIME_ASSERT((is_same_type::value == true)); + } + + const type operator() ( + long r, + long c + ) const { return lhs(r,c) + rhs(r,c); } + + inline const type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return lhs.aliases(item) || rhs.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); } + + long nr ( + ) const { return lhs.nr(); } + + long nc ( + ) const { return lhs.nc(); } + + const LHS& lhs; + const RHS& rhs; + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_add_exp operator+ ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + return matrix_add_exp(m1.ref(),m2.ref()); + } + +// ---------------------------------------------------------------------------------------- + + template + class matrix_subtract_exp; + + template + struct matrix_traits > + { + typedef typename LHS::type type; + typedef typename LHS::type const_ret_type; + typedef typename LHS::mem_manager_type mem_manager_type; + typedef typename LHS::layout_type layout_type; + const static long NR = (RHS::NR > LHS::NR) ? RHS::NR : LHS::NR; + const static long NC = (RHS::NC > LHS::NC) ? RHS::NC : LHS::NC; + const static long cost = LHS::cost+RHS::cost+1; + }; + + template < + typename LHS, + typename RHS + > + class matrix_subtract_exp : public matrix_exp > + { + /*! + REQUIREMENTS ON LHS AND RHS + - must be matrix_exp objects. + !*/ + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of objects. + template + matrix_subtract_exp (T1,T2); + + matrix_subtract_exp ( + const LHS& lhs_, + const RHS& rhs_ + ) : + lhs(lhs_), + rhs(rhs_) + { + // You can only subtract one matrix from another if they both have the same number of rows and columns. + COMPILE_TIME_ASSERT(LHS::NR == RHS::NR || LHS::NR == 0 || RHS::NR == 0); + COMPILE_TIME_ASSERT(LHS::NC == RHS::NC || LHS::NC == 0 || RHS::NC == 0); + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator-(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to subtract two incompatible matrices" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + // You can only subtract one matrix from another if they both contain elements of the same type. + COMPILE_TIME_ASSERT((is_same_type::value == true)); + } + + const type operator() ( + long r, + long c + ) const { return lhs(r,c) - rhs(r,c); } + + inline const type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return lhs.aliases(item) || rhs.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return lhs.destructively_aliases(item) || rhs.destructively_aliases(item); } + + long nr ( + ) const { return lhs.nr(); } + + long nc ( + ) const { return lhs.nc(); } + + const LHS& lhs; + const RHS& rhs; + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_subtract_exp operator- ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + return matrix_subtract_exp(m1.ref(),m2.ref()); + } + +// ---------------------------------------------------------------------------------------- + + template + class matrix_div_scal_exp; + + template + struct matrix_traits > + { + typedef typename M::type type; + typedef typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const static long NR = M::NR; + const static long NC = M::NC; + const static long cost = M::cost+1; + }; + + template < + typename M + > + class matrix_div_scal_exp : public matrix_exp > + { + /*! + REQUIREMENTS ON M + - must be a matrix_exp object. + !*/ + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of objects. + template + matrix_div_scal_exp (T1, const type&); + + matrix_div_scal_exp ( + const M& m_, + const type& s_ + ) : + m(m_), + s(s_) + {} + + const type operator() ( + long r, + long c + ) const { return m(r,c)/s; } + + inline const type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return m.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return m.destructively_aliases(item); } + + long nr ( + ) const { return m.nr(); } + + long nc ( + ) const { return m.nc(); } + + const M& m; + const type s; + }; + + template < + typename EXP, + typename S + > + inline const typename enable_if_c::is_integer, matrix_div_scal_exp >::type operator/ ( + const matrix_exp& m, + const S& s + ) + { + return matrix_div_scal_exp(m.ref(),static_cast(s)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct matrix_traits > + { + typedef typename M::type type; + typedef typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const static long NR = M::NR; + const static long NC = M::NC; + const static long cost = M::cost+1; + }; + + template struct conditional_reference { typedef T type; }; + template struct conditional_reference { typedef T& type; }; + + + template < + typename M, + bool use_reference + > + class matrix_mul_scal_exp : public matrix_exp > + { + /*! + REQUIREMENTS ON M + - must be a matrix_exp object. + + !*/ + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + // You aren't allowed to multiply a matrix of matrices by a scalar. + COMPILE_TIME_ASSERT(is_matrix::value == false); + + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of objects. + template + matrix_mul_scal_exp (T1, const type&); + + matrix_mul_scal_exp ( + const M& m_, + const type& s_ + ) : + m(m_), + s(s_) + {} + + const type operator() ( + long r, + long c + ) const { return m(r,c)*s; } + + inline const type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return m.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return m.destructively_aliases(item); } + + long nr ( + ) const { return m.nr(); } + + long nc ( + ) const { return m.nc(); } + + typedef typename conditional_reference::type M_ref_type; + + M_ref_type m; + const type s; + }; + + template < + typename EXP, + typename S + > + inline typename disable_if, const matrix_mul_scal_exp >::type operator* ( + const matrix_exp& m, + const S& s + ) + { + typedef typename EXP::type type; + return matrix_mul_scal_exp(m.ref(),static_cast(s)); + } + + template < + typename EXP, + typename S, + bool B + > + inline typename disable_if, const matrix_mul_scal_exp >::type operator* ( + const matrix_mul_scal_exp& m, + const S& s + ) + { + typedef typename EXP::type type; + return matrix_mul_scal_exp(m.m,static_cast(s)*m.s); + } + + template < + typename EXP, + typename S + > + inline typename disable_if, const matrix_mul_scal_exp >::type operator* ( + const S& s, + const matrix_exp& m + ) + { + typedef typename EXP::type type; + return matrix_mul_scal_exp(m.ref(),static_cast(s)); + } + + template < + typename EXP, + typename S, + bool B + > + inline typename disable_if, const matrix_mul_scal_exp >::type operator* ( + const S& s, + const matrix_mul_scal_exp& m + ) + { + typedef typename EXP::type type; + return matrix_mul_scal_exp(m.m,static_cast(s)*m.s); + } + + template < + typename EXP , + typename S + > + inline const typename disable_if_c::is_integer, matrix_mul_scal_exp >::type operator/ ( + const matrix_exp& m, + const S& s + ) + { + typedef typename EXP::type type; + const type one = 1; + return matrix_mul_scal_exp(m.ref(),one/static_cast(s)); + } + + template < + typename EXP, + bool B, + typename S + > + inline const typename disable_if_c::is_integer, matrix_mul_scal_exp >::type operator/ ( + const matrix_mul_scal_exp& m, + const S& s + ) + { + typedef typename EXP::type type; + return matrix_mul_scal_exp(m.m,m.s/static_cast(s)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_s_div_m : basic_op_m + { + typedef typename M::type type; + + op_s_div_m( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+1; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return s/this->m(r,c); + } + }; + + template < + typename EXP, + typename S + > + const typename disable_if, matrix_op > >::type operator/ ( + const S& val, + const matrix_exp& m + ) + { + typedef typename EXP::type type; + + typedef op_s_div_m op; + return matrix_op(op(m.ref(), static_cast(val))); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + inline const matrix_mul_scal_exp operator- ( + const matrix_exp& m + ) + { + return matrix_mul_scal_exp(m.ref(),-1); + } + + template < + typename EXP, + bool B + > + inline const matrix_mul_scal_exp operator- ( + const matrix_mul_scal_exp& m + ) + { + return matrix_mul_scal_exp(m.m,-1*m.s); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_add_scalar : basic_op_m + { + typedef typename M::type type; + + op_add_scalar( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+1; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return this->m(r,c) + s; + } + }; + + template < + typename EXP, + typename T + > + const typename disable_if, matrix_op > >::type operator+ ( + const matrix_exp& m, + const T& val + ) + { + typedef typename EXP::type type; + + typedef op_add_scalar op; + return matrix_op(op(m.ref(), static_cast(val))); + } + + template < + typename EXP, + typename T + > + const typename disable_if, matrix_op > >::type operator+ ( + const T& val, + const matrix_exp& m + ) + { + typedef typename EXP::type type; + + typedef op_add_scalar op; + return matrix_op(op(m.ref(), static_cast(val))); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_subl_scalar : basic_op_m + { + typedef typename M::type type; + + op_subl_scalar( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+1; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return s - this->m(r,c) ; + } + }; + + template < + typename EXP, + typename T + > + const typename disable_if, matrix_op > >::type operator- ( + const T& val, + const matrix_exp& m + ) + { + typedef typename EXP::type type; + + typedef op_subl_scalar op; + return matrix_op(op(m.ref(), static_cast(val))); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_subr_scalar : basic_op_m + { + typedef typename M::type type; + + op_subr_scalar( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+1; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return this->m(r,c) - s; + } + }; + + template < + typename EXP, + typename T + > + const typename disable_if, matrix_op > >::type operator- ( + const matrix_exp& m, + const T& val + ) + { + typedef typename EXP::type type; + + typedef op_subr_scalar op; + return matrix_op(op(m.ref(), static_cast(val))); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP1, + typename EXP2 + > + bool operator== ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + if (m1.nr() == m2.nr() && m1.nc() == m2.nc()) + { + for (long r = 0; r < m1.nr(); ++r) + { + for (long c = 0; c < m1.nc(); ++c) + { + if (m1(r,c) != m2(r,c)) + return false; + } + } + return true; + } + return false; + } + + template < + typename EXP1, + typename EXP2 + > + inline bool operator!= ( + const matrix_exp& m1, + const matrix_exp& m2 + ) { return !(m1 == m2); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager, + typename layout + > + struct matrix_traits > + { + typedef T type; + typedef const T& const_ret_type; + typedef mem_manager mem_manager_type; + typedef layout layout_type; + const static long NR = num_rows; + const static long NC = num_cols; + const static long cost = 1; + + }; + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager, + typename layout + > + class matrix : public matrix_exp > + { + + COMPILE_TIME_ASSERT(num_rows >= 0 && num_cols >= 0); + + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + typedef typename matrix_traits::layout_type layout_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + + matrix () + { + } + + explicit matrix ( + long length + ) + { + // This object you are trying to call matrix(length) on is not a column or + // row vector. + COMPILE_TIME_ASSERT(NR == 1 || NC == 1); + DLIB_ASSERT( length >= 0, + "\tmatrix::matrix(length)" + << "\n\tlength must be at least 0" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + if (NR == 1) + { + DLIB_ASSERT(NC == 0 || NC == length, + "\tmatrix::matrix(length)" + << "\n\tSince this is a statically sized matrix length must equal NC" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + data.set_size(1,length); + } + else + { + DLIB_ASSERT(NR == 0 || NR == length, + "\tvoid matrix::set_size(length)" + << "\n\tSince this is a statically sized matrix length must equal NR" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + data.set_size(length,1); + } + } + + matrix ( + long rows, + long cols + ) + { + DLIB_ASSERT( (NR == 0 || NR == rows) && ( NC == 0 || NC == cols) && + rows >= 0 && cols >= 0, + "\tvoid matrix::matrix(rows, cols)" + << "\n\tYou have supplied conflicting matrix dimensions" + << "\n\trows: " << rows + << "\n\tcols: " << cols + << "\n\tNR: " << NR + << "\n\tNC: " << NC + ); + data.set_size(rows,cols); + } + + template + matrix ( + const matrix_exp& m + ) + { + // You get an error on this line if the matrix m contains a type that isn't + // the same as the type contained in the target matrix. + COMPILE_TIME_ASSERT((is_same_type::value == true) || + (is_matrix::value == true)); + + // The matrix you are trying to assign m to is a statically sized matrix and + // m's dimensions don't match that of *this. + COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); + COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); + DLIB_ASSERT((NR == 0 || NR == m.nr()) && (NC == 0 || NC == m.nc()), + "\tmatrix& matrix::matrix(const matrix_exp& m)" + << "\n\tYou are trying to assign a dynamically sized matrix to a statically sized matrix with the wrong size" + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tthis: " << this + ); + + data.set_size(m.nr(),m.nc()); + + matrix_assign(*this, m); + } + + matrix ( + const matrix& m + ) : matrix_exp(*this) + { + data.set_size(m.nr(),m.nc()); + matrix_assign(*this, m); + } + + template + explicit matrix ( + U (&array)[len] + ) + { + COMPILE_TIME_ASSERT(NR*NC == len && len > 0); + size_t idx = 0; + for (long r = 0; r < NR; ++r) + { + for (long c = 0; c < NC; ++c) + { + data(r,c) = static_cast(array[idx]); + ++idx; + } + } + } + + T& operator() ( + long r, + long c + ) + { + DLIB_ASSERT(r < nr() && c < nc() && + r >= 0 && c >= 0, + "\tT& matrix::operator(r,c)" + << "\n\tYou must give a valid row and column" + << "\n\tr: " << r + << "\n\tc: " << c + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + return data(r,c); + } + + const T& operator() ( + long r, + long c + ) const + { + DLIB_ASSERT(r < nr() && c < nc() && + r >= 0 && c >= 0, + "\tconst T& matrix::operator(r,c)" + << "\n\tYou must give a valid row and column" + << "\n\tr: " << r + << "\n\tc: " << c + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + return data(r,c); + } + + T& operator() ( + long i + ) + { + // You can only use this operator on column vectors. + COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); + DLIB_ASSERT(nc() == 1 || nr() == 1, + "\tconst type matrix::operator(i)" + << "\n\tYou can only use this operator on column or row vectors" + << "\n\ti: " << i + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + DLIB_ASSERT( 0 <= i && i < size(), + "\tconst type matrix::operator(i)" + << "\n\tYou must give a valid row/column number" + << "\n\ti: " << i + << "\n\tsize(): " << size() + << "\n\tthis: " << this + ); + return data(i); + } + + const T& operator() ( + long i + ) const + { + // You can only use this operator on column vectors. + COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); + DLIB_ASSERT(nc() == 1 || nr() == 1, + "\tconst type matrix::operator(i)" + << "\n\tYou can only use this operator on column or row vectors" + << "\n\ti: " << i + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + DLIB_ASSERT( 0 <= i && i < size(), + "\tconst type matrix::operator(i)" + << "\n\tYou must give a valid row/column number" + << "\n\ti: " << i + << "\n\tsize(): " << size() + << "\n\tthis: " << this + ); + return data(i); + } + + inline operator const type ( + ) const + { + COMPILE_TIME_ASSERT(NC == 1 || NC == 0); + COMPILE_TIME_ASSERT(NR == 1 || NR == 0); + DLIB_ASSERT( nr() == 1 && nc() == 1 , + "\tmatrix::operator const type" + << "\n\tYou can only attempt to implicit convert a matrix to a scalar if" + << "\n\tthe matrix is a 1x1 matrix" + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + return data(0); + } + + void set_size ( + long rows, + long cols + ) + { + DLIB_ASSERT( (NR == 0 || NR == rows) && ( NC == 0 || NC == cols) && + rows >= 0 && cols >= 0, + "\tvoid matrix::set_size(rows, cols)" + << "\n\tYou have supplied conflicting matrix dimensions" + << "\n\trows: " << rows + << "\n\tcols: " << cols + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + if (nr() != rows || nc() != cols) + data.set_size(rows,cols); + } + + void set_size ( + long length + ) + { + // This object you are trying to call set_size(length) on is not a column or + // row vector. + COMPILE_TIME_ASSERT(NR == 1 || NC == 1); + DLIB_ASSERT( length >= 0, + "\tvoid matrix::set_size(length)" + << "\n\tlength must be at least 0" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + if (NR == 1) + { + DLIB_ASSERT(NC == 0 || NC == length, + "\tvoid matrix::set_size(length)" + << "\n\tSince this is a statically sized matrix length must equal NC" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + if (nc() != length) + data.set_size(1,length); + } + else + { + DLIB_ASSERT(NR == 0 || NR == length, + "\tvoid matrix::set_size(length)" + << "\n\tSince this is a statically sized matrix length must equal NR" + << "\n\tlength: " << length + << "\n\tNR: " << NR + << "\n\tNC: " << NC + << "\n\tthis: " << this + ); + + if (nr() != length) + data.set_size(length,1); + } + } + + long nr ( + ) const { return data.nr(); } + + long nc ( + ) const { return data.nc(); } + + long size ( + ) const { return data.nr()*data.nc(); } + + template + matrix& operator= ( + U (&array)[len] + ) + { + COMPILE_TIME_ASSERT(NR*NC == len && len > 0); + size_t idx = 0; + for (long r = 0; r < NR; ++r) + { + for (long c = 0; c < NC; ++c) + { + data(r,c) = static_cast(array[idx]); + ++idx; + } + } + return *this; + } + + template + matrix& operator= ( + const matrix_exp& m + ) + { + // You get an error on this line if the matrix you are trying to + // assign m to is a statically sized matrix and m's dimensions don't + // match that of *this. + COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); + COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); + DLIB_ASSERT((NR == 0 || nr() == m.nr()) && + (NC == 0 || nc() == m.nc()), + "\tmatrix& matrix::operator=(const matrix_exp& m)" + << "\n\tYou are trying to assign a dynamically sized matrix to a statically sized matrix with the wrong size" + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tthis: " << this + ); + + // You get an error on this line if the matrix m contains a type that isn't + // the same as the type contained in the target matrix. + COMPILE_TIME_ASSERT((is_same_type::value == true) || + (is_matrix::value == true)); + if (m.destructively_aliases(*this) == false) + { + // This if statement is seemingly unnecessary since set_size() contains this + // exact same if statement. However, structuring the code this way causes + // gcc to handle the way it inlines this function in a much more favorable way. + if (data.nr() == m.nr() && data.nc() == m.nc()) + { + matrix_assign(*this, m); + } + else + { + set_size(m.nr(),m.nc()); + matrix_assign(*this, m); + } + } + else + { + // we have to use a temporary matrix object here because + // *this is aliased inside the matrix_exp m somewhere. + matrix temp; + temp.set_size(m.nr(),m.nc()); + matrix_assign(temp, m); + temp.swap(*this); + } + return *this; + } + + template + matrix& operator += ( + const matrix_exp& m + ) + { + // The matrix you are trying to assign m to is a statically sized matrix and + // m's dimensions don't match that of *this. + COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); + COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + if (nr() == m.nr() && nc() == m.nc()) + { + if (m.destructively_aliases(*this) == false) + { + matrix_assign(*this, *this + m); + } + else + { + // we have to use a temporary matrix object here because + // this->data is aliased inside the matrix_exp m somewhere. + matrix temp; + temp.set_size(m.nr(),m.nc()); + matrix_assign(temp, *this + m); + temp.swap(*this); + } + } + else + { + *this = m; + } + return *this; + } + + + template + matrix& operator -= ( + const matrix_exp& m + ) + { + // The matrix you are trying to assign m to is a statically sized matrix and + // m's dimensions don't match that of *this. + COMPILE_TIME_ASSERT(EXP::NR == NR || NR == 0 || EXP::NR == 0); + COMPILE_TIME_ASSERT(EXP::NC == NC || NC == 0 || EXP::NC == 0); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + if (nr() == m.nr() && nc() == m.nc()) + { + if (m.destructively_aliases(*this) == false) + { + matrix_assign(*this, *this - m); + } + else + { + // we have to use a temporary matrix object here because + // this->data is aliased inside the matrix_exp m somewhere. + matrix temp; + temp.set_size(m.nr(),m.nc()); + matrix_assign(temp, *this - m); + temp.swap(*this); + } + } + else + { + *this = -m; + } + return *this; + } + + template + matrix& operator *= ( + const matrix_exp& m + ) + { + *this = *this * m; + return *this; + } + + matrix& operator += ( + const matrix& m + ) + { + const long size = m.nr()*m.nc(); + if (nr() == m.nr() && nc() == m.nc()) + { + for (long i = 0; i < size; ++i) + data(i) += m.data(i); + } + else + { + set_size(m.nr(), m.nc()); + for (long i = 0; i < size; ++i) + data(i) = m.data(i); + } + return *this; + } + + matrix& operator -= ( + const matrix& m + ) + { + const long size = m.nr()*m.nc(); + if (nr() == m.nr() && nc() == m.nc()) + { + for (long i = 0; i < size; ++i) + data(i) -= m.data(i); + } + else + { + set_size(m.nr(), m.nc()); + for (long i = 0; i < size; ++i) + data(i) = -m.data(i); + } + return *this; + } + + matrix& operator += ( + const T val + ) + { + const long size = nr()*nc(); + for (long i = 0; i < size; ++i) + data(i) += val; + + return *this; + } + + matrix& operator -= ( + const T val + ) + { + const long size = nr()*nc(); + for (long i = 0; i < size; ++i) + data(i) -= val; + + return *this; + } + + matrix& operator *= ( + const T a + ) + { + const long size = data.nr()*data.nc(); + for (long i = 0; i < size; ++i) + data(i) *= a; + return *this; + } + + matrix& operator /= ( + const T a + ) + { + const long size = data.nr()*data.nc(); + for (long i = 0; i < size; ++i) + data(i) /= a; + return *this; + } + + matrix& operator= ( + const matrix& m + ) + { + if (this != &m) + { + set_size(m.nr(),m.nc()); + const long size = m.nr()*m.nc(); + for (long i = 0; i < size; ++i) + data(i) = m.data(i); + } + return *this; + } + + void swap ( + matrix& item + ) + { + data.swap(item.data); + } + + template + bool aliases ( + const matrix_exp& + ) const { return false; } + + bool aliases ( + const matrix_exp >& item + ) const { return (this == &item); } + + template + bool destructively_aliases ( + const matrix_exp& + ) const { return false; } + + private: + struct literal_assign_helper + { + /* + This struct is a helper struct returned by the operator<<() function below. It is + used primarily to enable us to put DLIB_CASSERT statements on the usage of the + operator<< form of matrix assignment. + */ + + literal_assign_helper(const literal_assign_helper& item) : m(item.m), r(item.r), c(item.c), has_been_used(false) {} + literal_assign_helper(matrix* m_): m(m_), r(0), c(0),has_been_used(false) {next();} + ~literal_assign_helper() + { + DLIB_CASSERT(!has_been_used || r == m->nr(), + "You have used the matrix comma based assignment incorrectly by failing to\n" + "supply a full set of values for every element of a matrix object.\n"); + } + + const literal_assign_helper& operator, ( + const T& val + ) const + { + DLIB_CASSERT(r < m->nr() && c < m->nc(), + "You have used the matrix comma based assignment incorrectly by attempting to\n" << + "supply more values than there are elements in the matrix object being assigned to.\n\n" << + "Did you forget to call set_size()?" + << "\n\t r: " << r + << "\n\t c: " << c + << "\n\t m->nr(): " << m->nr() + << "\n\t m->nc(): " << m->nc()); + (*m)(r,c) = val; + next(); + has_been_used = true; + return *this; + } + + private: + + void next ( + ) const + { + ++c; + if (c == m->nc()) + { + c = 0; + ++r; + } + } + + matrix* m; + mutable long r; + mutable long c; + mutable bool has_been_used; + }; + + public: + + const literal_assign_helper operator = ( + const T& val + ) + { + // assign the given value to every spot in this matrix + for (long r = 0; r < nr(); ++r) + { + for (long c = 0; c < nc(); ++c) + { + data(r,c) = val; + } + } + + // Now return the literal_assign_helper so that the user + // can use the overloaded comma notation to initialize + // the matrix if they want to. + return literal_assign_helper(this); + } + + private: + + + typename layout::template layout data; + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void swap( + matrix& a, + matrix& b + ) { a.swap(b); } + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void serialize ( + const matrix& item, + std::ostream& out + ) + { + try + { + serialize(item.nr(),out); + serialize(item.nc(),out); + for (long r = 0; r < item.nr(); ++r) + { + for (long c = 0; c < item.nc(); ++c) + { + serialize(item(r,c),out); + } + } + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing dlib::matrix"); + } + } + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void deserialize ( + matrix& item, + std::istream& in + ) + { + try + { + long nr, nc; + deserialize(nr,in); + deserialize(nc,in); + + if (NR != 0 && nr != NR) + throw serialization_error("Error while deserializing a dlib::matrix. Invalid rows"); + if (NC != 0 && nc != NC) + throw serialization_error("Error while deserializing a dlib::matrix. Invalid columns"); + + item.set_size(nr,nc); + for (long r = 0; r < nr; ++r) + { + for (long c = 0; c < nc; ++c) + { + deserialize(item(r,c),in); + } + } + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing a dlib::matrix"); + } + } + + template < + typename EXP + > + std::ostream& operator<< ( + std::ostream& out, + const matrix_exp& m + ) + { + using namespace std; + const streamsize old = out.width(); + + // first figure out how wide we should make each field + string::size_type w = 0; + ostringstream sout; + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + sout << m(r,c); + w = std::max(sout.str().size(),w); + sout.str(""); + } + } + + // now actually print it + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + out.width(static_cast(w)); + out << m(r,c) << " "; + } + out << "\n"; + } + out.width(old); + return out; + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + class const_temp_matrix; + + template < + typename EXP + > + struct matrix_traits > + { + typedef typename EXP::type type; + typedef typename EXP::const_ret_type const_ret_type; + typedef typename EXP::mem_manager_type mem_manager_type; + typedef typename EXP::layout_type layout_type; + const static long NR = EXP::NR; + const static long NC = EXP::NC; + const static long cost = 1; + }; + + template + class const_temp_matrix : public matrix_exp >, noncopyable + { + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + typedef typename matrix_traits::layout_type layout_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + + const_temp_matrix ( + const matrix_exp& item + ) : + ref_(item.ref()) + {} + const_temp_matrix ( + const EXP& item + ) : + ref_(item) + {} + + const_ret_type operator() ( + long r, + long c + ) const { return ref_(r,c); } + + const_ret_type operator() ( long i ) const + { return ref_(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return ref_.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return ref_.destructively_aliases(item); } + + long nr ( + ) const { return ref_.nr(); } + + long nc ( + ) const { return ref_.nc(); } + + private: + + typename conditional_matrix_temp::type ref_; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef _MSC_VER +// put that warning back to its default setting +#pragma warning(default : 4355) +#endif + +#endif // DLIB_MATRIx_ + diff --git a/libs/dlib/matrix/matrix_abstract.h b/libs/dlib/matrix/matrix_abstract.h new file mode 100644 index 0000000..12e836b --- /dev/null +++ b/libs/dlib/matrix/matrix_abstract.h @@ -0,0 +1,723 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_ABSTRACT_ +#ifdef DLIB_MATRIx_ABSTRACT_ + +#include "matrix_exp_abstract.h" +#include "../serialize.h" +#include "../algs.h" +#include "matrix_data_layout_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /* + Note that these operator prototypes are not correct C++ (the real versions, which + you can see in the implementation are really complex and so probably would + distract/confuse people if shown here). Think of this as just a list of the + operators available to you and what they do. + */ + + const matrix_exp operator* ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1.nc() == m2.nr() + - m1.size() > 0 && m2.size() > 0 + (you can't multiply any sort of empty matrices together) + - m1 and m2 both contain elements of the same type + ensures + - returns the result of doing the matrix multiplication m1*m2. The resulting + matrix will have m1.nr() rows and m2.nc() columns. + !*/ + + const matrix_exp operator+ ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1.nr() == m2.nr() + - m1.nc() == m2.nc() + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that for all valid r and c: + R(r,c) == m1(r,c) + m2(r,c) + (i.e. returns the result of doing a pairwise addition of the matrices m1 and m2.) + The resulting matrix will have the same dimensions as the originals. + !*/ + + const matrix_exp operator- ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1.nr() == m2.nr() + - m1.nc() == m2.nc() + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that for all valid r and c: + R(r,c) == m1(r,c) - m2(r,c) + (i.e. returns the result of doing a pairwise subtraction of the matrices m1 and m2.) + The resulting matrix will have the same dimensions as the originals. + !*/ + + template + const matrix_exp operator* ( + const matrix_exp& m, + const T& value + ); + /*! + ensures + - returns the result of multiplying all the elements of matrix m by the given + scalar value. The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator* ( + const T& value, + const matrix_exp& m + ); + /*! + ensures + - returns the result of multiplying all the elements of matrix m by the given + scalar value. The resulting matrix will have the same dimensions as m. + !*/ + + const matrix_exp operator- ( + const matrix_exp& m + ); + /*! + ensures + - returns -1*m + !*/ + + template + const matrix_exp operator/ ( + const matrix_exp& m, + const T& value + ); + /*! + ensures + - returns the result of dividing all the elements of matrix m by the given + scalar value. The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator/ ( + const T& value, + const matrix_exp& m + ); + /*! + ensures + - returns the result of dividing the given scalar value by all the elements + of matrix m. The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator+ ( + const matrix_exp& m, + const T& value + ); + /*! + ensures + - returns the result of adding value to all the elements of matrix m. + The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator+ ( + const T& value, + const matrix_exp& m + ); + /*! + ensures + - returns the result of adding value to all the elements of matrix m. + The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator- ( + const matrix_exp& m, + const T& value + ); + /*! + ensures + - returns the result of subtracting value from all the elements of matrix m. + The resulting matrix will have the same dimensions as m. + !*/ + + template + const matrix_exp operator- ( + const T& value, + const matrix_exp& m + ); + /*! + ensures + - Returns a matrix M such that: + - M has the same dimensions as m + - M contains the same type of element as m + - for all valid r and c: + - M(r,c) == value - m(r,c) + !*/ + + bool operator== ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + ensures + - if (m1.nr() == m2.nr() && m1.nc() == m2.nc() && + for all valid r and c: m1(r,c) == m2(r,c) ) then + - returns true + - else + - returns false + !*/ + + bool operator!= ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + ensures + - returns !(m1 == m2) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long num_rows = 0, + long num_cols = 0, + typename mem_manager = default_memory_manager, + typename layout = row_major_layout + > + class matrix : public matrix_exp > + { + /*! + REQUIREMENTS ON num_rows and num_cols + both must be bigger than or equal to 0 + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + REQUIREMENTS ON layout + Must be either row_major_layout or column_major_layout + + INITIAL VALUE + - if (num_rows > 0) then + - nr() == num_rows + - else + - nr() == 0 + + - if (num_cols > 0) then + - nc() == num_cols + - else + - nc() == 0 + + WHAT THIS OBJECT REPRESENTS + This object represents a matrix of nr() rows and nc() columns. This object + is also a matrix_exp. Thus it can be used in all of the above + global operators. + + The number of rows and columns of this object are determined by the template + arguments num_rows and num_cols. If num_rows or num_cols are 0 then + the matrix starts out empty (i.e. nr() == 0 and nc() == 0) and you may change + its size via the set_size() member function. + + Setting num_rows or num_cols to something other than 0 causes that dimension + to have a fixed size. Setting a fixed size at compile time is useful because + any errors related to operating on matrices with incompatible dimensions will + be detected at compile time. It also allows the compiler to perform loop + unrolling which can result in substantially faster code. + + Also note that the elements of this matrix are laid out in memory by the layout + object supplied as a template argument to this class. The row_major_layout + sets elements down contiguously in memory and in row major order. Additionally, + all memory allocations are performed using the memory manager object supplied as + a template argument to this class. + !*/ + + public: + typedef T type; + typedef mem_manager mem_manager_type; + typedef layout layout_type; + const static long NR = num_rows; + const static long NC = num_cols; + const static long cost = 1; + + matrix ( + ); + /*! + ensures + - #*this is properly initialized + - #aliases(*this) == true + - #ref().aliases(*this) == true + !*/ + + explicit matrix ( + long length + ); + /*! + requires + - NR == 1 || NC == 1 (i.e. this must be a column or row vector) + - length >= 0 + - if (NR == 1 && NC > 0) then + - length == NC + - if (NC == 1 && NR > 0) then + - length == NR + ensures + - #*this is properly initialized + - #aliases(*this) == true + - #ref().aliases(*this) == true + - if (NR == 1) then + - #nr() == 1 + - #nc() == length + - else + - #nr() == length + - #nc() == 1 + !*/ + + matrix ( + long rows, + long cols + ); + /*! + requires + - rows == NR || NR == 0 + - cols == NC || NC == 0 + - rows >= 0 && cols >= 0 + ensures + - #*this is properly initialized + - #aliases(*this) == true + - #ref().aliases(*this) == true + - #nr() == rows + - #nc() == cols + !*/ + + template + matrix ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == T + (i.e. m contains the same type as *this does) + - if (NR != 0) then NR == m.nr() + - if (NC != 0) then NC == m.nc() + ensures + - #*this == m + - #aliases(*this) == true + - #ref().aliases(*this) == true + !*/ + + template + explicit matrix ( + U (&array)[len] + ); + /*! + requires + - NR != 0 && NC != 0 (i.e. you can only use this constructor on statically sized matrices) + - len == nr()*nc() (i.e. the array you give here must be the right size) + ensures + - for all valid r and c: + #(*this)(r,c) == array[r*nc() + c] + (i.e. initializes this matrix with the contents of the given array) + - #aliases(*this) == true + - #ref().aliases(*this) == true + !*/ + + T& operator() ( + long r, + long c + ); + /*! + requires + - 0 <= r < nr() + - 0 <= c < nc() + ensures + - returns a reference to the value at the given row and column in + this matrix. + !*/ + + const T& operator() ( + long r, + long c + ) const; + /*! + requires + - 0 <= r < nr() + - 0 <= c < nc() + ensures + - returns a const reference to the value at the given row and column in + this matrix. + !*/ + + T& operator() ( + long i + ); + /*! + requires + - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) + - 0 <= i < size() + ensures + - if (nc() == 1) then + - returns a reference to (*this)(i,0) + - else + - returns a reference to (*this)(0,i) + !*/ + + const T& operator() ( + long i + ) const; + /*! + requires + - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) + - 0 <= i < size() + ensures + - if (nc() == 1) then + - returns a reference to (*this)(i,0) + - else + - returns a reference to (*this)(0,i) + !*/ + + operator const type ( + ) const; + /*! + requires + - nr() == 1 + - nc() == 1 + ensures + - returns (*this)(0,0) + !*/ + + long nr( + ) const; + /*! + ensures + - returns the number of rows in this matrix + !*/ + + long nc( + ) const; + /*! + ensures + - returns the number of columns in this matrix + !*/ + + long size ( + ) const; + /*! + ensures + - returns nr()*nc() + !*/ + + void set_size ( + long rows, + long cols + ); + /*! + requires + - rows == NR || NR == 0 + - cols == NC || NC == 0 + - rows >= 0 && cols >= 0 + ensures + - #nr() == rows + - #nc() == cols + !*/ + + void set_size ( + long length + ); + /*! + requires + - NR == 1 || NC == 1 (i.e. this must be a column or row vector) + - length >= 0 + - if (NR == 1 && NC > 0) then + - length == NC + - if (NC == 1 && NR > 0) then + - length == NR + ensures + - if (NR == 1) then + - #nr() == 1 + - #nc() == length + - else + - #nr() == length + - #nc() == 1 + !*/ + + template + matrix& operator= ( + U (&array)[len] + ); + /*! + requires + - len == nr()*nc() (i.e. the array you give here must be the right size) + ensures + - for all valid r and c: + #(*this)(r,c) == array[r*nc() + c] + (i.e. loads this matrix with the contents of the given array) + - returns *this + !*/ + + template + matrix& operator= ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == T + (i.e. m contains the same type as *this does) + - if (NR != 0) then NR == m.nr() + - if (NC != 0) then NC == m.nc() + ensures + - copies the given matrix expression m to *this + - returns *this + !*/ + + template + matrix& operator += ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == T + ensures + - if (nr() == m.nr() && nc() == m.nc()) then + - #(*this) == *this + m + - else + - #(*this) == m + (i.e. if the dimensions don't match then this function performs a + normal assignment) + - returns *this + !*/ + + template + matrix& operator -= ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == T + ensures + - if (nr() == m.nr() && nc() == m.nc()) then + - #(*this) == *this - m + - else + - #(*this) == -m + - returns *this + !*/ + + template + matrix& operator *= ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == T + (i.e. m must contain the same type of element as *this) + - nc() == m.nr() + - size() > 0 && m.size() > 0 + (you can't multiply any sort of empty matrices together) + ensures + - #(*this) == *this * m + - returns *this + !*/ + + matrix& operator *= ( + const T& a + ); + /*! + ensures + - #(*this) == *this * a + - returns *this + !*/ + + matrix& operator /= ( + const T& a + ); + /*! + ensures + - #(*this) == *this / a + - returns *this + !*/ + + matrix& operator += ( + const T& a + ); + /*! + ensures + - #(*this) == *this + a + - returns *this + !*/ + + matrix& operator -= ( + const T& a + ); + /*! + ensures + - #(*this) == *this - a + - returns *this + !*/ + + const literal_assign_helper operator = ( + const T& val + ); + /*! + This function is somewhat different than all the others defined in this file. + The purpose of this function is to enable you to easily initialize a matrix object. + For example: + matrix m(2,3); + m = 1,2,3, + 4,5,6; + + The above code creates a matrix m with 2 rows and 3 columns and sets it so that + it contains the matrix | 1 2 3 | + | 4 5 6 | + + You can also use this function to assign to all elements of a matrix. So + saying m = 3; would assign all elements of m equal to 3. + + Note that to use this method of assignment it is required that you supply + exactly m.size() or 1 values so that the matrix is fully initialized. Supplying + fewer or more than that is an error that will cause a dlib::fatal_error to be + thrown. + + Note also that using an expression of the form m = scalar; when m.size() == 0 + is legal but has no effect on m. + !*/ + + void swap ( + matrix& item + ); + /*! + ensures + - swaps *this and item + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void swap( + matrix& a, + matrix& b + ) { a.swap(b); } + /*! + Provides a global swap function + !*/ + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void serialize ( + const matrix& item, + std::ostream& out + ); + /*! + Provides serialization support + !*/ + + template < + typename T, + long NR, + long NC, + typename mm, + typename l + > + void deserialize ( + matrix& item, + std::istream& in + ); + /*! + Provides deserialization support + !*/ + + template < + typename EXP + > + std::ostream& operator<< ( + std::ostream& out, + const matrix_exp& m + ); + /*! + ensures + - writes m to the given out stream in a form suitable for human consumption. + - returns out + !*/ + +// ---------------------------------------------------------------------------------------- + + template + class const_temp_matrix : public matrix_exp >, noncopyable + { + /*! + REQUIREMENTS ON EXP + - must be an object that inherits publicly from matrix_exp. + + WHAT THIS OBJECT REPRESENTS + This object represents a copy of a matrix expression. The twist + is that it only actually makes a copy of its input matrix expression + if that matrix expression is costly to evaluate. If it has + low cost then this object just stores a reference. + + This class is useful in cases where you write a function that + takes a matrix_exp object as input and you want to do some + intensive computation that looks at each element of that matrix_exp + many times. If the input matrix_exp has a high cost then you want + to store it into a temporary matrix. But if it has low cost then + it is faster if you just use a reference to it. The const_temp_matrix + makes doing this easy. + !*/ + public: + + const_temp_matrix ( + const matrix_exp& item + ); + /*! + ensures + - #*this == item + - if (EXP::cost <= 1) then + - this const_temp_matrix stores a reference to the item matrix + - else + - this const_temp_matrix creates a temporary matrix and copies + item into it + !*/ + + const_temp_matrix ( + const EXP& item + ); + /*! + ensures + - #*this == item + - if (EXP::cost <= 1) then + - this const_temp_matrix stores a reference to the item matrix + - else + - this const_temp_matrix creates a temporary matrix and copies + item into it + !*/ + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_ABSTRACT_ + diff --git a/libs/dlib/matrix/matrix_assign.h b/libs/dlib/matrix/matrix_assign.h new file mode 100644 index 0000000..f8f890f --- /dev/null +++ b/libs/dlib/matrix/matrix_assign.h @@ -0,0 +1,902 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_ASSIGn_ +#define DLIB_MATRIx_ASSIGn_ + +#include "../geometry.h" +#include "matrix.h" +#include "matrix_utilities.h" +#include "matrix_subexp.h" +#include "../enable_if.h" +#include "matrix_assign_fwd.h" +#include "matrix_default_mul.h" +#include "matrix_conj_trans.h" + +namespace dlib +{ + /* + This file contains some templates that are used inside the matrix_blas_bindings.h + file to bind various matrix expressions to optimized code for carrying them out. + */ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + namespace blas_bindings + { + + // ------------------------------------------------------------------------------------ + + template + void zero_matrix ( + T& m + ) + { + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + m(r,c) = 0; + } + } + } + + // ------------------------------------------------------------------------------------ + + // This template struct is used to tell us if a matrix expression contains a matrix multiply. + template + struct has_matrix_multiply + { + const static bool value = false; + }; + + template + struct has_matrix_multiply > + { const static bool value = true; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value || has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value || has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + template + struct has_matrix_multiply > + { const static bool value = has_matrix_multiply::value; }; + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + const int unknown_matrix = 0; + const int general_matrix = 1; + const int row_matrix = 2; + const int column_matrix = 3; + + // ------------------------------------------------------------------------------------ + + template + struct matrix_type_id + { + const static int value = unknown_matrix; + }; + + template + struct matrix_type_id > + { + const static int value = general_matrix; + }; + + template + struct matrix_type_id > + { + const static int value = column_matrix; + }; + + template + struct matrix_type_id > + { + const static int value = column_matrix; + }; + + template + struct matrix_type_id > + { + const static int value = row_matrix; + }; + + // ------------------------------------------------------------------------------------ + + template + struct matrix_type_id > > > + { + const static int value = column_matrix; + }; + + template + struct matrix_type_id > > > + { + const static int value = row_matrix; + }; + + template + struct matrix_type_id > > > + { + const static int value = column_matrix; + }; + + template + struct matrix_type_id > > > + { + const static int value = row_matrix; + }; + + template + struct matrix_type_id > > > + { + const static int value = general_matrix; + }; + + // ------------------------------------------------------------------------------------ + + template + struct same_matrix + { + const static int T_id = matrix_type_id::value; + const static int U_id = matrix_type_id::value; + // The check for unknown_matrix is here so that we can be sure that matrix types + // other than the ones specifically enumerated above never get pushed into + // any of the BLAS bindings. So saying they are never the same as anything + // else prevents them from matching any of the BLAS bindings. + const static bool value = (T_id == U_id) && (T_id != unknown_matrix); + }; + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + // This template struct is used to tell us if two matrix expressions both contain the same + // sequence of operators, expressions. It also only has a value of true if the T expression + // contains only matrices with the given layout. + template + struct same_exp + { + const static bool value = (is_same_type::value || + same_matrix::value) && + is_same_type::value; + + }; + + // Used only below. They help strip off the const and & qualifiers that can show up + // in the LHS_ref_type and RHS_ref_type typedefs. + template struct noref{ typedef T type;}; + template struct noref{ typedef T type;}; + template struct noref{ typedef T type;}; + template struct noref{ typedef T type;}; + + template + struct same_exp, matrix_multiply_exp,layout > + { + // The reason this case is more complex than the others is because the matrix_multiply_exp + // will use a temporary matrix instead of Tlhs or Trhs in the event that one of these + // types corresponds to an expensive expression. So we have to use the type that really + // gets used. The following typedefs are here to pick out that true type. + typedef typename matrix_multiply_exp::LHS_ref_type T_LHS_ref_type; + typedef typename matrix_multiply_exp::RHS_ref_type T_RHS_ref_type; + typedef typename noref::type T_lhs_type; + typedef typename noref::type T_rhs_type; + + typedef typename matrix_multiply_exp::LHS_ref_type U_LHS_ref_type; + typedef typename matrix_multiply_exp::RHS_ref_type U_RHS_ref_type; + typedef typename noref::type U_lhs_type; + typedef typename noref::type U_rhs_type; + + const static bool value = same_exp::value && + same_exp::value; + }; + + template + struct same_exp, matrix_add_exp, layout > + { const static bool value = same_exp::value && same_exp::value; }; + + template + struct same_exp, matrix_subtract_exp, layout > + { const static bool value = same_exp::value && same_exp::value; }; + + template + struct same_exp, matrix_mul_scal_exp, layout > + { const static bool value = same_exp::value; }; + + template + struct same_exp, matrix_div_scal_exp, layout > + { const static bool value = same_exp::value; }; + + template + struct same_exp >, matrix_op >, layout > + { const static bool value = same_exp::value; }; + + template + struct same_exp >, matrix_op >, layout > + { const static bool value = same_exp::value; }; + + template + struct same_exp >, matrix_op >, layout > + { const static bool value = same_exp::value; }; + + // ------------------------------------------------------------------------------------ + + struct yes_type + { + char ch; + }; + struct no_type + { + yes_type a, b; + }; + + // This is a helper that is used below to apply the same_exp template to matrix expressions. + template + typename enable_if,yes_type>::type test(U); + template + typename disable_if,no_type>::type test(U); + + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp, + typename enabled = void + > + struct matrix_assign_blas_helper + { + // We are in the default version of the blas helper so this + // means there wasn't any more specific overload. So just + // let the default matrix assignment happen. + template + static void assign ( + dest_exp& dest, + const EXP& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + if (transpose == false) + matrix_assign_default(dest,src,alpha,add_to); + else + matrix_assign_default(dest,trans(src),alpha,add_to); + } + + // If we know this is a matrix multiply then apply the + // default dlib matrix multiply to speed things up a bit more + // than the above default function would. + template + static void assign ( + dest_exp& dest, + const matrix_multiply_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + // At some point I need to improve the default (i.e. non BLAS) matrix + // multiplication algorithm... + + if (alpha == static_cast(1)) + { + if (add_to == false) + { + zero_matrix(dest); + } + + if (transpose == false) + default_matrix_multiply(dest, src.lhs, src.rhs); + else + default_matrix_multiply(dest, trans(src.rhs), trans(src.lhs)); + } + else + { + if (add_to) + { + typename dest_exp::matrix_type temp(dest.nr(),dest.nc()); + zero_matrix(temp); + + if (transpose == false) + default_matrix_multiply(temp, src.lhs, src.rhs); + else + default_matrix_multiply(temp, trans(src.rhs), trans(src.lhs)); + + matrix_assign_default(dest,temp, alpha,true); + } + else + { + zero_matrix(dest); + + if (transpose == false) + default_matrix_multiply(dest, src.lhs, src.rhs); + else + default_matrix_multiply(dest, trans(src.rhs), trans(src.lhs)); + + matrix_assign_default(dest,dest, alpha, false); + } + } + } + }; + +#ifdef __GNUC__ +#define DLIB_SHUT_UP_GCC_ABOUT_THIS_UNUSED_VARIABLE __attribute__ ((unused)) +#else +#define DLIB_SHUT_UP_GCC_ABOUT_THIS_UNUSED_VARIABLE +#endif + // This is a macro to help us add overloads for the matrix_assign_blas_helper template. + // Using this macro it is easy to add overloads for arbitrary matrix expressions. +#define DLIB_ADD_BLAS_BINDING(src_expression) \ + template struct BOOST_JOIN(blas,__LINE__) \ + { const static bool value = sizeof(yes_type) == sizeof(test(src_expression)); }; \ + \ + template < typename dest_exp, typename src_exp > \ + struct matrix_assign_blas_helper >::type > { \ + static void assign ( \ + dest_exp& dest, \ + const src_exp& src, \ + typename src_exp::type alpha, \ + bool add_to, \ + bool DLIB_SHUT_UP_GCC_ABOUT_THIS_UNUSED_VARIABLE transpose \ + ) { \ + typedef typename dest_exp::type T; + +#define DLIB_END_BLAS_BINDING }}; + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + // ------------------- Forward Declarations ------------------- + + template < + typename dest_exp, + typename src_exp + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const src_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ); + /*! + requires + - src.aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + !*/ + + template < + typename dest_exp, + typename src_exp, typename src_exp2 + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_add_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ); + /*! + requires + - src.aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + !*/ + + template < + typename dest_exp, + typename src_exp, bool Sb + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_mul_scal_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ); + /*! + requires + - src.aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + !*/ + + template < + typename dest_exp, + typename src_exp + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_op >& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ); + /*! + requires + - src.aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + !*/ + + template < + typename dest_exp, + typename src_exp, typename src_exp2 + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_subtract_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ); + /*! + requires + - src.aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + !*/ + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const src_exp& src + ); + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_add_exp ,src_exp>& src + ); + /*! + This function catches the expressions of the form: + M = M + exp; + and converts them into the appropriate matrix_assign_blas() call. + This is an important case to catch because it is the expression used + to represent the += matrix operator. + !*/ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_add_exp >& src + ); + /*! + This function catches the expressions of the form: + M = exp + M; + and converts them into the appropriate matrix_assign_blas() call. + This is an important case to catch because it is the expression used + to represent the += matrix operator. + !*/ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_subtract_exp ,src_exp>& src + ); + /*! + This function catches the expressions of the form: + M = M - exp; + and converts them into the appropriate matrix_assign_blas() call. + This is an important case to catch because it is the expression used + to represent the -= matrix operator. + !*/ + + + // End of forward declarations for overloaded matrix_assign_blas functions + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const src_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + matrix_assign_blas_helper::assign(dest,src,alpha,add_to, transpose); + } + + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp, typename src_exp2 + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_add_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + if (has_matrix_multiply::value || has_matrix_multiply::value) + { + matrix_assign_blas_proxy(dest, src.lhs, alpha, add_to, transpose); + matrix_assign_blas_proxy(dest, src.rhs, alpha, true, transpose); + } + else + { + if (transpose == false) + matrix_assign_default(dest, src, alpha, add_to); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp, bool Sb + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_mul_scal_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + matrix_assign_blas_proxy(dest, src.m, alpha*src.s, add_to, transpose); + } + + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_op >& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + matrix_assign_blas_proxy(dest, src.op.m, alpha, add_to, !transpose); + } + + // ------------------------------------------------------------------------------------ + + template < + typename dest_exp, + typename src_exp, typename src_exp2 + > + void matrix_assign_blas_proxy ( + dest_exp& dest, + const matrix_subtract_exp& src, + typename src_exp::type alpha, + bool add_to, + bool transpose + ) + { + + if (has_matrix_multiply::value || has_matrix_multiply::value) + { + matrix_assign_blas_proxy(dest, src.lhs, alpha, add_to, transpose); + matrix_assign_blas_proxy(dest, src.rhs, -alpha, true, transpose); + } + else + { + if (transpose == false) + matrix_assign_default(dest, src, alpha, add_to); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + } + } + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + // Once we get into this function it means that we are dealing with a matrix of float, + // double, complex, or complex and the src_exp contains at least one + // matrix multiply. + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const src_exp& src + ) + { + if (src.aliases(dest)) + { + matrix temp(dest.nr(),dest.nc()); + matrix_assign_blas_proxy(temp,src,1,false, false); + temp.swap(dest); + } + else + { + matrix_assign_blas_proxy(dest,src,1,false, false); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + assignable_sub_matrix& dest, + const src_exp& src + ) + { + if (src.aliases(dest.m)) + { + matrix temp(dest.nr(),dest.nc()); + matrix_assign_blas_proxy(temp,src,1,false, false); + matrix_assign_default(dest,temp); + } + else + { + matrix_assign_blas_proxy(dest,src,1,false, false); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + assignable_row_matrix& dest, + const src_exp& src + ) + { + if (src.aliases(dest.m)) + { + matrix temp(dest.nr(),dest.nc()); + matrix_assign_blas_proxy(temp,src,1,false, false); + matrix_assign_default(dest,temp); + } + else + { + matrix_assign_blas_proxy(dest,src,1,false, false); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + assignable_col_matrix& dest, + const src_exp& src + ) + { + if (src.aliases(dest.m)) + { + matrix temp(dest.nr(),dest.nc()); + matrix_assign_blas_proxy(temp,src,1,false, false); + matrix_assign_default(dest,temp); + } + else + { + matrix_assign_blas_proxy(dest,src,1,false, false); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_add_exp ,src_exp>& src + ) + { + if (src.rhs.aliases(dest) == false) + { + if (&src.lhs != &dest) + { + dest = src.lhs; + } + + matrix_assign_blas_proxy(dest, src.rhs, 1, true, false); + } + else + { + matrix temp(src.lhs); + matrix_assign_blas_proxy(temp, src.rhs, 1, true, false); + temp.swap(dest); + } + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_add_exp >& src + ) + { + // Just switch around the left and right hand sides of the incoming + // add expression and pass it back into matrix_assign_blas() so that + // the above function will be called. + typedef matrix_add_exp ,src_exp> swapped_add_exp; + matrix_assign_blas(dest, swapped_add_exp(src.rhs, src.lhs)); + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + void matrix_assign_blas ( + matrix& dest, + const matrix_subtract_exp ,src_exp>& src + ) + { + if (src.rhs.aliases(dest) == false) + { + if (&src.lhs != &dest) + { + dest = src.lhs; + } + + matrix_assign_blas_proxy(dest, src.rhs, -1, true, false); + } + else + { + matrix temp(src.lhs); + matrix_assign_blas_proxy(temp, src.rhs, -1, true, false); + temp.swap(dest); + } + } + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + } // end of namespace blas_bindings + + // ------------------------------------------------------------------------------------ + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + inline typename enable_if_c<(is_same_type::value || + is_same_type::value || + is_same_type >::value || + is_same_type >::value) && + blas_bindings::has_matrix_multiply::value + >::type matrix_assign_big ( + matrix& dest, + const src_exp& src + ) + { + blas_bindings::matrix_assign_blas(dest,src); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + inline typename enable_if_c<(is_same_type::value || + is_same_type::value || + is_same_type >::value || + is_same_type >::value) && + blas_bindings::has_matrix_multiply::value + >::type matrix_assign_big ( + assignable_sub_matrix& dest, + const src_exp& src + ) + { + blas_bindings::matrix_assign_blas(dest,src); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + inline typename enable_if_c<(is_same_type::value || + is_same_type::value || + is_same_type >::value || + is_same_type >::value) && + blas_bindings::has_matrix_multiply::value + >::type matrix_assign_big ( + assignable_row_matrix& dest, + const src_exp& src + ) + { + blas_bindings::matrix_assign_blas(dest,src); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, long NR, long NC, typename MM, typename L, + typename src_exp + > + inline typename enable_if_c<(is_same_type::value || + is_same_type::value || + is_same_type >::value || + is_same_type >::value) && + blas_bindings::has_matrix_multiply::value + >::type matrix_assign_big ( + assignable_col_matrix& dest, + const src_exp& src + ) + { + blas_bindings::matrix_assign_blas(dest,src); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_ASSIGn_ + diff --git a/libs/dlib/matrix/matrix_assign_fwd.h b/libs/dlib/matrix/matrix_assign_fwd.h new file mode 100644 index 0000000..d4ee64d --- /dev/null +++ b/libs/dlib/matrix/matrix_assign_fwd.h @@ -0,0 +1,402 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_ASSIGn_FWD_ +#define DLIB_MATRIx_ASSIGn_FWD_ + +#include "../enable_if.h" +#include "matrix_data_layout.h" +#include "../algs.h" + +namespace dlib +{ + + /* + The point of the matrix_assign() functions is to contain all the various + optimizations that help the matrix assign a matrix_exp to an actual matrix + object quickly. + */ + +// ---------------------------------------------------------------------------------------- + + namespace ma + { + // This template here controls how big a compile time sized matrix needs + // to be for it to get passed into the optimized versions of the + // matrix_assign() function. So small matrices are evaluated with a simple + // loop like the ones in this file and bigger matrices may get sent to BLAS + // routines or some other kind of optimized thing. + template < typename EXP, typename enable = void > + struct is_small_matrix { static const bool value = false; }; + template < typename EXP > + struct is_small_matrix=1 && EXP::NC>=1 && + EXP::NR<=17 && EXP::NC<=17 && (EXP::cost <= 70)>::type> { static const bool value = true; }; + + // I wouldn't use this mul object to do the multiply but visual studio 7.1 wouldn't + // compile otherwise. + template + struct mul { const static long value = a*b; }; + + template < typename EXP, typename enable = void > + struct is_very_small_matrix { static const bool value = false; }; + template < typename EXP > + struct is_very_small_matrix=1 && EXP::NC>=1 && + (mul::value <= 16) && (EXP::cost <= 70)>::type> { static const bool value = true; }; + + + template < typename EXP, typename enable = void > + struct has_column_major_layout { static const bool value = false; }; + template < typename EXP > + struct has_column_major_layout >::type > + { static const bool value = true; }; + + + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + class matrix_exp; + +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if >::type + matrix_assign_default ( + EXP1& dest, + const EXP2& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) = src(r,c); + } + } + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename enable_if >::type + matrix_assign_default ( + EXP1& dest, + const EXP2& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) = src(r,c); + } + } + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename disable_if >::type + matrix_assign_default ( + EXP1& dest, + const EXP2& src, + typename EXP2::type alpha, + bool add_to + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - if (add_to == false) then + - #dest == alpha*src + - else + - #dest == dest + alpha*src + !*/ + { + if (add_to) + { + if (alpha == static_cast(1)) + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) += src(r,c); + } + } + } + else if (alpha == static_cast(-1)) + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) -= src(r,c); + } + } + } + else + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) += alpha*src(r,c); + } + } + } + } + else + { + if (alpha == static_cast(1)) + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) = src(r,c); + } + } + } + else + { + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + dest(r,c) = alpha*src(r,c); + } + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename enable_if >::type + matrix_assign_default ( + EXP1& dest, + const EXP2& src, + typename EXP2::type alpha, + bool add_to + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - if (add_to == false) then + - #dest == alpha*src + - else + - #dest == dest + alpha*src + !*/ + { + if (add_to) + { + if (alpha == static_cast(1)) + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) += src(r,c); + } + } + } + else if (alpha == static_cast(-1)) + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) -= src(r,c); + } + } + } + else + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) += alpha*src(r,c); + } + } + } + } + else + { + if (alpha == static_cast(1)) + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) = src(r,c); + } + } + } + else + { + for (long c = 0; c < src.nc(); ++c) + { + for (long r = 0; r < src.nr(); ++r) + { + dest(r,c) = alpha*src(r,c); + } + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_dest_type, + typename src_exp + > + void matrix_assign_big ( + matrix_dest_type& dest, + const matrix_exp& src + ) + { + matrix_assign_default(dest,src); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_dest_type, + typename src_exp + > + inline typename disable_if >::type matrix_assign ( + matrix_dest_type& dest, + const matrix_exp& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + // Call src.ref() here so that the derived type of the matrix_exp shows + // up so we can overload matrix_assign_big() based on various matrix expression + // types. + matrix_assign_big(dest,src.ref()); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// this code is here to perform an unrolled version of the matrix_assign() function + template < typename DEST, typename SRC, long NR, long NC, + long R = 0, long C = 0, bool base_case = (R==NR) > + struct matrix_unroll_helper + { + inline static void go ( DEST& dest, const SRC& src) + { + dest(R,C) = src(R,C); + matrix_unroll_helper::go(dest,src); + } + }; + + template < typename DEST, typename SRC, long NR, long NC, long R, long C > + struct matrix_unroll_helper + { inline static void go ( DEST& , const SRC& ) {} }; + + template + inline void matrix_assign_unrolled ( + DEST& dest, + const SRC& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + COMPILE_TIME_ASSERT(SRC::NR*SRC::NC != 0); + matrix_unroll_helper::go(dest,src); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_dest_type, + typename src_exp + > + inline typename enable_if_c::value && ma::is_very_small_matrix::value==false >::type matrix_assign ( + matrix_dest_type& dest, + const matrix_exp& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + matrix_assign_default(dest,src.ref()); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_dest_type, + typename src_exp + > + inline typename enable_if_c::value && ma::is_very_small_matrix::value==true >::type matrix_assign ( + matrix_dest_type& dest, + const matrix_exp& src + ) + /*! + requires + - src.destructively_aliases(dest) == false + - dest.nr() == src.nr() + - dest.nc() == src.nc() + ensures + - #dest == src + !*/ + { + matrix_assign_unrolled(dest,src.ref()); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_ASSIGn_FWD_ + + diff --git a/libs/dlib/matrix/matrix_blas_bindings.h b/libs/dlib/matrix/matrix_blas_bindings.h new file mode 100644 index 0000000..877d3a1 --- /dev/null +++ b/libs/dlib/matrix/matrix_blas_bindings.h @@ -0,0 +1,1368 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_BLAS_BINDINGS_ +#define DLIB_MATRIx_BLAS_BINDINGS_ + +#ifndef DLIB_USE_BLAS +#error "DLIB_USE_BLAS should be defined if you want to use the BLAS bindings" +#endif + +#include "matrix_assign.h" +#include "matrix_conj_trans.h" +#include "cblas_constants.h" + +//#include +//using namespace std; + +namespace dlib +{ + + + namespace blas_bindings + { + +#ifdef DLIB_TEST_BLAS_BINDINGS + int& counter_gemm(); + int& counter_gemv(); + int& counter_ger(); + int& counter_dot(); + + #define DLIB_TEST_BLAS_BINDING_GEMM ++counter_gemm(); + #define DLIB_TEST_BLAS_BINDING_GEMV ++counter_gemv(); + #define DLIB_TEST_BLAS_BINDING_GER ++counter_ger(); + #define DLIB_TEST_BLAS_BINDING_DOT ++counter_dot(); +#else + #define DLIB_TEST_BLAS_BINDING_GEMM + #define DLIB_TEST_BLAS_BINDING_GEMV + #define DLIB_TEST_BLAS_BINDING_GER + #define DLIB_TEST_BLAS_BINDING_DOT +#endif + + extern "C" + { + // Here we declare the prototypes for the CBLAS calls used by the BLAS bindings below + + void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const float alpha, const float *A, + const int lda, const float *B, const int ldb, + const float beta, float *C, const int ldc); + void cblas_dgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const double alpha, const double *A, + const int lda, const double *B, const int ldb, + const double beta, double *C, const int ldc); + void cblas_cgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); + void cblas_zgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const void *alpha, const void *A, + const int lda, const void *B, const int ldb, + const void *beta, void *C, const int ldc); + void cblas_sgemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *X, const int incX, const float beta, + float *Y, const int incY); + void cblas_dgemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *X, const int incX, const double beta, + double *Y, const int incY); + void cblas_cgemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); + void cblas_zgemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const void *alpha, const void *A, const int lda, + const void *X, const int incX, const void *beta, + void *Y, const int incY); + void cblas_sger(const enum CBLAS_ORDER order, const int M, const int N, + const float alpha, const float *X, const int incX, + const float *Y, const int incY, float *A, const int lda); + void cblas_dger(const enum CBLAS_ORDER order, const int M, const int N, + const double alpha, const double *X, const int incX, + const double *Y, const int incY, double *A, const int lda); + void cblas_cgerc(const enum CBLAS_ORDER order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); + void cblas_zgerc(const enum CBLAS_ORDER order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); + float cblas_sdot(const int N, const float *X, const int incX, + const float *Y, const int incY); + double cblas_ddot(const int N, const double *X, const int incX, + const double *Y, const int incY); + void cblas_cdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); + void cblas_zdotu_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotu); + void cblas_cdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + void cblas_zdotc_sub(const int N, const void *X, const int incX, + const void *Y, const int incY, void *dotc); + void cblas_cgeru(const enum CBLAS_ORDER order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); + void cblas_zgeru(const enum CBLAS_ORDER order, const int M, const int N, + const void *alpha, const void *X, const int incX, + const void *Y, const int incY, void *A, const int lda); + } + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + inline void cblas_gemm( const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const float alpha, const float *A, + const int lda, const float *B, const int ldb, + const float beta, float *C, const int ldc) + { + DLIB_TEST_BLAS_BINDING_GEMM; + cblas_sgemm( Order, TransA, TransB, M, N, + K, alpha, A, lda, B, ldb, beta, C, ldc); + } + + inline void cblas_gemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const double alpha, const double *A, + const int lda, const double *B, const int ldb, + const double beta, double *C, const int ldc) + { + DLIB_TEST_BLAS_BINDING_GEMM; + cblas_dgemm( Order, TransA, TransB, M, N, + K, alpha, A, lda, B, ldb, beta, C, ldc); + } + + inline void cblas_gemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const std::complex& alpha, const std::complex *A, + const int lda, const std::complex *B, const int ldb, + const std::complex& beta, std::complex *C, const int ldc) + { + DLIB_TEST_BLAS_BINDING_GEMM; + cblas_cgemm( Order, TransA, TransB, M, N, + K, &alpha, A, lda, B, ldb, &beta, C, ldc); + } + + inline void cblas_gemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_TRANSPOSE TransB, const int M, const int N, + const int K, const std::complex& alpha, const std::complex *A, + const int lda, const std::complex *B, const int ldb, + const std::complex& beta, std::complex *C, const int ldc) + { + DLIB_TEST_BLAS_BINDING_GEMM; + cblas_zgemm( Order, TransA, TransB, M, N, + K, &alpha, A, lda, B, ldb, &beta, C, ldc); + } + + // ---------------------------------------------------------------------------------------- + + inline void cblas_gemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const float alpha, const float *A, const int lda, + const float *X, const int incX, const float beta, + float *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_GEMV; + cblas_sgemv(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } + + inline void cblas_gemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const double alpha, const double *A, const int lda, + const double *X, const int incX, const double beta, + double *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_GEMV; + cblas_dgemv(order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } + + inline void cblas_gemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const std::complex& alpha, const std::complex *A, const int lda, + const std::complex *X, const int incX, const std::complex& beta, + std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_GEMV; + cblas_cgemv(order, TransA, M, N, &alpha, A, lda, X, incX, &beta, Y, incY); + } + + inline void cblas_gemv(const enum CBLAS_ORDER order, + const enum CBLAS_TRANSPOSE TransA, const int M, const int N, + const std::complex& alpha, const std::complex *A, const int lda, + const std::complex *X, const int incX, const std::complex& beta, + std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_GEMV; + cblas_zgemv(order, TransA, M, N, &alpha, A, lda, X, incX, &beta, Y, incY); + } + + // ---------------------------------------------------------------------------------------- + + inline void cblas_ger(const enum CBLAS_ORDER order, const int M, const int N, + const std::complex& alpha, const std::complex *X, const int incX, + const std::complex *Y, const int incY, std::complex *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_cgeru (order, M, N, &alpha, X, incX, Y, incY, A, lda); + } + + inline void cblas_ger(const enum CBLAS_ORDER order, const int M, const int N, + const std::complex& alpha, const std::complex *X, const int incX, + const std::complex *Y, const int incY, std::complex *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_zgeru (order, M, N, &alpha, X, incX, Y, incY, A, lda); + } + + inline void cblas_ger(const enum CBLAS_ORDER order, const int M, const int N, + const float alpha, const float *X, const int incX, + const float *Y, const int incY, float *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_sger (order, M, N, alpha, X, incX, Y, incY, A, lda); + } + + inline void cblas_ger(const enum CBLAS_ORDER order, const int M, const int N, + const double alpha, const double *X, const int incX, + const double *Y, const int incY, double *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_dger (order, M, N, alpha, X, incX, Y, incY, A, lda); + } + + // ---------------------------------------------------------------------------------------- + + inline void cblas_gerc(const enum CBLAS_ORDER order, const int M, const int N, + const std::complex& alpha, const std::complex *X, const int incX, + const std::complex *Y, const int incY, std::complex *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_cgerc (order, M, N, &alpha, X, incX, Y, incY, A, lda); + } + + inline void cblas_gerc(const enum CBLAS_ORDER order, const int M, const int N, + const std::complex& alpha, const std::complex *X, const int incX, + const std::complex *Y, const int incY, std::complex *A, const int lda) + { + DLIB_TEST_BLAS_BINDING_GER; + cblas_zgerc (order, M, N, &alpha, X, incX, Y, incY, A, lda); + } + + // ---------------------------------------------------------------------------------------- + + inline float cblas_dot(const int N, const float *X, const int incX, + const float *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + return cblas_sdot(N, X, incX, Y, incY); + } + + inline double cblas_dot(const int N, const double *X, const int incX, + const double *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + return cblas_ddot(N, X, incX, Y, incY); + } + + inline std::complex cblas_dot(const int N, const std::complex *X, const int incX, + const std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + std::complex result; + cblas_cdotu_sub(N, X, incX, Y, incY, &result); + return result; + } + + inline std::complex cblas_dot(const int N, const std::complex *X, const int incX, + const std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + std::complex result; + cblas_zdotu_sub(N, X, incX, Y, incY, &result); + return result; + } + + // ---------------------------------------------------------------------------------------- + + inline std::complex cblas_dotc(const int N, const std::complex *X, const int incX, + const std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + std::complex result; + cblas_cdotc_sub(N, X, incX, Y, incY, &result); + return result; + } + + inline std::complex cblas_dotc(const int N, const std::complex *X, const int incX, + const std::complex *Y, const int incY) + { + DLIB_TEST_BLAS_BINDING_DOT; + std::complex result; + cblas_zdotc_sub(N, X, incX, Y, incY, &result); + return result; + } + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // Helpers for determining the data pointer, LDA, and incX arguments to BLAS functions. + + template + int get_ld (const matrix& m) { return m.nc(); } + + template + int get_ld (const matrix& m) { return m.nr(); } + + + template + int get_ld (const matrix_op > >& m) { return m.op.m.nc(); } + + template + int get_ld (const matrix_op > >& m) { return m.op.m.nr(); } + + template + int get_ld (const assignable_sub_matrix& m) { return m.m.nc(); } + + template + int get_ld (const assignable_sub_matrix& m) { return m.m.nr(); } + + // -------- + + template + int get_inc (const matrix& ) { return 1; } + + template + int get_inc(const matrix_op > >& m) + { + return m.op.m.nc(); + } + + template + int get_inc(const matrix_op > >& ) + { + return 1; + } + + template + int get_inc(const matrix_op > >& m) + { + return m.op.m.nc(); + } + + template + int get_inc(const matrix_op > >& ) + { + return 1; + } + + + + template + int get_inc(const matrix_op > >& ) + { + return 1; + } + + template + int get_inc(const matrix_op > >& m) + { + return m.op.m.nr(); + } + + template + int get_inc(const matrix_op > >& ) + { + return 1; + } + + template + int get_inc(const matrix_op > >& m) + { + return m.op.m.nr(); + } + + + + template + int get_inc(const assignable_row_matrix& ) + { + return 1; + } + + template + int get_inc(const assignable_row_matrix& m) + { + return m.m.nr(); + } + + template + int get_inc(const assignable_col_matrix& m) + { + return m.m.nc(); + } + + template + int get_inc(const assignable_col_matrix& ) + { + return 1; + } + + // -------- + + template + const T* get_ptr (const matrix& m) { return &m(0,0); } + + template + T* get_ptr (matrix& m) { return &m(0,0); } + + template + const T* get_ptr (const matrix_op > >& m) { return &m.op.m(m.op.r_,m.op.c_); } + + template + const T* get_ptr (const matrix_op > >& m) { return &m.op.m(0,m.op.col); } + + template + const T* get_ptr (const matrix_op > >& m) { return &m.op.m(m.op.row,0); } + + template + const T* get_ptr (const matrix_op > >& m) { return &m.op.m(0,m.op.col); } + + template + const T* get_ptr (const matrix_op > >& m) { return &m.op.m(m.op.row,0); } + + + template + T* get_ptr (assignable_col_matrix& m) { return &m(0,0); } + + template + T* get_ptr (assignable_row_matrix& m) { return &m(0,0); } + + template + T* get_ptr (assignable_sub_matrix& m) { return &m(0,0); } + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + // Here we declare some matrix objects for use in the DLIB_ADD_BLAS_BINDING macro. These + // extern declarations don't actually correspond to any real matrix objects. They are + // simply here so we can build matrix expressions with the DLIB_ADD_BLAS_BINDING marco. + + + // Note that the fact that these are double matrices isn't important, it is just a placeholder in this case. + extern matrix m; // general matrix + extern matrix rv; // general row vector + extern matrix cv; // general column vector + extern const double s; + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // GEMM overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + DLIB_ADD_BLAS_BINDING(m*m) + { + //cout << "BLAS GEMM: m*m" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs); + const int lda = get_ld(src.lhs); + const T* B = get_ptr(src.rhs); + const int ldb = get_ld(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, CblasNoTrans, CblasNoTrans, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + cblas_gemm(Order, CblasTrans, CblasTrans, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(m)*m) + { + //cout << "BLAS GEMM: trans(m)*m" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const CBLAS_TRANSPOSE TransB = CblasNoTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs); + const int ldb = get_ld(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + cblas_gemm(Order, TransA, TransB, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(m*trans(m)) + { + //cout << "BLAS GEMM: m*trans(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const CBLAS_TRANSPOSE TransB = CblasTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs); + const int lda = get_ld(src.lhs); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + cblas_gemm(Order, TransA, TransB, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(m)*trans(m)) + { + //cout << "BLAS GEMM: trans(m)*trans(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, CblasTrans, CblasTrans, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + cblas_gemm(Order, CblasNoTrans, CblasNoTrans, N, M, K, alpha, B, ldb, A, lda, beta, C, ldc); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + // -------------------------------------- + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(m))*m) + { + //cout << "BLAS GEMM: trans(conj(m))*m" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const CBLAS_TRANSPOSE TransB = CblasNoTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs); + const int ldb = get_ld(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(m)) + { + //cout << "BLAS GEMM: trans(conj(m))*trans(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const CBLAS_TRANSPOSE TransB = CblasTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(m*trans(conj(m))) + { + //cout << "BLAS GEMM: m*trans(conj(m))" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const CBLAS_TRANSPOSE TransB = CblasConjTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs); + const int lda = get_ld(src.lhs); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(m)*trans(conj(m))) + { + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const CBLAS_TRANSPOSE TransB = CblasConjTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(conj(m))) + { + //cout << "BLAS GEMM: trans(conj(m))*trans(conj(m))" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const CBLAS_TRANSPOSE TransB = CblasConjTrans; + const int M = static_cast(src.nr()); + const int N = static_cast(src.nc()); + const int K = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* B = get_ptr(src.rhs.op.m); + const int ldb = get_ld(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* C = get_ptr(dest); + const int ldc = get_ld(dest); + + if (transpose == false) + cblas_gemm(Order, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, ldc); + else + matrix_assign_default(dest, trans(src), alpha, add_to); + } DLIB_END_BLAS_BINDING + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // GEMV overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + DLIB_ADD_BLAS_BINDING(m*cv) + { + //cout << "BLAS GEMV: m*cv" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const int M = static_cast(src.lhs.nr()); + const int N = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs); + const int lda = get_ld(src.lhs); + const T* X = get_ptr(src.rhs); + const int incX = get_inc(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(rv*m) + { + // Note that rv*m is the same as trans(m)*trans(rv) + + //cout << "BLAS GEMV: rv*m" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const int M = static_cast(src.rhs.nr()); + const int N = static_cast(src.rhs.nc()); + const T* A = get_ptr(src.rhs); + const int lda = get_ld(src.rhs); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(cv)*m) + { + // Note that trans(cv)*m is the same as trans(m)*cv + + //cout << "BLAS GEMV: trans(cv)*m" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const int M = static_cast(src.rhs.nr()); + const int N = static_cast(src.rhs.nc()); + const T* A = get_ptr(src.rhs); + const int lda = get_ld(src.rhs); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(m*trans(rv)) + { + //cout << "BLAS GEMV: m*trans(rv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const int M = static_cast(src.lhs.nr()); + const int N = static_cast(src.lhs.nc()); + const T* A = get_ptr(src.lhs); + const int lda = get_ld(src.lhs); + const T* X = get_ptr(src.rhs.op.m); + const int incX = get_inc(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + // -------------------------------------- + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(m)*cv) + { + //cout << "BLAS GEMV: trans(m)*cv" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const int M = static_cast(src.lhs.op.m.nr()); + const int N = static_cast(src.lhs.op.m.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* X = get_ptr(src.rhs); + const int incX = get_inc(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(rv*trans(m)) + { + // Note that rv*trans(m) is the same as m*trans(rv) + + //cout << "BLAS GEMV: rv*trans(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const int M = static_cast(src.rhs.op.m.nr()); + const int N = static_cast(src.rhs.op.m.nc()); + const T* A = get_ptr(src.rhs.op.m); + const int lda = get_ld(src.rhs.op.m); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(cv)*trans(m)) + { + // Note that trans(cv)*trans(m) is the same as m*cv + + //cout << "BLAS GEMV: trans(cv)*trans(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasNoTrans; + const int M = static_cast(src.rhs.op.m.nr()); + const int N = static_cast(src.rhs.op.m.nc()); + const T* A = get_ptr(src.rhs.op.m); + const int lda = get_ld(src.rhs.op.m); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(m)*trans(rv)) + { + //cout << "BLAS GEMV: trans(m)*trans(rv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasTrans; + const int M = static_cast(src.lhs.op.m.nr()); + const int N = static_cast(src.lhs.op.m.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* X = get_ptr(src.rhs.op.m); + const int incX = get_inc(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + // -------------------------------------- + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(cv)*conj(m)) + { + // Note that trans(cv)*conj(m) == conj(trans(m))*cv + //cout << "BLAS GEMV: trans(cv)*conj(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const int M = static_cast(src.rhs.op.m.nr()); + const int N = static_cast(src.rhs.op.m.nc()); + const T* A = get_ptr(src.rhs.op.m); + const int lda = get_ld(src.rhs.op.m); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(rv*conj(m)) + { + // Note that rv*conj(m) == conj(trans(m))*cv + //cout << "BLAS GEMV: rv*conj(m)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const int M = static_cast(src.rhs.op.m.nr()); + const int N = static_cast(src.rhs.op.m.nc()); + const T* A = get_ptr(src.rhs.op.m); + const int lda = get_ld(src.rhs.op.m); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(m))*cv) + { + //cout << "BLAS GEMV: trans(conj(m))*cv" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const int M = static_cast(src.lhs.op.m.nr()); + const int N = static_cast(src.lhs.op.m.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* X = get_ptr(src.rhs); + const int incX = get_inc(src.rhs); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(m))*trans(rv)) + { + //cout << "BLAS GEMV: trans(conj(m))*trans(rv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const CBLAS_TRANSPOSE TransA = CblasConjTrans; + const int M = static_cast(src.lhs.op.m.nr()); + const int N = static_cast(src.lhs.op.m.nc()); + const T* A = get_ptr(src.lhs.op.m); + const int lda = get_ld(src.lhs.op.m); + const T* X = get_ptr(src.rhs.op.m); + const int incX = get_inc(src.rhs.op.m); + + const T beta = static_cast(add_to?1:0); + T* Y = get_ptr(dest); + const int incY = get_inc(dest); + + cblas_gemv(Order, TransA, M, N, alpha, A, lda, X, incX, beta, Y, incY); + } DLIB_END_BLAS_BINDING + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // GER overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + DLIB_ADD_BLAS_BINDING(cv*rv) + { + //cout << "BLAS GER: cv*rv" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(rv)*rv) + { + //cout << "BLAS GER: trans(rv)*rv" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(cv*trans(cv)) + { + //cout << "BLAS GER: cv*trans(cv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(rv)*trans(cv)) + { + //cout << "BLAS GER: trans(rv)*trans(cv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_ger(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_ger(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } DLIB_END_BLAS_BINDING + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // GERC overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + /* + DLIB_ADD_BLAS_BINDING(cv*conj(rv)) + { + //cout << "BLAS GERC: cv*conj(rv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } DLIB_END_BLAS_BINDING + */ + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(cv*conj(trans(cv))) + { + //cout << "BLAS GERC: cv*conj(trans(cv))" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + + if (transpose == false) + { + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (add_to == false) + zero_matrix(dest); + + cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); + } + else + { + matrix_assign_default(dest,trans(src),alpha,add_to); + //cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(rv)*conj(trans(cv))) + { + //cout << "BLAS GERC: trans(rv)*conj(trans(cv))" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + + if (transpose == false) + { + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); + } + else + { + matrix_assign_default(dest,trans(src),alpha,add_to); + //cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + /* + DLIB_ADD_BLAS_BINDING(trans(rv)*conj(rv)) + { + //cout << "BLAS GERC: trans(rv)*conj(rv)" << endl; + const bool is_row_major_order = is_same_type::value; + const CBLAS_ORDER Order = is_row_major_order ? CblasRowMajor : CblasColMajor; + const int M = static_cast(dest.nr()); + const int N = static_cast(dest.nc()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + zero_matrix(dest); + + T* A = get_ptr(dest); + const int lda = get_ld(dest); + + if (transpose == false) + cblas_gerc(Order, M, N, alpha, X, incX, Y, incY, A, lda); + else + cblas_gerc(Order, M, N, alpha, Y, incY, X, incX, A, lda); + } DLIB_END_BLAS_BINDING + */ + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // DOT overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + DLIB_ADD_BLAS_BINDING(rv*cv) + { + //cout << "BLAS DOT: rv*cv" << endl; + const int N = static_cast(src.lhs.size()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(cv)*cv) + { + //cout << "BLAS DOT: trans(cv)*cv" << endl; + const int N = static_cast(src.lhs.size()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(rv*trans(rv)) + { + //cout << "BLAS DOT: rv*trans(rv)" << endl; + const int N = static_cast(src.lhs.size()); + const T* X = get_ptr(src.lhs); + const int incX = get_inc(src.lhs); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(cv)*trans(rv)) + { + //cout << "BLAS DOT: trans(cv)*trans(rv)" << endl; + const int N = static_cast(src.lhs.op.m.size()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + dest(0) = alpha*cblas_dot(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dot(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + // DOTC overloads + // ---------------------------------------------------------------------------------------- + // ---------------------------------------------------------------------------------------- + + DLIB_ADD_BLAS_BINDING(conj(rv)*cv) + { + //cout << "BLAS DOTC: conj(rv)*cv" << endl; + const int N = static_cast(src.lhs.op.m.size()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(conj(trans(cv))*cv) + { + //cout << "BLAS DOTC: conj(trans(cv))*cv" << endl; + const int N = static_cast(src.lhs.op.m.size()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs); + const int incY = get_inc(src.rhs); + + if (add_to == false) + dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + // -------------------------------------- + + DLIB_ADD_BLAS_BINDING(trans(conj(cv))*trans(rv)) + { + //cout << "BLAS DOTC: trans(conj(cv))*trans(rv)" << endl; + const int N = static_cast(src.lhs.op.m.size()); + const T* X = get_ptr(src.lhs.op.m); + const int incX = get_inc(src.lhs.op.m); + const T* Y = get_ptr(src.rhs.op.m); + const int incY = get_inc(src.rhs.op.m); + + if (add_to == false) + dest(0) = alpha*cblas_dotc(N, X, incX, Y, incY); + else + dest(0) += alpha*cblas_dotc(N, X, incX, Y, incY); + + } DLIB_END_BLAS_BINDING + + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_BLAS_BINDINGS_ + diff --git a/libs/dlib/matrix/matrix_cholesky.h b/libs/dlib/matrix/matrix_cholesky.h new file mode 100644 index 0000000..fc11406 --- /dev/null +++ b/libs/dlib/matrix/matrix_cholesky.h @@ -0,0 +1,231 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +// This code was adapted from code from the JAMA part of NIST's TNT library. +// See: http://math.nist.gov/tnt/ +#ifndef DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H +#define DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H + +#include "matrix.h" +#include "matrix_utilities.h" +#include "matrix_subexp.h" +#include + +#ifdef DLIB_USE_LAPACK +#include "lapack/potrf.h" +#endif + +#include "matrix_trsm.h" + +namespace dlib +{ + + template < + typename matrix_exp_type + > + class cholesky_decomposition + { + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef matrix matrix_type; + typedef matrix column_vector_type; + + // You have supplied an invalid type of matrix_exp_type. You have + // to use this object with matrices that contain float or double type data. + COMPILE_TIME_ASSERT((is_same_type::value || + is_same_type::value )); + + + + template + cholesky_decomposition( + const matrix_exp& A + ); + + bool is_spd( + ) const; + + const matrix_type& get_l( + ) const; + + template + const typename EXP::matrix_type solve ( + const matrix_exp& B + ) const; + + private: + + matrix_type L_; // lower triangular factor + bool isspd; // true if matrix to be factored was SPD + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + bool cholesky_decomposition:: + is_spd( + ) const + { + return isspd; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename cholesky_decomposition::matrix_type& cholesky_decomposition:: + get_l( + ) const + { + return L_; + } + +// ---------------------------------------------------------------------------------------- + + template + template + cholesky_decomposition:: + cholesky_decomposition( + const matrix_exp& A_ + ) + { + using std::sqrt; + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(A_.nr() == A_.nc() && A_.size() > 0, + "\tcholesky_decomposition::cholesky_decomposition(A_)" + << "\n\tYou can only use this on square matrices" + << "\n\tA_.nr(): " << A_.nr() + << "\n\tA_.nc(): " << A_.nc() + << "\n\tA_.size(): " << A_.size() + << "\n\tthis: " << this + ); + +#ifdef DLIB_USE_LAPACK + L_ = A_; + const type eps = max(abs(diag(L_)))*std::sqrt(std::numeric_limits::epsilon())/100; + + // check if the matrix is actually symmetric + bool is_symmetric = true; + for (long r = 0; r < L_.nr() && is_symmetric; ++r) + { + for (long c = r+1; c < L_.nc() && is_symmetric; ++c) + { + // this is approximately doing: is_symmetric = is_symmetric && ( L_(k,j) == L_(j,k)) + is_symmetric = is_symmetric && (std::abs(L_(r,c) - L_(c,r)) < eps ); + } + } + + // now compute the actual cholesky decomposition + int info = lapack::potrf('L', L_); + + // check if it's really SPD + if (info == 0 && is_symmetric && min(abs(diag(L_))) > eps*100) + isspd = true; + else + isspd = false; + + L_ = lowerm(L_); +#else + const_temp_matrix A(A_); + + + isspd = true; + + const long n = A.nc(); + L_.set_size(n,n); + + const type eps = max(abs(diag(A)))*std::sqrt(std::numeric_limits::epsilon())/100; + + // Main loop. + for (long j = 0; j < n; j++) + { + type d(0.0); + for (long k = 0; k < j; k++) + { + type s(0.0); + for (long i = 0; i < k; i++) + { + s += L_(k,i)*L_(j,i); + } + + // if L_(k,k) != 0 + if (std::abs(L_(k,k)) > eps) + { + s = (A(j,k) - s)/L_(k,k); + } + else + { + s = (A(j,k) - s); + isspd = false; + } + + L_(j,k) = s; + + d = d + s*s; + + // this is approximately doing: isspd = isspd && ( A(k,j) == A(j,k)) + isspd = isspd && (std::abs(A(k,j) - A(j,k)) < eps ); + } + d = A(j,j) - d; + isspd = isspd && (d > eps); + L_(j,j) = sqrt(d > 0.0 ? d : 0.0); + for (long k = j+1; k < n; k++) + { + L_(j,k) = 0.0; + } + } +#endif + } + +// ---------------------------------------------------------------------------------------- + + template + template + const typename EXP::matrix_type cholesky_decomposition:: + solve( + const matrix_exp& B + ) const + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(L_.nr() == B.nr(), + "\tconst matrix cholesky_decomposition::solve(B)" + << "\n\tInvalid arguments were given to this function." + << "\n\tL_.nr(): " << L_.nr() + << "\n\tB.nr(): " << B.nr() + << "\n\tthis: " << this + ); + + matrix X(B); + + using namespace blas_bindings; + // Solve L*y = b; + triangular_solver(CblasLeft, CblasLower, CblasNoTrans, CblasNonUnit, L_, X); + // Solve L'*X = Y; + triangular_solver(CblasLeft, CblasLower, CblasTrans, CblasNonUnit, L_, X); + return X; + } + +// ---------------------------------------------------------------------------------------- + + + +} + +#endif // DLIB_MATRIX_CHOLESKY_DECOMPOSITION_H + + + + diff --git a/libs/dlib/matrix/matrix_conj_trans.h b/libs/dlib/matrix/matrix_conj_trans.h new file mode 100644 index 0000000..3c319cc --- /dev/null +++ b/libs/dlib/matrix/matrix_conj_trans.h @@ -0,0 +1,71 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_CONJ_TRANS_FUNCTIONS +#define DLIB_MATRIx_CONJ_TRANS_FUNCTIONS + +#include "matrix_utilities.h" +#include "matrix_math_functions.h" +#include "matrix.h" +#include "../algs.h" +#include +#include +#include + + +namespace dlib +{ + /*! + The point of the two functions defined in this file is to make statements + of the form conj(trans(m)) and trans(conj(m)) look the same so that it is + easier to map them to BLAS functions later on. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + struct op_conj_trans + { + op_conj_trans( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost+1; + const static long NR = M::NC; + const static long NC = M::NR; + typedef typename M::type type; + typedef typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply (long r, long c) const { return std::conj(m(c,r)); } + + long nr () const { return m.nc(); } + long nc () const { return m.nr(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template + const matrix_op > trans ( + const matrix_op >& m + ) + { + typedef op_conj_trans op; + return matrix_op(op(m.op.m)); + } + + template + const matrix_op > conj ( + const matrix_op >& m + ) + { + typedef op_conj_trans op; + return matrix_op(op(m.op.m)); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_CONJ_TRANS_FUNCTIONS + + diff --git a/libs/dlib/matrix/matrix_conv.h b/libs/dlib/matrix/matrix_conv.h new file mode 100644 index 0000000..79a3ded --- /dev/null +++ b/libs/dlib/matrix/matrix_conv.h @@ -0,0 +1,308 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_CONV_H__ +#define DLIB_MATRIx_CONV_H__ + +#include "matrix_conv_abstract.h" +#include "matrix.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + const T& conj(const T& item) { return item; } + template + std::complex conj(const std::complex& item) { return std::conj(item); } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + struct op_conv + { + op_conv( const M1& m1_, const M2& m2_) : + m1(m1_), + m2(m2_), + nr_(m1.nr()+m2.nr()-1), + nc_(m1.nc()+m2.nc()-1) + { + if (nr_ < 0 || m1.size() == 0 || m2.size() == 0) + nr_ = 0; + if (nc_ < 0 || m1.size() == 0 || m2.size() == 0) + nc_ = 0; + } + + const M1& m1; + const M2& m2; + long nr_; + long nc_; + + const static long cost = (M1::cost+M2::cost)*10; + const static long NR = (M1::NR*M2::NR==0) ? (0) : (M1::NR+M2::NR-1); + const static long NC = (M1::NC*M2::NC==0) ? (0) : (M1::NC+M2::NC-1); + typedef typename M1::type type; + typedef type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply (long r, long c) const + { + type temp = 0; + + const long min_rr = std::max(r-m2.nr()+1, 0); + const long max_rr = std::min(m1.nr()-1, r); + + const long min_cc = std::max(c-m2.nc()+1, 0); + const long max_cc = std::min(m1.nc()-1, c); + + for (long rr = min_rr; rr <= max_rr; ++rr) + { + for (long cc = min_cc; cc <= max_cc; ++cc) + { + if (flip_m2) + temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); + else + temp += m1(rr,cc)*m2(r-rr,c-cc); + } + } + + return temp; + } + + long nr () const { return nr_; } + long nc () const { return nc_; } + + template bool aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + + }; + + template < + typename M1, + typename M2 + > + const matrix_op > conv ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv op; + return matrix_op(op(m1.ref(),m2.ref())); + } + + template < + typename M1, + typename M2 + > + const matrix_op > xcorr ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv op; + return matrix_op(op(m1.ref(),m2.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + struct op_conv_same + { + op_conv_same( const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_),nr_(m1.nr()),nc_(m1.nc()) + { + if (m1.size() == 0 || m2.size() == 0) + nr_ = 0; + if (m1.size() == 0 || m2.size() == 0) + nc_ = 0; + } + + const M1& m1; + const M2& m2; + long nr_; + long nc_; + + const static long cost = (M1::cost+M2::cost)*10; + const static long NR = M1::NR; + const static long NC = M1::NC; + typedef typename M1::type type; + typedef type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply (long r, long c) const + { + r += m2.nr()/2; + c += m2.nc()/2; + + type temp = 0; + + const long min_rr = std::max(r-m2.nr()+1, 0); + const long max_rr = std::min(m1.nr()-1, r); + + const long min_cc = std::max(c-m2.nc()+1, 0); + const long max_cc = std::min(m1.nc()-1, c); + + for (long rr = min_rr; rr <= max_rr; ++rr) + { + for (long cc = min_cc; cc <= max_cc; ++cc) + { + if (flip_m2) + temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); + else + temp += m1(rr,cc)*m2(r-rr,c-cc); + } + } + + return temp; + } + + long nr () const { return nr_; } + long nc () const { return nc_; } + + template bool aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + + }; + + template < + typename M1, + typename M2 + > + const matrix_op > conv_same ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv_same op; + return matrix_op(op(m1.ref(),m2.ref())); + } + + template < + typename M1, + typename M2 + > + const matrix_op > xcorr_same ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv_same op; + return matrix_op(op(m1.ref(),m2.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + struct op_conv_valid + { + op_conv_valid( const M1& m1_, const M2& m2_) : + m1(m1_),m2(m2_), + nr_(m1.nr()-m2.nr()+1), + nc_(m1.nc()-m2.nc()+1) + { + if (nr_ < 0 || nc_ <= 0 || m1.size() == 0 || m2.size() == 0) + nr_ = 0; + if (nc_ < 0 || nr_ <= 0 || m1.size() == 0 || m2.size() == 0) + nc_ = 0; + } + + const M1& m1; + const M2& m2; + long nr_; + long nc_; + + const static long cost = (M1::cost+M2::cost)*10; + const static long NR = (M1::NR*M2::NR==0) ? (0) : (M1::NR-M2::NR+1); + const static long NC = (M1::NC*M2::NC==0) ? (0) : (M1::NC-M2::NC+1); + typedef typename M1::type type; + typedef type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply (long r, long c) const + { + r += m2.nr()-1; + c += m2.nc()-1; + + type temp = 0; + + const long min_rr = std::max(r-m2.nr()+1, 0); + const long max_rr = std::min(m1.nr()-1, r); + + const long min_cc = std::max(c-m2.nc()+1, 0); + const long max_cc = std::min(m1.nc()-1, c); + + for (long rr = min_rr; rr <= max_rr; ++rr) + { + for (long cc = min_cc; cc <= max_cc; ++cc) + { + if (flip_m2) + temp += m1(rr,cc)*dlib::impl::conj(m2(m2.nr()-r+rr-1, m2.nc()-c+cc-1)); + else + temp += m1(rr,cc)*m2(r-rr,c-cc); + } + } + + return temp; + } + + long nr () const { return nr_; } + long nc () const { return nc_; } + + template bool aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m1.aliases(item) || m2.aliases(item); } + + }; + + template < + typename M1, + typename M2 + > + const matrix_op > conv_valid ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv_valid op; + return matrix_op(op(m1.ref(),m2.ref())); + } + + template < + typename M1, + typename M2 + > + const matrix_op > xcorr_valid ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_conv_valid op; + return matrix_op(op(m1.ref(),m2.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_CONV_H__ + diff --git a/libs/dlib/matrix/matrix_conv_abstract.h b/libs/dlib/matrix/matrix_conv_abstract.h new file mode 100644 index 0000000..a773939 --- /dev/null +++ b/libs/dlib/matrix/matrix_conv_abstract.h @@ -0,0 +1,141 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_CONV_ABSTRACT_H__ +#ifdef DLIB_MATRIx_CONV_ABSTRACT_H__ + +#include "matrix_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp conv ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the convolution of m1 with m2. In particular, this function is + equivalent to performing the following in matlab: R = conv2(m1,m2). + - R::type == the same type that was in m1 and m2. + - R.nr() == m1.nr()+m2.nr()-1 + - R.nc() == m1.nc()+m2.nc()-1 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp xcorr ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the cross-correlation of m1 with m2. In particular, this + function returns conv(m1,flip(m2)) if the matrices contain real + elements and conv(m1,flip(conj(m2))) if they are complex. + - R::type == the same type that was in m1 and m2. + - R.nr() == m1.nr()+m2.nr()-1 + - R.nc() == m1.nc()+m2.nc()-1 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp conv_same ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the convolution of m1 with m2. In particular, this function is + equivalent to performing the following in matlab: R = conv2(m1,m2,'same'). + In particular, this means the result will have the same dimensions as m1 and will + contain the central part of the full convolution. Therefore, conv_same(m1,m2) is + equivalent to subm(conv(m1,m2), m2.nr()/2, m2.nc()/2, m1.nr(), m1.nc()). + - R::type == the same type that was in m1 and m2. + - R.nr() == m1.nr() + - R.nc() == m1.nc() + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp xcorr_same ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the cross-correlation of m1 with m2. In particular, this + function returns conv_same(m1,flip(m2)) if the matrices contain real + elements and conv_same(m1,flip(conj(m2))) if they are complex. + - R::type == the same type that was in m1 and m2. + - R.nr() == m1.nr() + - R.nc() == m1.nc() + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp conv_valid ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the convolution of m1 with m2. In particular, this function is + equivalent to performing the following in matlab: R = conv2(m1,m2,'valid'). + In particular, this means only elements of the convolution which don't require + zero padding are included in the result. + - R::type == the same type that was in m1 and m2. + - if (m1 has larger dimensions than m2) then + - R.nr() == m1.nr()-m2.nr()+1 + - R.nc() == m1.nc()-m2.nc()+1 + - else + - R.nr() == 0 + - R.nc() == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp xcorr_valid ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - m1 and m2 both contain elements of the same type + ensures + - returns a matrix R such that: + - R is the cross-correlation of m1 with m2. In particular, this + function returns conv_valid(m1,flip(m2)) if the matrices contain real + elements and conv_valid(m1,flip(conj(m2))) if they are complex. + - R::type == the same type that was in m1 and m2. + - if (m1 has larger dimensions than m2) then + - R.nr() == m1.nr()-m2.nr()+1 + - R.nc() == m1.nc()-m2.nc()+1 + - else + - R.nr() == 0 + - R.nc() == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_CONV_ABSTRACT_H__ + + diff --git a/libs/dlib/matrix/matrix_data_layout.h b/libs/dlib/matrix/matrix_data_layout.h new file mode 100644 index 0000000..1d45b51 --- /dev/null +++ b/libs/dlib/matrix/matrix_data_layout.h @@ -0,0 +1,900 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_DATA_LAYOUT_ +#define DLIB_MATRIx_DATA_LAYOUT_ + +#include "../algs.h" +#include "matrix_fwd.h" +#include "matrix_data_layout_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*! + A matrix layout object is any object that contains a templated class called "layout" + with an interface identical to one below: + (Note that all the template arguments are just the template arguments from the dlib::matrix + object and the member functions are defined identically to the ones with the same + signatures inside the matrix object.) + + struct matrix_layout + { + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout + { + public: + + T& operator() ( + long r, + long c + ); + + const T& operator() ( + long r, + long c + ); + + T& operator() ( + long i + ); + + const T& operator() ( + long i + ) const; + + void swap( + layout& item + ); + + long nr ( + ) const; + + long nc ( + ) const; + + void set_size ( + long nr_, + long nc_ + ); + }; + }; + !*/ + +// ---------------------------------------------------------------------------------------- + + struct row_major_layout + { + // if a matrix is bigger than this many bytes then don't put it on the stack + const static size_t max_stack_based_size = 256; + + // this is a hack to avoid a compile time error in visual studio 8. I would just + // use sizeof(T) and be done with it but that won't compile. The idea here + // is to avoid using the stack allocation of the layout object if it + // is going to contain another matrix and also avoid asking for the sizeof() + // the contained matrix. + template + struct get_sizeof_helper + { + const static std::size_t val = sizeof(T); + }; + + template + struct get_sizeof_helper > + { + const static std::size_t val = 1000000; + }; + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager, + int val = static_switch < + // when the sizes are all non zero and small + (num_rows*num_cols*get_sizeof_helper::val <= max_stack_based_size) && (num_rows != 0 && num_cols != 0), + // when the sizes are all non zero and big + (num_rows*num_cols*get_sizeof_helper::val > max_stack_based_size) && (num_rows != 0 && num_cols != 0), + num_rows == 0 && num_cols != 0, + num_rows != 0 && num_cols == 0, + num_rows == 0 && num_cols == 0 + >::value + > + class layout ; + /*! + WHAT THIS OBJECT REPRESENTS + This object represents the actual allocation of space for a matrix. + Small matrices allocate all their data on the stack and bigger ones + use a memory_manager to get their memory. + !*/ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when the sizes are all non zero and small + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout() {} + + T& operator() ( + long r, + long c + ) { return data[r][c]; } + + const T& operator() ( + long r, + long c + ) const { return data[r][c]; } + + T& operator() ( + long i + ) { return *(*data + i); } + + const T& operator() ( + long i + ) const { return *(*data + i); } + + void swap( + layout& item + ) + { + for (long r = 0; r < num_rows; ++r) + { + for (long c = 0; c < num_cols; ++c) + { + exchange((*this)(r,c),item(r,c)); + } + } + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long , + long + ) + { + } + + private: + T data[num_rows][num_cols]; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when the sizes are all non zero and big + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ) { data = pool.allocate_array(num_rows*num_cols); } + + ~layout () + { pool.deallocate_array(data); } + + T& operator() ( + long r, + long c + ) { return data[r*num_cols + c]; } + + const T& operator() ( + long r, + long c + ) const { return data[r*num_cols + c]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + pool.swap(item.pool); + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long , + long + ) + { + } + + private: + + T* data; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows == 0 && num_cols != 0, + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nr_(0) { } + + ~layout () + { + if (data) + pool.deallocate_array(data); + } + + T& operator() ( + long r, + long c + ) { return data[r*num_cols + c]; } + + const T& operator() ( + long r, + long c + ) const { return data[r*num_cols + c]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nr_,nr_); + pool.swap(item.pool); + } + + long nr ( + ) const { return nr_; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nr_ = nr; + } + + private: + + T* data; + long nr_; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows != 0 && num_cols == 0 + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nc_(0) { } + + ~layout () + { + if (data) + { + pool.deallocate_array(data); + } + } + + T& operator() ( + long r, + long c + ) { return data[r*nc_ + c]; } + + const T& operator() ( + long r, + long c + ) const { return data[r*nc_ + c]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nc_,nc_); + pool.swap(item.pool); + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return nc_; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nc_ = nc; + } + + private: + + T* data; + long nc_; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows == 0 && num_cols == 0 + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nr_(0), nc_(0) { } + + ~layout () + { + if (data) + { + pool.deallocate_array(data); + } + } + + T& operator() ( + long r, + long c + ) { return data[r*nc_ + c]; } + + const T& operator() ( + long r, + long c + ) const { return data[r*nc_ + c]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nc_,nc_); + std::swap(item.nr_,nr_); + pool.swap(item.pool); + } + + long nr ( + ) const { return nr_; } + + long nc ( + ) const { return nc_; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nr_ = nr; + nc_ = nc; + } + + private: + T* data; + long nr_; + long nc_; + typename mem_manager::template rebind::other pool; + }; + + }; + +// ---------------------------------------------------------------------------------------- + + struct column_major_layout + { + // if a matrix is bigger than this many bytes then don't put it on the stack + const static size_t max_stack_based_size = 256; + + + // this is a hack to avoid a compile time error in visual studio 8. I would just + // use sizeof(T) and be done with it but that won't compile. The idea here + // is to avoid using the stack allocation of the layout object if it + // is going to contain another matrix and also avoid asking for the sizeof() + // the contained matrix. + template + struct get_sizeof_helper + { + const static std::size_t val = sizeof(T); + }; + + template + struct get_sizeof_helper > + { + const static std::size_t val = 1000000; + }; + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager, + int val = static_switch < + // when the sizes are all non zero and small + (num_rows*num_cols*get_sizeof_helper::val <= max_stack_based_size) && (num_rows != 0 && num_cols != 0), + // when the sizes are all non zero and big + (num_rows*num_cols*get_sizeof_helper::val > max_stack_based_size) && (num_rows != 0 && num_cols != 0), + num_rows == 0 && num_cols != 0, + num_rows != 0 && num_cols == 0, + num_rows == 0 && num_cols == 0 + >::value + > + class layout ; + /*! + WHAT THIS OBJECT REPRESENTS + This object represents the actual allocation of space for a matrix. + Small matrices allocate all their data on the stack and bigger ones + use a memory_manager to get their memory. + !*/ + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when the sizes are all non zero and small + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout() {} + + T& operator() ( + long r, + long c + ) { return data[c][r]; } + + const T& operator() ( + long r, + long c + ) const { return data[c][r]; } + + T& operator() ( + long i + ) { return *(*data + i); } + + const T& operator() ( + long i + ) const { return *(*data + i); } + + void swap( + layout& item + ) + { + for (long r = 0; r < num_rows; ++r) + { + for (long c = 0; c < num_cols; ++c) + { + exchange((*this)(r,c),item(r,c)); + } + } + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long, + long + ) + { + } + + private: + T data[num_cols][num_rows]; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when the sizes are all non zero and big + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ) { data = pool.allocate_array(num_rows*num_cols); } + + ~layout () + { pool.deallocate_array(data); } + + T& operator() ( + long r, + long c + ) { return data[c*num_rows + r]; } + + const T& operator() ( + long r, + long c + ) const { return data[c*num_rows + r]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + pool.swap(item.pool); + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long , + long + ) + { + } + + private: + + T* data; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows == 0 && num_cols != 0, + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nr_(0) { } + + ~layout () + { + if (data) + pool.deallocate_array(data); + } + + T& operator() ( + long r, + long c + ) { return data[c*nr_ + r]; } + + const T& operator() ( + long r, + long c + ) const { return data[c*nr_ + r]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nr_,nr_); + pool.swap(item.pool); + } + + long nr ( + ) const { return nr_; } + + long nc ( + ) const { return num_cols; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nr_ = nr; + } + + private: + + T* data; + long nr_; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows != 0 && num_cols == 0 + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nc_(0) { } + + ~layout () + { + if (data) + { + pool.deallocate_array(data); + } + } + + T& operator() ( + long r, + long c + ) { return data[c*num_rows + r]; } + + const T& operator() ( + long r, + long c + ) const { return data[c*num_rows + r]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nc_,nc_); + pool.swap(item.pool); + } + + long nr ( + ) const { return num_rows; } + + long nc ( + ) const { return nc_; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nc_ = nc; + } + + private: + + T* data; + long nc_; + typename mem_manager::template rebind::other pool; + }; + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long num_rows, + long num_cols, + typename mem_manager + > + class layout : noncopyable // when num_rows == 0 && num_cols == 0 + { + public: + const static long NR = num_rows; + const static long NC = num_cols; + + layout ( + ):data(0), nr_(0), nc_(0) { } + + ~layout () + { + if (data) + { + pool.deallocate_array(data); + } + } + + T& operator() ( + long r, + long c + ) { return data[c*nr_ + r]; } + + const T& operator() ( + long r, + long c + ) const { return data[c*nr_ + r]; } + + T& operator() ( + long i + ) { return data[i]; } + + const T& operator() ( + long i + ) const { return data[i]; } + + void swap( + layout& item + ) + { + std::swap(item.data,data); + std::swap(item.nc_,nc_); + std::swap(item.nr_,nr_); + pool.swap(item.pool); + } + + long nr ( + ) const { return nr_; } + + long nc ( + ) const { return nc_; } + + void set_size ( + long nr, + long nc + ) + { + if (data) + { + pool.deallocate_array(data); + } + data = pool.allocate_array(nr*nc); + nr_ = nr; + nc_ = nc; + } + + private: + T* data; + long nr_; + long nc_; + typename mem_manager::template rebind::other pool; + }; + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_DATA_LAYOUT_ + diff --git a/libs/dlib/matrix/matrix_data_layout_abstract.h b/libs/dlib/matrix/matrix_data_layout_abstract.h new file mode 100644 index 0000000..c3fa02b --- /dev/null +++ b/libs/dlib/matrix/matrix_data_layout_abstract.h @@ -0,0 +1,40 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ +#ifdef DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ + +#include "../algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct row_major_layout + { + /*! + This is the default matrix layout. Any matrix object that uses this + layout will be laid out in memory in row major order. Additionally, + all elements are contiguous (e.g. there isn't any padding at the ends of + rows or anything like that) + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + struct column_major_layout + { + /*! + Any matrix object that uses this layout will be laid out in memory in + column major order. Additionally, all elements are contiguous (e.g. + there isn't any padding at the ends of rows or anything like that) + !*/ + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_DATA_LAYOUT_ABSTRACT_ + + diff --git a/libs/dlib/matrix/matrix_default_mul.h b/libs/dlib/matrix/matrix_default_mul.h new file mode 100644 index 0000000..ce1e37f --- /dev/null +++ b/libs/dlib/matrix/matrix_default_mul.h @@ -0,0 +1,134 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_DEFAULT_MULTIPLY_ +#define DLIB_MATRIx_DEFAULT_MULTIPLY_ + +#include "../geometry.h" +#include "matrix.h" +#include "matrix_utilities.h" +#include "../enable_if.h" + +namespace dlib +{ + +// ------------------------------------------------------------------------------------ + + namespace ma + { + template < typename EXP, typename enable = void > + struct matrix_is_vector { static const bool value = false; }; + template < typename EXP > + struct matrix_is_vector::type > { static const bool value = true; }; + } + +// ------------------------------------------------------------------------------------ + + /*! This file defines the default_matrix_multiply() function. It is a function + that conforms to the following definition: + + template < + typename matrix_dest_type, + typename EXP1, + typename EXP2 + > + void default_matrix_multiply ( + matrix_dest_type& dest, + const EXP1& lhs, + const EXP2& rhs + ); + requires + - (lhs*rhs).destructively_aliases(dest) == false + - dest.nr() == (lhs*rhs).nr() + - dest.nc() == (lhs*rhs).nc() + ensures + - #dest == dest + lhs*rhs + !*/ + +// ------------------------------------------------------------------------------------ + + template < + typename matrix_dest_type, + typename EXP1, + typename EXP2 + > + typename enable_if_c::value == true || ma::matrix_is_vector::value == true>::type + default_matrix_multiply ( + matrix_dest_type& dest, + const EXP1& lhs, + const EXP2& rhs + ) + { + matrix_assign_default(dest, lhs*rhs, 1, true); + } + +// ------------------------------------------------------------------------------------ + + template < + typename matrix_dest_type, + typename EXP1, + typename EXP2 + > + typename enable_if_c::value == false && ma::matrix_is_vector::value == false>::type + default_matrix_multiply ( + matrix_dest_type& dest, + const EXP1& lhs, + const EXP2& rhs + ) + { + const long bs = 90; + + // if the matrices are small enough then just use the simple multiply algorithm + if (lhs.nc() <= 2 || rhs.nc() <= 2 || lhs.nr() <= 2 || rhs.nr() <= 2 || (lhs.size() <= bs*10 && rhs.size() <= bs*10) ) + { + matrix_assign_default(dest, lhs*rhs, 1, true); + } + else + { + // if the lhs and rhs matrices are big enough we should use a cache friendly + // algorithm that computes the matrix multiply in blocks. + + + // Loop over all the blocks in the lhs matrix + for (long r = 0; r < lhs.nr(); r+=bs) + { + for (long c = 0; c < lhs.nc(); c+=bs) + { + // make a rect for the block from lhs + rectangle lhs_block(c, r, std::min(c+bs-1,lhs.nc()-1), std::min(r+bs-1,lhs.nr()-1)); + + // now loop over all the rhs blocks we have to multiply with the current lhs block + for (long i = 0; i < rhs.nc(); i += bs) + { + // make a rect for the block from rhs + rectangle rhs_block(i, c, std::min(i+bs-1,rhs.nc()-1), std::min(c+bs-1,rhs.nr()-1)); + + // make a target rect in res + rectangle res_block(rhs_block.left(),lhs_block.top(), rhs_block.right(), lhs_block.bottom()); + + // This loop is optimized assuming that the data is laid out in + // row major order in memory. + for (long r = lhs_block.top(); r <= lhs_block.bottom(); ++r) + { + for (long c = lhs_block.left(); c<= lhs_block.right(); ++c) + { + const typename EXP2::type temp = lhs(r,c); + for (long i = rhs_block.left(); i <= rhs_block.right(); ++i) + { + dest(r,i) += rhs(c,i)*temp; + } + } + } + } + } + } + } + + + } + +// ------------------------------------------------------------------------------------ + +} + +#endif // DLIB_MATRIx_DEFAULT_MULTIPLY_ + diff --git a/libs/dlib/matrix/matrix_eigenvalue.h b/libs/dlib/matrix/matrix_eigenvalue.h new file mode 100644 index 0000000..143b056 --- /dev/null +++ b/libs/dlib/matrix/matrix_eigenvalue.h @@ -0,0 +1,1376 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +// This code was adapted from code from the JAMA part of NIST's TNT library. +// See: http://math.nist.gov/tnt/ +#ifndef DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H +#define DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H + +#include "matrix.h" +#include "matrix_utilities.h" +#include "matrix_subexp.h" +#include +#include +#include + +#ifdef DLIB_USE_LAPACK +#include "lapack/geev.h" +#include "lapack/syev.h" +#include "lapack/syevr.h" +#endif + +#define DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH 4 + +namespace dlib +{ + + template < + typename matrix_exp_type + > + class eigenvalue_decomposition + { + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef typename matrix_exp_type::matrix_type matrix_type; + typedef matrix column_vector_type; + + typedef matrix,0,0,mem_manager_type,layout_type> complex_matrix_type; + typedef matrix,NR,1,mem_manager_type,layout_type> complex_column_vector_type; + + + // You have supplied an invalid type of matrix_exp_type. You have + // to use this object with matrices that contain float or double type data. + COMPILE_TIME_ASSERT((is_same_type::value || + is_same_type::value )); + + + template + eigenvalue_decomposition( + const matrix_exp& A + ); + + template + eigenvalue_decomposition( + const matrix_op >& A + ); + + long dim ( + ) const; + + const complex_column_vector_type get_eigenvalues ( + ) const; + + const column_vector_type& get_real_eigenvalues ( + ) const; + + const column_vector_type& get_imag_eigenvalues ( + ) const; + + const complex_matrix_type get_v ( + ) const; + + const complex_matrix_type get_d ( + ) const; + + const matrix_type& get_pseudo_v ( + ) const; + + const matrix_type get_pseudo_d ( + ) const; + + private: + + /** Row and column dimension (square matrix). */ + int n; + + bool issymmetric; + + /** Arrays for internal storage of eigenvalues. */ + + column_vector_type d; /* real part */ + column_vector_type e; /* img part */ + + /** Array for internal storage of eigenvectors. */ + matrix_type V; + + /** Array for internal storage of nonsymmetric Hessenberg form. + @serial internal storage of nonsymmetric Hessenberg form. + */ + matrix_type H; + + + /** Working storage for nonsymmetric algorithm. + @serial working storage for nonsymmetric algorithm. + */ + column_vector_type ort; + + // Symmetric Householder reduction to tridiagonal form. + void tred2(); + + + // Symmetric tridiagonal QL algorithm. + void tql2 (); + + + // Nonsymmetric reduction to Hessenberg form. + void orthes (); + + + // Complex scalar division. + type cdivr, cdivi; + void cdiv_(type xr, type xi, type yr, type yi); + + + // Nonsymmetric reduction from Hessenberg to real Schur form. + void hqr2 (); + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Public member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + template + eigenvalue_decomposition:: + eigenvalue_decomposition( + const matrix_exp& A__ + ) + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + + const_temp_matrix A(A__); + + // make sure requires clause is not broken + DLIB_ASSERT(A.nr() == A.nc() && A.size() > 0, + "\teigenvalue_decomposition::eigenvalue_decomposition(A)" + << "\n\tYou can only use this on square matrices" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + << "\n\tA.size(): " << A.size() + << "\n\tthis: " << this + ); + + + n = A.nc(); + V.set_size(n,n); + d.set_size(n); + e.set_size(n); + + + issymmetric = true; + for (int j = 0; (j < n) && issymmetric; j++) + { + for (int i = 0; (i < n) && issymmetric; i++) + { + issymmetric = (A(i,j) == A(j,i)); + } + } + + if (issymmetric) + { + V = A; + +#ifdef DLIB_USE_LAPACK + if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) + { + e = 0; + + // We could compute the result using syev() + //lapack::syev('V', 'L', V, d); + + // Instead, we use syevr because its faster and maybe more stable. + matrix_type tempA(A); + matrix isupz; + + lapack::integer temp; + lapack::syevr('V','A','L',tempA,0,0,0,0,-1,temp,d,V,isupz); + } +#endif + // Tridiagonalize. + tred2(); + + // Diagonalize. + tql2(); + + } + else + { + +#ifdef DLIB_USE_LAPACK + if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) + { + matrix temp, vl, vr; + temp = A; + lapack::geev('N', 'V', temp, d, e, vl, vr); + V = vr; + return; + } +#endif + H = A; + + ort.set_size(n); + + // Reduce to Hessenberg form. + orthes(); + + // Reduce Hessenberg to real Schur form. + hqr2(); + } + } + +// ---------------------------------------------------------------------------------------- + + template + template + eigenvalue_decomposition:: + eigenvalue_decomposition( + const matrix_op >& A + ) + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + + // make sure requires clause is not broken + DLIB_ASSERT(A.nr() == A.nc() && A.size() > 0, + "\teigenvalue_decomposition::eigenvalue_decomposition(A)" + << "\n\tYou can only use this on square matrices" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + << "\n\tA.size(): " << A.size() + << "\n\tthis: " << this + ); + + + n = A.nc(); + V.set_size(n,n); + d.set_size(n); + e.set_size(n); + + + V = A; + +#ifdef DLIB_USE_LAPACK + if (A.nr() > DLIB_LAPACK_EIGENVALUE_DECOMP_SIZE_THRESH) + { + e = 0; + + // We could compute the result using syev() + //lapack::syev('V', 'L', V, d); + + // Instead, we use syevr because its faster and maybe more stable. + matrix_type tempA(A); + matrix isupz; + + lapack::integer temp; + lapack::syevr('V','A','L',tempA,0,0,0,0,-1,temp,d,V,isupz); + return; + } +#endif + // Tridiagonalize. + tred2(); + + // Diagonalize. + tql2(); + + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::matrix_type& eigenvalue_decomposition:: + get_pseudo_v ( + ) const + { + return V; + } + +// ---------------------------------------------------------------------------------------- + + template + long eigenvalue_decomposition:: + dim ( + ) const + { + return V.nr(); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::complex_column_vector_type eigenvalue_decomposition:: + get_eigenvalues ( + ) const + { + return complex_matrix(get_real_eigenvalues(), get_imag_eigenvalues()); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::column_vector_type& eigenvalue_decomposition:: + get_real_eigenvalues ( + ) const + { + return d; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::column_vector_type& eigenvalue_decomposition:: + get_imag_eigenvalues ( + ) const + { + return e; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::complex_matrix_type eigenvalue_decomposition:: + get_d ( + ) const + { + return diagm(complex_matrix(get_real_eigenvalues(), get_imag_eigenvalues())); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::complex_matrix_type eigenvalue_decomposition:: + get_v ( + ) const + { + complex_matrix_type CV(n,n); + + for (int i = 0; i < n; i++) + { + if (e(i) > 0) + { + set_colm(CV,i) = complex_matrix(colm(V,i), colm(V,i+1)); + } + else if (e(i) < 0) + { + set_colm(CV,i) = complex_matrix(colm(V,i), colm(V,i-1)); + } + else + { + set_colm(CV,i) = complex_matrix(colm(V,i), uniform_matrix(n,1,0)); + } + } + + return CV; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename eigenvalue_decomposition::matrix_type eigenvalue_decomposition:: + get_pseudo_d ( + ) const + { + matrix_type D(n,n); + + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + D(i,j) = 0.0; + } + D(i,i) = d(i); + if (e(i) > 0) + { + D(i,i+1) = e(i); + } + else if (e(i) < 0) + { + D(i,i-1) = e(i); + } + } + + return D; + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Private member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// Symmetric Householder reduction to tridiagonal form. + template + void eigenvalue_decomposition:: + tred2() + { + using std::abs; + using std::sqrt; + + // This is derived from the Algol procedures tred2 by + // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + + for (int j = 0; j < n; j++) + { + d(j) = V(n-1,j); + } + + // Householder reduction to tridiagonal form. + + for (int i = n-1; i > 0; i--) + { + + // Scale to avoid under/overflow. + + type scale = 0.0; + type h = 0.0; + for (int k = 0; k < i; k++) + { + scale = scale + abs(d(k)); + } + if (scale == 0.0) + { + e(i) = d(i-1); + for (int j = 0; j < i; j++) + { + d(j) = V(i-1,j); + V(i,j) = 0.0; + V(j,i) = 0.0; + } + } + else + { + + // Generate Householder vector. + + for (int k = 0; k < i; k++) + { + d(k) /= scale; + h += d(k) * d(k); + } + type f = d(i-1); + type g = sqrt(h); + if (f > 0) + { + g = -g; + } + e(i) = scale * g; + h = h - f * g; + d(i-1) = f - g; + for (int j = 0; j < i; j++) + { + e(j) = 0.0; + } + + // Apply similarity transformation to remaining columns. + + for (int j = 0; j < i; j++) + { + f = d(j); + V(j,i) = f; + g = e(j) + V(j,j) * f; + for (int k = j+1; k <= i-1; k++) + { + g += V(k,j) * d(k); + e(k) += V(k,j) * f; + } + e(j) = g; + } + f = 0.0; + for (int j = 0; j < i; j++) + { + e(j) /= h; + f += e(j) * d(j); + } + type hh = f / (h + h); + for (int j = 0; j < i; j++) + { + e(j) -= hh * d(j); + } + for (int j = 0; j < i; j++) + { + f = d(j); + g = e(j); + for (int k = j; k <= i-1; k++) + { + V(k,j) -= (f * e(k) + g * d(k)); + } + d(j) = V(i-1,j); + V(i,j) = 0.0; + } + } + d(i) = h; + } + + // Accumulate transformations. + + for (int i = 0; i < n-1; i++) + { + V(n-1,i) = V(i,i); + V(i,i) = 1.0; + type h = d(i+1); + if (h != 0.0) + { + for (int k = 0; k <= i; k++) + { + d(k) = V(k,i+1) / h; + } + for (int j = 0; j <= i; j++) + { + type g = 0.0; + for (int k = 0; k <= i; k++) + { + g += V(k,i+1) * V(k,j); + } + for (int k = 0; k <= i; k++) + { + V(k,j) -= g * d(k); + } + } + } + for (int k = 0; k <= i; k++) + { + V(k,i+1) = 0.0; + } + } + for (int j = 0; j < n; j++) + { + d(j) = V(n-1,j); + V(n-1,j) = 0.0; + } + V(n-1,n-1) = 1.0; + e(0) = 0.0; + } + +// ---------------------------------------------------------------------------------------- + + template + void eigenvalue_decomposition:: + tql2 () + { + using std::pow; + using std::min; + using std::max; + using std::abs; + + // This is derived from the Algol procedures tql2, by + // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + + for (int i = 1; i < n; i++) + { + e(i-1) = e(i); + } + e(n-1) = 0.0; + + type f = 0.0; + type tst1 = 0.0; + const type eps = std::numeric_limits::epsilon(); + for (int l = 0; l < n; l++) + { + + // Find small subdiagonal element + + tst1 = max(tst1,abs(d(l)) + abs(e(l))); + int m = l; + + // Original while-loop from Java code + while (m < n) + { + if (abs(e(m)) <= eps*tst1) + { + break; + } + m++; + } + + + // If m == l, d(l) is an eigenvalue, + // otherwise, iterate. + + if (m > l) + { + int iter = 0; + do + { + iter = iter + 1; // (Could check iteration count here.) + + // Compute implicit shift + + type g = d(l); + type p = (d(l+1) - g) / (2.0 * e(l)); + type r = hypot(p,1.0); + if (p < 0) + { + r = -r; + } + d(l) = e(l) / (p + r); + d(l+1) = e(l) * (p + r); + type dl1 = d(l+1); + type h = g - d(l); + for (int i = l+2; i < n; i++) + { + d(i) -= h; + } + f = f + h; + + // Implicit QL transformation. + + p = d(m); + type c = 1.0; + type c2 = c; + type c3 = c; + type el1 = e(l+1); + type s = 0.0; + type s2 = 0.0; + for (int i = m-1; i >= l; i--) + { + c3 = c2; + c2 = c; + s2 = s; + g = c * e(i); + h = c * p; + r = hypot(p,e(i)); + e(i+1) = s * r; + s = e(i) / r; + c = p / r; + p = c * d(i) - s * g; + d(i+1) = h + s * (c * g + s * d(i)); + + // Accumulate transformation. + + for (int k = 0; k < n; k++) + { + h = V(k,i+1); + V(k,i+1) = s * V(k,i) + c * h; + V(k,i) = c * V(k,i) - s * h; + } + } + p = -s * s2 * c3 * el1 * e(l) / dl1; + e(l) = s * p; + d(l) = c * p; + + // Check for convergence. + + } while (abs(e(l)) > eps*tst1); + } + d(l) = d(l) + f; + e(l) = 0.0; + } + + /* + The code to sort the eigenvalues and eigenvectors + has been removed from here since, in the non-symmetric case, + we can't sort the eigenvalues in a meaningful way. If we left this + code in here then the user might supply what they thought was a symmetric + matrix but was actually slightly non-symmetric due to rounding error + and then they would end up in the non-symmetric eigenvalue solver + where the eigenvalues don't end up getting sorted. So to avoid + any possible user confusion I'm just removing this. + */ + } + +// ---------------------------------------------------------------------------------------- + + template + void eigenvalue_decomposition:: + orthes () + { + using std::abs; + using std::sqrt; + + // This is derived from the Algol procedures orthes and ortran, + // by Martin and Wilkinson, Handbook for Auto. Comp., + // Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutines in EISPACK. + + int low = 0; + int high = n-1; + + for (int m = low+1; m <= high-1; m++) + { + + // Scale column. + + type scale = 0.0; + for (int i = m; i <= high; i++) + { + scale = scale + abs(H(i,m-1)); + } + if (scale != 0.0) + { + + // Compute Householder transformation. + + type h = 0.0; + for (int i = high; i >= m; i--) + { + ort(i) = H(i,m-1)/scale; + h += ort(i) * ort(i); + } + type g = sqrt(h); + if (ort(m) > 0) + { + g = -g; + } + h = h - ort(m) * g; + ort(m) = ort(m) - g; + + // Apply Householder similarity transformation + // H = (I-u*u'/h)*H*(I-u*u')/h) + + for (int j = m; j < n; j++) + { + type f = 0.0; + for (int i = high; i >= m; i--) + { + f += ort(i)*H(i,j); + } + f = f/h; + for (int i = m; i <= high; i++) + { + H(i,j) -= f*ort(i); + } + } + + for (int i = 0; i <= high; i++) + { + type f = 0.0; + for (int j = high; j >= m; j--) + { + f += ort(j)*H(i,j); + } + f = f/h; + for (int j = m; j <= high; j++) + { + H(i,j) -= f*ort(j); + } + } + ort(m) = scale*ort(m); + H(m,m-1) = scale*g; + } + } + + // Accumulate transformations (Algol's ortran). + + for (int i = 0; i < n; i++) + { + for (int j = 0; j < n; j++) + { + V(i,j) = (i == j ? 1.0 : 0.0); + } + } + + for (int m = high-1; m >= low+1; m--) + { + if (H(m,m-1) != 0.0) + { + for (int i = m+1; i <= high; i++) + { + ort(i) = H(i,m-1); + } + for (int j = m; j <= high; j++) + { + type g = 0.0; + for (int i = m; i <= high; i++) + { + g += ort(i) * V(i,j); + } + // Double division avoids possible underflow + g = (g / ort(m)) / H(m,m-1); + for (int i = m; i <= high; i++) + { + V(i,j) += g * ort(i); + } + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + template + void eigenvalue_decomposition:: + cdiv_(type xr, type xi, type yr, type yi) + { + using std::abs; + type r,d; + if (abs(yr) > abs(yi)) + { + r = yi/yr; + d = yr + r*yi; + cdivr = (xr + r*xi)/d; + cdivi = (xi - r*xr)/d; + } + else + { + r = yr/yi; + d = yi + r*yr; + cdivr = (r*xr + xi)/d; + cdivi = (r*xi - xr)/d; + } + } + +// ---------------------------------------------------------------------------------------- + + template + void eigenvalue_decomposition:: + hqr2 () + { + using std::pow; + using std::min; + using std::max; + using std::abs; + using std::sqrt; + + // This is derived from the Algol procedure hqr2, + // by Martin and Wilkinson, Handbook for Auto. Comp., + // Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + + // Initialize + + int nn = this->n; + int n = nn-1; + int low = 0; + int high = nn-1; + const type eps = std::numeric_limits::epsilon(); + type exshift = 0.0; + type p=0,q=0,r=0,s=0,z=0,t,w,x,y; + + // Store roots isolated by balanc and compute matrix norm + + type norm = 0.0; + for (int i = 0; i < nn; i++) + { + if ((i < low) || (i > high)) + { + d(i) = H(i,i); + e(i) = 0.0; + } + for (int j = max(i-1,0); j < nn; j++) + { + norm = norm + abs(H(i,j)); + } + } + + // Outer loop over eigenvalue index + + int iter = 0; + while (n >= low) + { + + // Look for single small sub-diagonal element + + int l = n; + while (l > low) + { + s = abs(H(l-1,l-1)) + abs(H(l,l)); + if (s == 0.0) + { + s = norm; + } + if (abs(H(l,l-1)) < eps * s) + { + break; + } + l--; + } + + // Check for convergence + // One root found + + if (l == n) + { + H(n,n) = H(n,n) + exshift; + d(n) = H(n,n); + e(n) = 0.0; + n--; + iter = 0; + + // Two roots found + + } + else if (l == n-1) + { + w = H(n,n-1) * H(n-1,n); + p = (H(n-1,n-1) - H(n,n)) / 2.0; + q = p * p + w; + z = sqrt(abs(q)); + H(n,n) = H(n,n) + exshift; + H(n-1,n-1) = H(n-1,n-1) + exshift; + x = H(n,n); + + // type pair + + if (q >= 0) + { + if (p >= 0) + { + z = p + z; + } + else + { + z = p - z; + } + d(n-1) = x + z; + d(n) = d(n-1); + if (z != 0.0) + { + d(n) = x - w / z; + } + e(n-1) = 0.0; + e(n) = 0.0; + x = H(n,n-1); + s = abs(x) + abs(z); + p = x / s; + q = z / s; + r = sqrt(p * p+q * q); + p = p / r; + q = q / r; + + // Row modification + + for (int j = n-1; j < nn; j++) + { + z = H(n-1,j); + H(n-1,j) = q * z + p * H(n,j); + H(n,j) = q * H(n,j) - p * z; + } + + // Column modification + + for (int i = 0; i <= n; i++) + { + z = H(i,n-1); + H(i,n-1) = q * z + p * H(i,n); + H(i,n) = q * H(i,n) - p * z; + } + + // Accumulate transformations + + for (int i = low; i <= high; i++) + { + z = V(i,n-1); + V(i,n-1) = q * z + p * V(i,n); + V(i,n) = q * V(i,n) - p * z; + } + + // Complex pair + + } + else + { + d(n-1) = x + p; + d(n) = x + p; + e(n-1) = z; + e(n) = -z; + } + n = n - 2; + iter = 0; + + // No convergence yet + + } + else + { + + // Form shift + + x = H(n,n); + y = 0.0; + w = 0.0; + if (l < n) + { + y = H(n-1,n-1); + w = H(n,n-1) * H(n-1,n); + } + + // Wilkinson's original ad hoc shift + + if (iter == 10) + { + exshift += x; + for (int i = low; i <= n; i++) + { + H(i,i) -= x; + } + s = abs(H(n,n-1)) + abs(H(n-1,n-2)); + x = y = 0.75 * s; + w = -0.4375 * s * s; + } + + // MATLAB's new ad hoc shift + + if (iter == 30) + { + s = (y - x) / 2.0; + s = s * s + w; + if (s > 0) + { + s = sqrt(s); + if (y < x) + { + s = -s; + } + s = x - w / ((y - x) / 2.0 + s); + for (int i = low; i <= n; i++) + { + H(i,i) -= s; + } + exshift += s; + x = y = w = 0.964; + } + } + + iter = iter + 1; // (Could check iteration count here.) + + // Look for two consecutive small sub-diagonal elements + + int m = n-2; + while (m >= l) + { + z = H(m,m); + r = x - z; + s = y - z; + p = (r * s - w) / H(m+1,m) + H(m,m+1); + q = H(m+1,m+1) - z - r - s; + r = H(m+2,m+1); + s = abs(p) + abs(q) + abs(r); + p = p / s; + q = q / s; + r = r / s; + if (m == l) + { + break; + } + if (abs(H(m,m-1)) * (abs(q) + abs(r)) < + eps * (abs(p) * (abs(H(m-1,m-1)) + abs(z) + + abs(H(m+1,m+1))))) + { + break; + } + m--; + } + + for (int i = m+2; i <= n; i++) + { + H(i,i-2) = 0.0; + if (i > m+2) + { + H(i,i-3) = 0.0; + } + } + + // Double QR step involving rows l:n and columns m:n + + for (int k = m; k <= n-1; k++) + { + int notlast = (k != n-1); + if (k != m) + { + p = H(k,k-1); + q = H(k+1,k-1); + r = (notlast ? H(k+2,k-1) : 0.0); + x = abs(p) + abs(q) + abs(r); + if (x != 0.0) + { + p = p / x; + q = q / x; + r = r / x; + } + } + if (x == 0.0) + { + break; + } + s = sqrt(p * p + q * q + r * r); + if (p < 0) + { + s = -s; + } + if (s != 0) + { + if (k != m) + { + H(k,k-1) = -s * x; + } + else if (l != m) + { + H(k,k-1) = -H(k,k-1); + } + p = p + s; + x = p / s; + y = q / s; + z = r / s; + q = q / p; + r = r / p; + + // Row modification + + for (int j = k; j < nn; j++) + { + p = H(k,j) + q * H(k+1,j); + if (notlast) + { + p = p + r * H(k+2,j); + H(k+2,j) = H(k+2,j) - p * z; + } + H(k,j) = H(k,j) - p * x; + H(k+1,j) = H(k+1,j) - p * y; + } + + // Column modification + + for (int i = 0; i <= min(n,k+3); i++) + { + p = x * H(i,k) + y * H(i,k+1); + if (notlast) + { + p = p + z * H(i,k+2); + H(i,k+2) = H(i,k+2) - p * r; + } + H(i,k) = H(i,k) - p; + H(i,k+1) = H(i,k+1) - p * q; + } + + // Accumulate transformations + + for (int i = low; i <= high; i++) + { + p = x * V(i,k) + y * V(i,k+1); + if (notlast) + { + p = p + z * V(i,k+2); + V(i,k+2) = V(i,k+2) - p * r; + } + V(i,k) = V(i,k) - p; + V(i,k+1) = V(i,k+1) - p * q; + } + } // (s != 0) + } // k loop + } // check convergence + } // while (n >= low) + + // Backsubstitute to find vectors of upper triangular form + + if (norm == 0.0) + { + return; + } + + for (n = nn-1; n >= 0; n--) + { + p = d(n); + q = e(n); + + // Real vector + + if (q == 0) + { + int l = n; + H(n,n) = 1.0; + for (int i = n-1; i >= 0; i--) + { + w = H(i,i) - p; + r = 0.0; + for (int j = l; j <= n; j++) + { + r = r + H(i,j) * H(j,n); + } + if (e(i) < 0.0) + { + z = w; + s = r; + } + else + { + l = i; + if (e(i) == 0.0) + { + if (w != 0.0) + { + H(i,n) = -r / w; + } + else + { + H(i,n) = -r / (eps * norm); + } + + // Solve real equations + + } + else + { + x = H(i,i+1); + y = H(i+1,i); + q = (d(i) - p) * (d(i) - p) + e(i) * e(i); + t = (x * s - z * r) / q; + H(i,n) = t; + if (abs(x) > abs(z)) + { + H(i+1,n) = (-r - w * t) / x; + } + else + { + H(i+1,n) = (-s - y * t) / z; + } + } + + // Overflow control + + t = abs(H(i,n)); + if ((eps * t) * t > 1) + { + for (int j = i; j <= n; j++) + { + H(j,n) = H(j,n) / t; + } + } + } + } + + // Complex vector + + } + else if (q < 0) + { + int l = n-1; + + // Last vector component imaginary so matrix is triangular + + if (abs(H(n,n-1)) > abs(H(n-1,n))) + { + H(n-1,n-1) = q / H(n,n-1); + H(n-1,n) = -(H(n,n) - p) / H(n,n-1); + } + else + { + cdiv_(0.0,-H(n-1,n),H(n-1,n-1)-p,q); + H(n-1,n-1) = cdivr; + H(n-1,n) = cdivi; + } + H(n,n-1) = 0.0; + H(n,n) = 1.0; + for (int i = n-2; i >= 0; i--) + { + type ra,sa,vr,vi; + ra = 0.0; + sa = 0.0; + for (int j = l; j <= n; j++) + { + ra = ra + H(i,j) * H(j,n-1); + sa = sa + H(i,j) * H(j,n); + } + w = H(i,i) - p; + + if (e(i) < 0.0) + { + z = w; + r = ra; + s = sa; + } + else + { + l = i; + if (e(i) == 0) + { + cdiv_(-ra,-sa,w,q); + H(i,n-1) = cdivr; + H(i,n) = cdivi; + } + else + { + + // Solve complex equations + + x = H(i,i+1); + y = H(i+1,i); + vr = (d(i) - p) * (d(i) - p) + e(i) * e(i) - q * q; + vi = (d(i) - p) * 2.0 * q; + if ((vr == 0.0) && (vi == 0.0)) + { + vr = eps * norm * (abs(w) + abs(q) + + abs(x) + abs(y) + abs(z)); + } + cdiv_(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi); + H(i,n-1) = cdivr; + H(i,n) = cdivi; + if (abs(x) > (abs(z) + abs(q))) + { + H(i+1,n-1) = (-ra - w * H(i,n-1) + q * H(i,n)) / x; + H(i+1,n) = (-sa - w * H(i,n) - q * H(i,n-1)) / x; + } + else + { + cdiv_(-r-y*H(i,n-1),-s-y*H(i,n),z,q); + H(i+1,n-1) = cdivr; + H(i+1,n) = cdivi; + } + } + + // Overflow control + + t = max(abs(H(i,n-1)),abs(H(i,n))); + if ((eps * t) * t > 1) + { + for (int j = i; j <= n; j++) + { + H(j,n-1) = H(j,n-1) / t; + H(j,n) = H(j,n) / t; + } + } + } + } + } + } + + // Vectors of isolated roots + + for (int i = 0; i < nn; i++) + { + if (i < low || i > high) + { + for (int j = i; j < nn; j++) + { + V(i,j) = H(i,j); + } + } + } + + // Back transformation to get eigenvectors of original matrix + + for (int j = nn-1; j >= low; j--) + { + for (int i = low; i <= high; i++) + { + z = 0.0; + for (int k = low; k <= min(j,high); k++) + { + z = z + V(i,k) * H(k,j); + } + V(i,j) = z; + } + } + } + +// ---------------------------------------------------------------------------------------- + + +} + +#endif // DLIB_MATRIX_EIGENVALUE_DECOMPOSITION_H + + + + diff --git a/libs/dlib/matrix/matrix_exp.h b/libs/dlib/matrix/matrix_exp.h new file mode 100644 index 0000000..609e8e6 --- /dev/null +++ b/libs/dlib/matrix/matrix_exp.h @@ -0,0 +1,209 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_EXP_h_ +#define DLIB_MATRIx_EXP_h_ + +#include "../algs.h" +#include "../is_kind.h" +#include "matrix_fwd.h" +#include "matrix_exp_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // We want to return the compile time constant if our NR and NC dimensions + // aren't zero but if they are then we want to call ref_.nx() and return + // the correct values. + template < typename exp_type, long NR > + struct get_nr_helper + { + static inline long get(const exp_type&) { return NR; } + }; + + template < typename exp_type > + struct get_nr_helper + { + static inline long get(const exp_type& m) { return m.nr(); } + }; + + template < typename exp_type, long NC > + struct get_nc_helper + { + static inline long get(const exp_type&) { return NC; } + }; + + template < typename exp_type > + struct get_nc_helper + { + static inline long get(const exp_type& m) { return m.nc(); } + }; + + template + struct matrix_traits + { + typedef typename EXP::type type; + typedef typename EXP::const_ret_type const_ret_type; + typedef typename EXP::mem_manager_type mem_manager_type; + typedef typename EXP::layout_type layout_type; + const static long NR = EXP::NR; + const static long NC = EXP::NC; + const static long cost = EXP::cost; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + class matrix_exp + { + /*! + REQUIREMENTS ON EXP + EXP should be something convertible to a matrix_exp. That is, + it should inherit from matrix_exp + !*/ + + public: + typedef typename matrix_traits::type type; + typedef type value_type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + typedef typename matrix_traits::layout_type layout_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + + typedef matrix matrix_type; + typedef EXP exp_type; + + inline const_ret_type operator() ( + long r, + long c + ) const + { + DLIB_ASSERT(r < nr() && c < nc() && r >= 0 && c >= 0, + "\tconst type matrix_exp::operator(r,c)" + << "\n\tYou must give a valid row and column" + << "\n\tr: " << r + << "\n\tc: " << c + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + return ref()(r,c); + } + + const_ret_type operator() ( + long i + ) const + { + COMPILE_TIME_ASSERT(NC == 1 || NC == 0 || NR == 1 || NR == 0); + DLIB_ASSERT(nc() == 1 || nr() == 1, + "\tconst type matrix_exp::operator(i)" + << "\n\tYou can only use this operator on column or row vectors" + << "\n\ti: " << i + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + DLIB_ASSERT( ((nc() == 1 && i < nr()) || (nr() == 1 && i < nc())) && i >= 0, + "\tconst type matrix_exp::operator(i)" + << "\n\tYou must give a valid row/column number" + << "\n\ti: " << i + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + if (nc() == 1) + return ref()(i,0); + else + return ref()(0,i); + } + + long size ( + ) const { return nr()*nc(); } + + long nr ( + ) const { return get_nr_helper::get(ref()); } + + long nc ( + ) const { return get_nc_helper::get(ref()); } + + template + bool aliases ( + const matrix_exp& item + ) const { return ref().aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return ref().destructively_aliases(item); } + + inline const exp_type& ref ( + ) const { return *static_cast(this); } + + inline operator const type ( + ) const + { + COMPILE_TIME_ASSERT(NC == 1 || NC == 0); + COMPILE_TIME_ASSERT(NR == 1 || NR == 0); + DLIB_ASSERT(nr() == 1 && nc() == 1, + "\tmatrix_exp::operator const type() const" + << "\n\tYou can only use this operator on a 1x1 matrix" + << "\n\tnr(): " << nr() + << "\n\tnc(): " << nc() + << "\n\tthis: " << this + ); + + // Put the expression contained in this matrix_exp into + // a temporary 1x1 matrix so that the expression will encounter + // all the overloads of matrix_assign() and have the chance to + // go through any applicable optimizations. + matrix temp(ref()); + return temp(0); + } + + protected: + matrix_exp() {} + matrix_exp(const matrix_exp& ) {} + + private: + + matrix_exp& operator= (const matrix_exp&); + }; + +// ---------------------------------------------------------------------------------------- + + // something is a matrix if it is convertible to a matrix_exp object + template + struct is_matrix& > >::type > + { static const bool value = true; }; + /* + is_matrix::value == 1 if T is a matrix type else 0 + */ + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + class matrix_diag_exp : public matrix_exp + { + /*! + This is a matrix expression type used to represent diagonal matrices. + That is, square matrices with all off diagonal elements equal to 0. + !*/ + + protected: + matrix_diag_exp() {} + matrix_diag_exp(const matrix_diag_exp& item ):matrix_exp(item) {} + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_EXP_h_ + diff --git a/libs/dlib/matrix/matrix_exp_abstract.h b/libs/dlib/matrix/matrix_exp_abstract.h new file mode 100644 index 0000000..ae3eb56 --- /dev/null +++ b/libs/dlib/matrix/matrix_exp_abstract.h @@ -0,0 +1,187 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_EXP_ABSTRACT_ +#ifdef DLIB_MATRIx_EXP_ABSTRACT_ + +#include "matrix_fwd.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + class matrix_exp + { + /*! + REQUIREMENTS ON EXP + - must be an object that inherits publicly from matrix_exp (this class). + + WHAT THIS OBJECT REPRESENTS + This object represents an expression that evaluates to a matrix + of nr() rows and nc() columns. + + The reason for having an object that represents an expression is that it + allows us to use the "expression templates" technique to eliminate the + temporary matrix objects that would normally be returned from expressions + such as M = A+B+C+D; Normally each invocation of the + operator would + construct and return a temporary matrix object but using this technique we + can avoid creating all of these temporary objects and receive a large + speed boost. + + Note that every time you invoke operator() on this object it recomputes + its result which may not be what you want to do. For example, if you + are going to be accessing the same element over and over it might + be faster to assign the matrix_exp to a temporary matrix and then + use that temporary. + + + const_ret_type typedef (defined below) + The purpose of the const_ret_type typedef is to allow matrix expressions + to return their elements by reference when appropriate. So const_ret_type + should be one of the following types: + - const type + - const type& + !*/ + + public: + typedef typename EXP::type type; + typedef type value_type; // Redefined for compatibility with the STL + typedef typename EXP::const_ret_type const_ret_type; + typedef typename EXP::mem_manager_type mem_manager_type; + typedef typename EXP::layout_type layout_type; + const static long cost = EXP::cost; + const static long NR = EXP::NR; + const static long NC = EXP::NC; + typedef matrix matrix_type; + typedef EXP exp_type; + + const_ret_type operator() ( + long r, + long c + ) const; + /*! + requires + - 0 <= r < nr() + - 0 <= c < nc() + ensures + - returns ref()(r,c) + (i.e. returns the value at the given row and column that would be in + the matrix represented by this matrix expression) + !*/ + + const_ret_type operator() ( + long i + ) const; + /*! + requires + - nc() == 1 || nr() == 1 (i.e. this must be a column or row vector) + - if (nc() == 1) then + - 0 <= i < nr() + - else + - 0 <= i < nc() + ensures + - if (nc() == 1) then + - returns (*this)(i,0) + - else + - returns (*this)(0,i) + !*/ + + operator const type ( + ) const; + /*! + requires + - nr() == 1 + - nc() == 1 + ensures + - returns (*this)(0,0) + !*/ + + long nr ( + ) const; + /*! + ensures + - returns the number of rows in this matrix expression. + !*/ + + long nc ( + ) const; + /*! + ensures + - returns the number of columns in this matrix expression. + !*/ + + long size ( + ) const; + /*! + ensures + - returns nr()*nc() + !*/ + + template + bool aliases ( + const matrix_exp& item + ) const; + /*! + ensures + - if (A change to the state of item could cause a change to the state of *this + matrix_exp object. ) then + - returns true + - This happens when this matrix_exp contains item in some way. + - else + - returns false + !*/ + + template + bool destructively_aliases ( + const matrix_exp& item + ) const; + /*! + ensures + - if (aliases(item)) then + - if (nr() != item.nr() || nc() != item.nc() + - returns true + (i.e. if this expression has different dimensions than item then + we have destructive aliasing) + + - returns true if the following assignment would evaluate incorrectly: + for (long r = 0; r < nr(); ++r) + for (long c = 0; c < nc(); ++c) + item(r,c) = (*this)(r,c) + - That is, if this matrix expression aliases item in such a way that a modification + to element item(r,c) causes a change in the value of something other than + (*this)(r,c) then this function returns true. + + - returns false if none of the above conditions say we should return true + - else + - returns false + !*/ + + inline const exp_type& ref ( + ) const; + /*! + ensures + - returns a reference to the expression contained in *this. + (i.e. returns *static_cast(this) ) + !*/ + + protected: + + // Only derived classes of matrix_exp may call the matrix_exp constructors. + matrix_exp(const matrix_exp&); + matrix_exp(); + + private: + // no one may ever use the assignment operator on a matrix_exp + matrix_exp& operator= (const matrix_exp&); + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_EXP_ABSTRACT_ + + diff --git a/libs/dlib/matrix/matrix_expressions.h b/libs/dlib/matrix/matrix_expressions.h new file mode 100644 index 0000000..4442ce2 --- /dev/null +++ b/libs/dlib/matrix/matrix_expressions.h @@ -0,0 +1,280 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_EXPRESSIONS_H_ +#define DLIB_MATRIx_EXPRESSIONS_H_ + +#include "matrix_fwd.h" + +#ifdef _MSC_VER +// This #pragma directive is also located in the algs.h file but for whatever +// reason visual studio 9 just ignores it when it is only there. + +// this is to disable the "'this' : used in base member initializer list" +// warning you get from some of the GUI objects since all the objects +// require that their parent class be passed into their constructor. +// In this case though it is totally safe so it is ok to disable this warning. +#pragma warning(disable : 4355) +#endif + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Helper templates for making operators used by expression objects +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + class matrix_range_exp; + + template + struct matrix_traits > + { + typedef T type; + typedef const T const_ret_type; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + const static long NR = 1; + const static long NC = 0; + const static long cost = 1; + }; + + template + class matrix_range_exp : public matrix_exp > + { + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + + matrix_range_exp ( + T start_, + T end_ + ) + { + start = start_; + if (start_ <= end_) + inc = 1; + else + inc = -1; + nc_ = std::abs(end_ - start_) + 1; + } + matrix_range_exp ( + T start_, + T inc_, + T end_ + ) + { + start = start_; + nc_ = std::abs(end_ - start_)/inc_ + 1; + if (start_ <= end_) + inc = inc_; + else + inc = -inc_; + } + + matrix_range_exp ( + T start_, + T end_, + long num, + bool + ) + { + start = start_; + nc_ = num; + if (num > 1) + { + inc = (end_-start_)/(num-1); + } + else + { + inc = 0; + start = end_; + } + + } + + const_ret_type operator() ( + long, + long c + ) const { return start + c*inc; } + + const_ret_type operator() ( + long c + ) const { return start + c*inc; } + + template + bool aliases ( + const matrix_exp& + ) const { return false; } + + template + bool destructively_aliases ( + const matrix_exp& + ) const { return false; } + + long nr ( + ) const { return NR; } + + long nc ( + ) const { return nc_; } + + long nc_; + T start; + T inc; + }; + +// ---------------------------------------------------------------------------------------- + + template + class matrix_log_range_exp; + + template + struct matrix_traits > + { + typedef T type; + typedef const T const_ret_type; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + const static long NR = 1; + const static long NC = 0; + const static long cost = 1; + }; + + template + class matrix_log_range_exp : public matrix_exp > + { + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + + matrix_log_range_exp ( + T start_, + T end_, + long num + ) + { + start = start_; + nc_ = num; + if (num > 1) + { + inc = (end_-start_)/(num-1); + } + else + { + inc = 0; + start = end_; + } + + } + + const_ret_type operator() ( + long, + long c + ) const { return std::pow((T)10,start + c*inc); } + + const_ret_type operator() ( + long c + ) const { return std::pow((T)10,start + c*inc); } + + template + bool aliases ( + const matrix_exp& + ) const { return false; } + + template + bool destructively_aliases ( + const matrix_exp& + ) const { return false; } + + long nr ( + ) const { return NR; } + + long nc ( + ) const { return nc_; } + + long nc_; + T start; + T inc; + }; + +// ---------------------------------------------------------------------------------------- + + template + class matrix_range_static_exp; + + template + struct matrix_traits > + { + typedef long type; + typedef const long const_ret_type; + typedef default_memory_manager mem_manager_type; + const static long NR = 1; + const static long NC = tabs<(end - start)>::value/inc_ + 1; + const static long cost = 1; + typedef row_major_layout layout_type; + }; + + template + class matrix_range_static_exp : public matrix_exp > + { + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + typedef typename matrix_traits::layout_type layout_type; + + const static long inc = (start <= end)?inc_:-inc_; + + + matrix_range_static_exp ( + ) {} + + const_ret_type operator() ( + long , + long c + ) const { return start + c*inc; } + + const_ret_type operator() ( + long c + ) const { return start + c*inc; } + + template + bool aliases ( + const matrix_exp& + ) const { return false; } + + template + bool destructively_aliases ( + const matrix_exp& + ) const { return false; } + + long nr ( + ) const { return NR; } + + long nc ( + ) const { return NC; } + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_EXPRESSIONS_H_ + diff --git a/libs/dlib/matrix/matrix_fwd.h b/libs/dlib/matrix/matrix_fwd.h new file mode 100644 index 0000000..1f40a17 --- /dev/null +++ b/libs/dlib/matrix/matrix_fwd.h @@ -0,0 +1,31 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_FWD +#define DLIB_MATRIx_FWD + +#include "../algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct row_major_layout; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long num_rows = 0, + long num_cols = 0, + typename mem_manager = default_memory_manager, + typename layout = row_major_layout + > + class matrix; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_FWD + diff --git a/libs/dlib/matrix/matrix_la.h b/libs/dlib/matrix/matrix_la.h new file mode 100644 index 0000000..2a59e11 --- /dev/null +++ b/libs/dlib/matrix/matrix_la.h @@ -0,0 +1,1529 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_LA_FUNCTS_ +#define DLIB_MATRIx_LA_FUNCTS_ + +#include "matrix_la_abstract.h" +#include "matrix_utilities.h" + +// The 4 decomposition objects described in the matrix_la_abstract.h file are +// actually implemented in the following 4 files. +#include "matrix_lu.h" +#include "matrix_qr.h" +#include "matrix_cholesky.h" +#include "matrix_eigenvalue.h" + +#ifdef DLIB_USE_LAPACK +#include "lapack/potrf.h" +#include "lapack/gesdd.h" +#include "lapack/gesvd.h" +#endif + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + namespace nric + { + // This namespace contains stuff adapted from the algorithms + // described in the book Numerical Recipes in C + + template + inline T pythag(const T& a, const T& b) + { + T absa,absb; + absa=std::abs(a); + absb=std::abs(b); + if (absa > absb) + { + T val = absb/absa; + val *= val; + return absa*std::sqrt(1.0+val); + } + else + { + if (absb == 0.0) + { + return 0.0; + } + else + { + T val = absa/absb; + val *= val; + return absb*std::sqrt(1.0+val); + } + } + } + + template + inline T sign(const T& a, const T& b) + { + if (b < 0) + { + return -std::abs(a); + } + else + { + return std::abs(a); + } + } + + + template < + typename T, + long M, long N, + long wN, long wX, + long vN, + long rN, long rX, + typename MM1, + typename MM2, + typename MM3, + typename MM4, + typename L1, + typename L2, + typename L3, + typename L4 + > + bool svdcmp( + matrix& a, + matrix& w, + matrix& v, + matrix& rv1 + ) + /*! ( this function is derived from the one in numerical recipes in C chapter 2.6) + requires + - w.nr() == a.nc() + - w.nc() == 1 + - v.nr() == a.nc() + - v.nc() == a.nc() + - rv1.nr() == a.nc() + - rv1.nc() == 1 + ensures + - computes the singular value decomposition of a + - let W be the matrix such that diag(W) == #w then: + - a == #a*W*trans(#v) + - trans(#a)*#a == identity matrix + - trans(#v)*#v == identity matrix + - #rv1 == some undefined value + - returns true for success and false for failure + !*/ + { + + DLIB_ASSERT( + w.nr() == a.nc() && + w.nc() == 1 && + v.nr() == a.nc() && + v.nc() == a.nc() && + rv1.nr() == a.nc() && + rv1.nc() == 1, ""); + + COMPILE_TIME_ASSERT(wX == 0 || wX == 1); + COMPILE_TIME_ASSERT(rX == 0 || rX == 1); + + const T one = 1.0; + const long max_iter = 300; + const long n = a.nc(); + const long m = a.nr(); + const T eps = std::numeric_limits::epsilon(); + long nm = 0, l = 0; + bool flag; + T anorm,c,f,g,h,s,scale,x,y,z; + g = 0.0; + scale = 0.0; + anorm = 0.0; + + for (long i = 0; i < n; ++i) + { + l = i+1; + rv1(i) = scale*g; + g = s = scale = 0.0; + if (i < m) + { + for (long k = i; k < m; ++k) + scale += std::abs(a(k,i)); + + if (scale) + { + for (long k = i; k < m; ++k) + { + a(k,i) /= scale; + s += a(k,i)*a(k,i); + } + f = a(i,i); + g = -sign(std::sqrt(s),f); + h = f*g - s; + a(i,i) = f - g; + for (long j = l; j < n; ++j) + { + s = 0.0; + for (long k = i; k < m; ++k) + s += a(k,i)*a(k,j); + + f = s/h; + + for (long k = i; k < m; ++k) + a(k,j) += f*a(k,i); + } + for (long k = i; k < m; ++k) + a(k,i) *= scale; + } + } + + w(i) = scale *g; + + g=s=scale=0.0; + + if (i < m && i < n-1) + { + for (long k = l; k < n; ++k) + scale += std::abs(a(i,k)); + + if (scale) + { + for (long k = l; k < n; ++k) + { + a(i,k) /= scale; + s += a(i,k)*a(i,k); + } + f = a(i,l); + g = -sign(std::sqrt(s),f); + h = f*g - s; + a(i,l) = f - g; + + for (long k = l; k < n; ++k) + rv1(k) = a(i,k)/h; + + for (long j = l; j < m; ++j) + { + s = 0.0; + for (long k = l; k < n; ++k) + s += a(j,k)*a(i,k); + + for (long k = l; k < n; ++k) + a(j,k) += s*rv1(k); + } + for (long k = l; k < n; ++k) + a(i,k) *= scale; + } + } + anorm = std::max(anorm,(std::abs(w(i))+std::abs(rv1(i)))); + } + for (long i = n-1; i >= 0; --i) + { + if (i < n-1) + { + if (g != 0) + { + for (long j = l; j < n ; ++j) + v(j,i) = (a(i,j)/a(i,l))/g; + + for (long j = l; j < n; ++j) + { + s = 0.0; + for (long k = l; k < n; ++k) + s += a(i,k)*v(k,j); + + for (long k = l; k < n; ++k) + v(k,j) += s*v(k,i); + } + } + + for (long j = l; j < n; ++j) + v(i,j) = v(j,i) = 0.0; + } + + v(i,i) = 1.0; + g = rv1(i); + l = i; + } + + for (long i = std::min(m,n)-1; i >= 0; --i) + { + l = i + 1; + g = w(i); + + for (long j = l; j < n; ++j) + a(i,j) = 0.0; + + if (g != 0) + { + g = 1.0/g; + + for (long j = l; j < n; ++j) + { + s = 0.0; + for (long k = l; k < m; ++k) + s += a(k,i)*a(k,j); + + f=(s/a(i,i))*g; + + for (long k = i; k < m; ++k) + a(k,j) += f*a(k,i); + } + for (long j = i; j < m; ++j) + a(j,i) *= g; + } + else + { + for (long j = i; j < m; ++j) + a(j,i) = 0.0; + } + + ++a(i,i); + } + + for (long k = n-1; k >= 0; --k) + { + for (long its = 1; its <= max_iter; ++its) + { + flag = true; + for (l = k; l >= 1; --l) + { + nm = l - 1; + if (std::abs(rv1(l)) <= eps*anorm) + { + flag = false; + break; + } + if (std::abs(w(nm)) <= eps*anorm) + { + break; + } + } + + if (flag) + { + c = 0.0; + s = 1.0; + for (long i = l; i <= k; ++i) + { + f = s*rv1(i); + rv1(i) = c*rv1(i); + if (std::abs(f) <= eps*anorm) + break; + + g = w(i); + h = pythag(f,g); + w(i) = h; + h = 1.0/h; + c = g*h; + s = -f*h; + for (long j = 0; j < m; ++j) + { + y = a(j,nm); + z = a(j,i); + a(j,nm) = y*c + z*s; + a(j,i) = z*c - y*s; + } + } + } + + z = w(k); + if (l == k) + { + if (z < 0.0) + { + w(k) = -z; + for (long j = 0; j < n; ++j) + v(j,k) = -v(j,k); + } + break; + } + + if (its == max_iter) + return false; + + x = w(l); + nm = k - 1; + y = w(nm); + g = rv1(nm); + h = rv1(k); + f = ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y); + g = pythag(f,one); + f = ((x-z)*(x+z) + h*((y/(f+sign(g,f)))-h))/x; + c = s = 1.0; + for (long j = l; j <= nm; ++j) + { + long i = j + 1; + g = rv1(i); + y = w(i); + h = s*g; + g = c*g; + z = pythag(f,h); + rv1(j) = z; + c = f/z; + s = h/z; + f = x*c + g*s; + g = g*c - x*s; + h = y*s; + y *= c; + for (long jj = 0; jj < n; ++jj) + { + x = v(jj,j); + z = v(jj,i); + v(jj,j) = x*c + z*s; + v(jj,i) = z*c - x*s; + } + z = pythag(f,h); + w(j) = z; + if (z != 0) + { + z = 1.0/z; + c = f*z; + s = h*z; + } + f = c*g + s*y; + x = c*y - s*g; + for (long jj = 0; jj < m; ++jj) + { + y = a(jj,j); + z = a(jj,i); + a(jj,j) = y*c + z*s; + a(jj,i) = z*c - y*s; + } + } + rv1(l) = 0.0; + rv1(k) = f; + w(k) = x; + } + } + return true; + } + + // ------------------------------------------------------------------------------------ + + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + long qN, long qX, + long uM, + long vN, + typename MM1, + typename MM2, + typename MM3, + typename L1 + > + long svd2 ( + bool withu, + bool withv, + const matrix_exp& a, + matrix& u, + matrix& q, + matrix& v + ) + { + /* + Singular value decomposition. Translated to 'C' from the + original Algol code in "Handbook for Automatic Computation, + vol. II, Linear Algebra", Springer-Verlag. Note that this + published algorithm is considered to be the best and numerically + stable approach to computing the real-valued svd and is referenced + repeatedly in ieee journal papers, etc where the svd is used. + + This is almost an exact translation from the original, except that + an iteration counter is added to prevent stalls. This corresponds + to similar changes in other translations. + + Returns an error code = 0, if no errors and 'k' if a failure to + converge at the 'kth' singular value. + + USAGE: given the singular value decomposition a = u * diagm(q) * trans(v) for an m*n + matrix a with m >= n ... + After the svd call u is an m x m matrix which is columnwise + orthogonal. q will be an n element vector consisting of singular values + and v an n x n orthogonal matrix. eps and tol are tolerance constants. + Suitable values are eps=1e-16 and tol=(1e-300)/eps if T == double. + + If withu == false then u won't be computed and similarly if withv == false + then v won't be computed. + */ + + const long NR = matrix_exp::NR; + const long NC = matrix_exp::NC; + + // make sure the output matrices have valid dimensions if they are statically dimensioned + COMPILE_TIME_ASSERT(qX == 0 || qX == 1); + COMPILE_TIME_ASSERT(NR == 0 || uM == 0 || NR == uM); + COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); + + DLIB_ASSERT(a.nr() >= a.nc(), + "\tconst matrix_exp svd2()" + << "\n\tYou have given an invalidly sized matrix" + << "\n\ta.nr(): " << a.nr() + << "\n\ta.nc(): " << a.nc() + ); + + + typedef typename EXP::type T; + +#ifdef DLIB_USE_LAPACK + matrix temp(a); + + char jobu = 'A'; + char jobvt = 'A'; + if (withu == false) + jobu = 'N'; + if (withv == false) + jobvt = 'N'; + + int info; + if (withu == withv) + { + info = lapack::gesdd(jobu, temp, q, u, v); + } + else + { + info = lapack::gesvd(jobu, jobvt, temp, q, u, v); + } + + // pad q with zeros if it isn't the length we want + if (q.nr() < a.nc()) + q = join_cols(q, zeros_matrix(a.nc()-q.nr(),1)); + + v = trans(v); + + return info; +#else + using std::abs; + using std::sqrt; + + T eps = std::numeric_limits::epsilon(); + T tol = std::numeric_limits::min()/eps; + + const long m = a.nr(); + const long n = a.nc(); + long i, j, k, l = 0, l1, iter, retval; + T c, f, g, h, s, x, y, z; + + matrix e(n,1); + q.set_size(n,1); + u.set_size(m,m); + retval = 0; + + if (withv) + { + v.set_size(n,n); + } + + /* Copy 'a' to 'u' */ + for (i=0; i x) + x = y; + } /* end i */ + + /* accumulation of right-hand transformations */ + if (withv) + { + for (i=n-1; i>=0; i--) + { + if (g != 0.0) + { + h = u(i,i+1) * g; + + for (j=l; j=0; i--) + { + l = i + 1; + g = q(i); + + for (j=l; j=0; k--) + { + iter = 0; + +test_f_splitting: + + for (l=k; l>=0; l--) + { + if (abs(e(l)) <= eps) + goto test_f_convergence; + + if (abs(q(l-1)) <= eps) + goto cancellation; + } /* end l */ + + /* cancellation of e(l) if l > 0 */ + +cancellation: + + c = 0.0; + s = 1.0; + l1 = l - 1; + + for (i=l; i<=k; i++) + { + f = s * e(i); + e(i) *= c; + + if (abs(f) <= eps) + goto test_f_convergence; + + g = q(i); + h = q(i) = sqrt(f*f + g*g); + c = g / h; + s = -f / h; + + if (withu) + { + for (j=0; j 300) + { + retval = k; + break; + } + x = q(l); + y = q(k-1); + g = e(k-1); + h = e(k); + f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2 * h * y); + g = sqrt(f * f + 1.0); + f = ((x - z) * (x + z) + h * (y / ((f < 0)?(f - g) : (f + g)) - h)) / x; + + /* next QR transformation */ + c = s = 1.0; + + for (i=l+1; i<=k; i++) + { + g = e(i); + y = q(i); + h = s * g; + g *= c; + e(i-1) = z = sqrt(f * f + h * h); + c = f / z; + s = h / z; + f = x * c + g * s; + g = -x * s + g * c; + h = y * s; + y *= c; + + if (withv) + { + for (j=0;j + struct inv_helper + { + static const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) + { + using namespace nric; + typedef typename EXP::mem_manager_type MM; + // you can't invert a non-square matrix + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC || + matrix_exp::NR == 0 || + matrix_exp::NC == 0); + DLIB_ASSERT(m.nr() == m.nc(), + "\tconst matrix_exp::type inv(const matrix_exp& m)" + << "\n\tYou can only apply inv() to a square matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef typename matrix_exp::type type; + + lu_decomposition lu(m); + return lu.solve(identity_matrix(m.nr())); + } + }; + + template < + typename EXP + > + struct inv_helper + { + static const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + matrix a; + a(0) = 1/m(0); + return a; + } + }; + + template < + typename EXP + > + struct inv_helper + { + static const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + matrix a; + type d = static_cast(1.0/det(m)); + a(0,0) = m(1,1)*d; + a(0,1) = m(0,1)*-d; + a(1,0) = m(1,0)*-d; + a(1,1) = m(0,0)*d; + return a; + } + }; + + template < + typename EXP + > + struct inv_helper + { + static const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + matrix ret; + const type de = static_cast(1.0/det(m)); + const type a = m(0,0); + const type b = m(0,1); + const type c = m(0,2); + const type d = m(1,0); + const type e = m(1,1); + const type f = m(1,2); + const type g = m(2,0); + const type h = m(2,1); + const type i = m(2,2); + + ret(0,0) = (e*i - f*h)*de; + ret(1,0) = (f*g - d*i)*de; + ret(2,0) = (d*h - e*g)*de; + + ret(0,1) = (c*h - b*i)*de; + ret(1,1) = (a*i - c*g)*de; + ret(2,1) = (b*g - a*h)*de; + + ret(0,2) = (b*f - c*e)*de; + ret(1,2) = (c*d - a*f)*de; + ret(2,2) = (a*e - b*d)*de; + + return ret; + } + }; + + template < + typename EXP + > + struct inv_helper + { + static const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + matrix ret; + const type de = static_cast(1.0/det(m)); + ret(0,0) = det(removerc<0,0>(m)); + ret(0,1) = -det(removerc<0,1>(m)); + ret(0,2) = det(removerc<0,2>(m)); + ret(0,3) = -det(removerc<0,3>(m)); + + ret(1,0) = -det(removerc<1,0>(m)); + ret(1,1) = det(removerc<1,1>(m)); + ret(1,2) = -det(removerc<1,2>(m)); + ret(1,3) = det(removerc<1,3>(m)); + + ret(2,0) = det(removerc<2,0>(m)); + ret(2,1) = -det(removerc<2,1>(m)); + ret(2,2) = det(removerc<2,2>(m)); + ret(2,3) = -det(removerc<2,3>(m)); + + ret(3,0) = -det(removerc<3,0>(m)); + ret(3,1) = det(removerc<3,1>(m)); + ret(3,2) = -det(removerc<3,2>(m)); + ret(3,3) = det(removerc<3,3>(m)); + + return trans(ret)*de; + } + }; + + template < + typename EXP + > + inline const typename matrix_exp::matrix_type inv ( + const matrix_exp& m + ) { return inv_helper::NR>::inv(m); } + +// ---------------------------------------------------------------------------------------- + + template + struct op_diag_inv + { + template + op_diag_inv( const matrix_exp& m_) : m(m_){} + + + const static long cost = 1; + const static long NR = ((M::NC!=0)&&(M::NR!=0))? (tmax::value) : (0); + const static long NC = NR; + typedef typename M::type type; + typedef const type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + + // hold the matrix by value + const matrix m; + + const_ret_type apply ( long r, long c) const + { + if (r==c) + return m(r); + else + return 0; + } + + long nr () const { return m.size(); } + long nc () const { return m.size(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_diag_op > inv ( + const matrix_diag_exp& m + ) + { + typedef op_diag_inv op; + return matrix_diag_op(op(reciprocal(diag(m)))); + } + + template < + typename EXP + > + const matrix_diag_op > pinv ( + const matrix_diag_exp& m + ) + { + typedef op_diag_inv op; + return matrix_diag_op(op(reciprocal(diag(m)))); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename matrix_exp::matrix_type inv_lower_triangular ( + const matrix_exp& A + ) + { + DLIB_ASSERT(A.nr() == A.nc(), + "\tconst matrix inv_lower_triangular(const matrix_exp& A)" + << "\n\tA must be a square matrix" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + ); + + typedef typename matrix_exp::matrix_type matrix_type; + typedef typename matrix_type::type type; + + matrix_type m(A); + + for(long c = 0; c < m.nc(); ++c) + { + if( m(c,c) == 0 ) + { + // there isn't an inverse so just give up + return m; + } + + // compute m(c,c) + m(c,c) = 1/m(c,c); + + // compute the values in column c that are below m(c,c). + // We do this by just doing the same thing we do for upper triangular + // matrices because we take the transpose of m which turns m into an + // upper triangular matrix. + for(long r = 0; r < c; ++r) + { + const long n = c-r; + m(c,r) = -m(c,c)*subm(trans(m),r,r,1,n)*subm(trans(m),r,c,n,1); + } + } + + return m; + + } + +// ---------------------------------------------------------------------------------------- + + template + const typename matrix_exp::matrix_type inv_upper_triangular ( + const matrix_exp& A + ) + { + DLIB_ASSERT(A.nr() == A.nc(), + "\tconst matrix inv_upper_triangular(const matrix_exp& A)" + << "\n\tA must be a square matrix" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + ); + + typedef typename matrix_exp::matrix_type matrix_type; + typedef typename matrix_type::type type; + + matrix_type m(A); + + for(long c = 0; c < m.nc(); ++c) + { + if( m(c,c) == 0 ) + { + // there isn't an inverse so just give up + return m; + } + + // compute m(c,c) + m(c,c) = 1/m(c,c); + + // compute the values in column c that are above m(c,c) + for(long r = 0; r < c; ++r) + { + const long n = c-r; + m(r,c) = -m(c,c)*subm(m,r,r,1,n)*subm(m,r,c,n,1); + } + } + + return m; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + inline const typename matrix_exp::matrix_type chol ( + const matrix_exp& A + ) + { + DLIB_ASSERT(A.nr() == A.nc(), + "\tconst matrix chol(const matrix_exp& A)" + << "\n\tYou can only apply the chol to a square matrix" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + ); + typename matrix_exp::matrix_type L(A.nr(),A.nc()); + +#ifdef DLIB_USE_LAPACK + // Only call LAPACK if the matrix is big enough. Otherwise, + // our own code is faster, especially for statically dimensioned + // matrices. + if (A.nr() > 4) + { + L = A; + lapack::potrf('L', L); + // mask out upper triangular area + return lowerm(L); + } +#endif + typedef typename EXP::type T; + set_all_elements(L,0); + + // do nothing if the matrix is empty + if (A.size() == 0) + return L; + + const T eps = std::numeric_limits::epsilon(); + + // compute the upper left corner + if (A(0,0) > 0) + L(0,0) = std::sqrt(A(0,0)); + + // compute the first column + for (long r = 1; r < A.nr(); ++r) + { + // if (L(0,0) > 0) + if (L(0,0) > eps*std::abs(A(r,0))) + L(r,0) = A(r,0)/L(0,0); + else + return L; + } + + // now compute all the other columns + for (long c = 1; c < A.nc(); ++c) + { + // compute the diagonal element + T temp = A(c,c); + for (long i = 0; i < c; ++i) + { + temp -= L(c,i)*L(c,i); + } + if (temp > 0) + L(c,c) = std::sqrt(temp); + + // compute the non diagonal elements + for (long r = c+1; r < A.nr(); ++r) + { + temp = A(r,c); + for (long i = 0; i < c; ++i) + { + temp -= L(r,i)*L(c,i); + } + + // if (L(c,c) > 0) + if (L(c,c) > eps*std::abs(temp)) + L(r,c) = temp/L(c,c); + else + return L; + } + } + + return L; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + long uNR, + long uNC, + long wN, + long vN, + long wX, + typename MM1, + typename MM2, + typename MM3, + typename L1 + > + inline void svd3 ( + const matrix_exp& m, + matrix::type, uNR, uNC,MM1,L1>& u, + matrix::type, wN, wX,MM2,L1>& w, + matrix::type, vN, vN,MM3,L1>& v + ) + { + typedef typename matrix_exp::type T; + const long NR = matrix_exp::NR; + const long NC = matrix_exp::NC; + + // make sure the output matrices have valid dimensions if they are statically dimensioned + COMPILE_TIME_ASSERT(NR == 0 || uNR == 0 || NR == uNR); + COMPILE_TIME_ASSERT(NC == 0 || uNC == 0 || NC == uNC); + COMPILE_TIME_ASSERT(NC == 0 || wN == 0 || NC == wN); + COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); + COMPILE_TIME_ASSERT(wX == 0 || wX == 1); + +#ifdef DLIB_USE_LAPACK + matrix::type, uNR, uNC,MM1,L1> temp(m); + lapack::gesvd('S','A', temp, w, u, v); + v = trans(v); + // if u isn't the size we want then pad it (and v) with zeros + if (u.nc() < m.nc()) + { + w = join_cols(w, zeros_matrix(m.nc()-u.nc(),1)); + u = join_rows(u, zeros_matrix(u.nr(), m.nc()-u.nc())); + } +#else + v.set_size(m.nc(),m.nc()); + + u = m; + + w.set_size(m.nc(),1); + matrix::NC,1,MM1> rv1(m.nc(),1); + nric::svdcmp(u,w,v,rv1); +#endif + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const matrix pinv_helper ( + const matrix_exp& m + ) + /*! + ensures + - computes the results of pinv(m) but does so using a method that is fastest + when m.nc() <= m.nr(). So if m.nc() > m.nr() then it is best to use + trans(pinv_helper(trans(m))) to compute pinv(m). + !*/ + { + typename matrix_exp::matrix_type u; + typedef typename EXP::mem_manager_type MM1; + typedef typename EXP::layout_type layout_type; + matrix v; + + typedef typename matrix_exp::type T; + + matrix::NC,1,MM1, layout_type> w; + + svd3(m, u,w,v); + + const double machine_eps = std::numeric_limits::epsilon(); + // compute a reasonable epsilon below which we round to zero before doing the + // reciprocal + const double eps = machine_eps*std::max(m.nr(),m.nc())*max(w); + + // now compute the pseudoinverse + return tmp(scale_columns(v,reciprocal(round_zeros(w,eps))))*trans(u); + } + + template < + typename EXP + > + const matrix pinv ( + const matrix_exp& m + ) + { + // if m has more columns then rows then it is more efficient to + // compute the pseudo-inverse of its transpose (given the way I'm doing it below). + if (m.nc() > m.nr()) + return trans(pinv_helper(trans(m))); + else + return pinv_helper(m); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + long uNR, + long uNC, + long wN, + long vN, + typename MM1, + typename MM2, + typename MM3, + typename L1 + > + inline void svd ( + const matrix_exp& m, + matrix::type, uNR, uNC,MM1,L1>& u, + matrix::type, wN, wN,MM2,L1>& w, + matrix::type, vN, vN,MM3,L1>& v + ) + { + typedef typename matrix_exp::type T; + const long NR = matrix_exp::NR; + const long NC = matrix_exp::NC; + + // make sure the output matrices have valid dimensions if they are statically dimensioned + COMPILE_TIME_ASSERT(NR == 0 || uNR == 0 || NR == uNR); + COMPILE_TIME_ASSERT(NC == 0 || uNC == 0 || NC == uNC); + COMPILE_TIME_ASSERT(NC == 0 || wN == 0 || NC == wN); + COMPILE_TIME_ASSERT(NC == 0 || vN == 0 || NC == vN); + + matrix::NC,1,MM1, L1> W; + svd3(m,u,W,v); + w = diagm(W); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type trace ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC || + matrix_exp::NR == 0 || + matrix_exp::NC == 0 + ); + DLIB_ASSERT(m.nr() == m.nc(), + "\tconst matrix_exp::type trace(const matrix_exp& m)" + << "\n\tYou can only apply trace() to a square matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + return sum(diag(m)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + long N = EXP::NR + > + struct det_helper + { + static const typename matrix_exp::type det ( + const matrix_exp& m + ) + { + using namespace nric; + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC || + matrix_exp::NR == 0 || + matrix_exp::NC == 0 + ); + DLIB_ASSERT(m.nr() == m.nc(), + "\tconst matrix_exp::type det(const matrix_exp& m)" + << "\n\tYou can only apply det() to a square matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef typename matrix_exp::type type; + typedef typename matrix_exp::mem_manager_type MM; + + return lu_decomposition(m).det(); + } + }; + + template < + typename EXP + > + struct det_helper + { + static const typename matrix_exp::type det ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + return m(0); + } + }; + + template < + typename EXP + > + struct det_helper + { + static const typename matrix_exp::type det ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + return m(0,0)*m(1,1) - m(0,1)*m(1,0); + } + }; + + template < + typename EXP + > + struct det_helper + { + static const typename matrix_exp::type det ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + type temp = m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) - + m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) + + m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0)); + return temp; + } + }; + + + template < + typename EXP + > + inline const typename matrix_exp::type det ( + const matrix_exp& m + ) { return det_helper::det(m); } + + + template < + typename EXP + > + struct det_helper + { + static const typename matrix_exp::type det ( + const matrix_exp& m + ) + { + COMPILE_TIME_ASSERT(matrix_exp::NR == matrix_exp::NC); + typedef typename matrix_exp::type type; + + type temp = m(0,0)*(dlib::det(removerc<0,0>(m))) - + m(0,1)*(dlib::det(removerc<0,1>(m))) + + m(0,2)*(dlib::det(removerc<0,2>(m))) - + m(0,3)*(dlib::det(removerc<0,3>(m))); + return temp; + } + }; + +// ---------------------------------------------------------------------------------------- + + template + const matrix real_eigenvalues ( + const matrix_exp& m + ) + { + // You can only use this function with matrices that contain float or double values + COMPILE_TIME_ASSERT((is_same_type::value || + is_same_type::value)); + + DLIB_ASSERT(m.nr() == m.nc(), + "\tconst matrix real_eigenvalues()" + << "\n\tYou have given an invalidly sized matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + + if (m.nr() == 2) + { + typedef typename EXP::type T; + const T m00 = m(0,0); + const T m01 = m(0,1); + const T m10 = m(1,0); + const T m11 = m(1,1); + + const T b = -(m00 + m11); + const T c = m00*m11 - m01*m10; + matrix v(2); + + + T disc = b*b - 4*c; + if (disc >= 0) + disc = std::sqrt(disc); + else + disc = 0; + + v(0) = (-b + disc)/2; + v(1) = (-b - disc)/2; + return v; + } + else + { + // Call .ref() so that the symmetric matrix overload can take effect if m + // has the appropriate type. + return eigenvalue_decomposition(m.ref()).get_real_eigenvalues(); + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_LA_FUNCTS_ + + diff --git a/libs/dlib/matrix/matrix_la_abstract.h b/libs/dlib/matrix/matrix_la_abstract.h new file mode 100644 index 0000000..4c6d51b --- /dev/null +++ b/libs/dlib/matrix/matrix_la_abstract.h @@ -0,0 +1,840 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ +#ifdef DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ + +#include "matrix_abstract.h" +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Global linear algebra functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp::matrix_type inv ( + const matrix_exp& m + ); + /*! + requires + - m is a square matrix + ensures + - returns the inverse of m + (Note that if m is singular or so close to being singular that there + is a lot of numerical error then the returned matrix will be bogus. + You can check by seeing if m*inv(m) is an identity matrix) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix pinv ( + const matrix_exp& m + ); + /*! + ensures + - returns the Moore-Penrose pseudoinverse of m. + - The returned matrix has m.nc() rows and m.nr() columns. + !*/ + +// ---------------------------------------------------------------------------------------- + + void svd ( + const matrix_exp& m, + matrix& u, + matrix& w, + matrix& v + ); + /*! + ensures + - computes the singular value decomposition of m + - m == #u*#w*trans(#v) + - trans(#u)*#u == identity matrix + - trans(#v)*#v == identity matrix + - diag(#w) == the singular values of the matrix m in no + particular order. All non-diagonal elements of #w are + set to 0. + - #u.nr() == m.nr() + - #u.nc() == m.nc() + - #w.nr() == m.nc() + - #w.nc() == m.nc() + - #v.nr() == m.nc() + - #v.nc() == m.nc() + - if DLIB_USE_LAPACK is #defined then the xGESVD routine + from LAPACK is used to compute the SVD. + !*/ + +// ---------------------------------------------------------------------------------------- + + long svd2 ( + bool withu, + bool withv, + const matrix_exp& m, + matrix& u, + matrix& w, + matrix& v + ); + /*! + requires + - m.nr() >= m.nc() + ensures + - computes the singular value decomposition of matrix m + - m == subm(#u,get_rect(m))*diagm(#w)*trans(#v) + - trans(#u)*#u == identity matrix + - trans(#v)*#v == identity matrix + - #w == the singular values of the matrix m in no + particular order. + - #u.nr() == m.nr() + - #u.nc() == m.nr() + - #w.nr() == m.nc() + - #w.nc() == 1 + - #v.nr() == m.nc() + - #v.nc() == m.nc() + - if (widthu == false) then + - ignore the above regarding #u, it isn't computed and its + output state is undefined. + - if (widthv == false) then + - ignore the above regarding #v, it isn't computed and its + output state is undefined. + - returns an error code of 0, if no errors and 'k' if we fail to + converge at the 'kth' singular value. + - if (DLIB_USE_LAPACK is #defined) then + - if (withu == withv) then + - the xGESDD routine from LAPACK is used to compute the SVD. + - else + - the xGESVD routine from LAPACK is used to compute the SVD. + !*/ + +// ---------------------------------------------------------------------------------------- + + void svd3 ( + const matrix_exp& m, + matrix& u, + matrix& w, + matrix& v + ); + /*! + ensures + - computes the singular value decomposition of m + - m == #u*diagm(#w)*trans(#v) + - trans(#u)*#u == identity matrix + - trans(#v)*#v == identity matrix + - #w == the singular values of the matrix m in no + particular order. + - #u.nr() == m.nr() + - #u.nc() == m.nc() + - #w.nr() == m.nc() + - #w.nc() == 1 + - #v.nr() == m.nc() + - #v.nc() == m.nc() + - if DLIB_USE_LAPACK is #defined then the xGESVD routine + from LAPACK is used to compute the SVD. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix real_eigenvalues ( + const matrix_exp& m + ); + /*! + requires + - m.nr() == m.nc() + - matrix_exp::type == float or double + ensures + - returns a matrix E such that: + - E.nr() == m.nr() + - E.nc() == 1 + - E contains the real part of all eigenvalues of the matrix m. + (note that the eigenvalues are not sorted) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type det ( + const matrix_exp& m + ); + /*! + requires + - m is a square matrix + ensures + - returns the determinant of m + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type trace ( + const matrix_exp& m + ); + /*! + requires + - m is a square matrix + ensures + - returns the trace of m + (i.e. returns sum(diag(m))) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::matrix_type chol ( + const matrix_exp& A + ); + /*! + requires + - A is a square matrix + ensures + - if (A has a Cholesky Decomposition) then + - returns the decomposition of A. That is, returns a matrix L + such that L*trans(L) == A. L will also be lower triangular. + - else + - returns a matrix with the same dimensions as A but it + will have a bogus value. I.e. it won't be a decomposition. + In this case the algorithm returns a partial decomposition. + - You can tell when chol fails by looking at the lower right + element of the returned matrix. If it is 0 then it means + A does not have a cholesky decomposition. + + - If DLIB_USE_LAPACK is defined then the LAPACK routine xPOTRF + is used to compute the cholesky decomposition. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::matrix_type inv_lower_triangular ( + const matrix_exp& A + ); + /*! + requires + - A is a square matrix + ensures + - if (A is lower triangular) then + - returns the inverse of A. + - else + - returns a matrix with the same dimensions as A but it + will have a bogus value. I.e. it won't be an inverse. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::matrix_type inv_upper_triangular ( + const matrix_exp& A + ); + /*! + requires + - A is a square matrix + ensures + - if (A is upper triangular) then + - returns the inverse of A. + - else + - returns a matrix with the same dimensions as A but it + will have a bogus value. I.e. it won't be an inverse. + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Matrix decomposition classes +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_exp_type + > + class lu_decomposition + { + /*! + REQUIREMENTS ON matrix_exp_type + must be some kind of matrix expression as defined in the + dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) + The matrix type must also contain float or double values. + + WHAT THIS OBJECT REPRESENTS + This object represents something that can compute an LU + decomposition of a real valued matrix. That is, for any + matrix A it computes matrices L, U, and a pivot vector P such + that rowm(A,P) == L*U. + + The LU decomposition with pivoting always exists, even if the matrix is + singular, so the constructor will never fail. The primary use of the + LU decomposition is in the solution of square systems of simultaneous + linear equations. This will fail if is_singular() returns true (or + if A is very nearly singular). + + If DLIB_USE_LAPACK is defined then the LAPACK routine xGETRF + is used to compute the LU decomposition. + !*/ + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef matrix matrix_type; + typedef matrix column_vector_type; + typedef matrix pivot_column_vector_type; + + template + lu_decomposition ( + const matrix_exp &A + ); + /*! + requires + - EXP::type == lu_decomposition::type + - A.size() > 0 + ensures + - #nr() == A.nr() + - #nc() == A.nc() + - #is_square() == (A.nr() == A.nc()) + - computes the LU factorization of the given A matrix. + !*/ + + bool is_square ( + ) const; + /*! + ensures + - if (the input A matrix was a square matrix) then + - returns true + - else + - returns false + !*/ + + bool is_singular ( + ) const; + /*! + requires + - is_square() == true + ensures + - if (the input A matrix is singular) then + - returns true + - else + - returns false + !*/ + + long nr( + ) const; + /*! + ensures + - returns the number of rows in the input matrix + !*/ + + long nc( + ) const; + /*! + ensures + - returns the number of columns in the input matrix + !*/ + + const matrix_type get_l ( + ) const; + /*! + ensures + - returns the lower triangular L factor of the LU factorization. + - L.nr() == nr() + - L.nc() == min(nr(),nc()) + !*/ + + const matrix_type get_u ( + ) const; + /*! + ensures + - returns the upper triangular U factor of the LU factorization. + - U.nr() == min(nr(),nc()) + - U.nc() == nc() + !*/ + + const pivot_column_vector_type& get_pivot ( + ) const; + /*! + ensures + - returns the pivot permutation vector. That is, + if A is the input matrix then this function + returns a vector P such that: + - rowm(A,P) == get_l()*get_u() + - P.nr() == A.nr() + !*/ + + type det ( + ) const; + /*! + requires + - is_square() == true + ensures + - computes and returns the determinant of the input + matrix using LU factors. + !*/ + + template + const matrix_type solve ( + const matrix_exp &B + ) const; + /*! + requires + - EXP::type == lu_decomposition::type + - is_square() == true + - B.nr() == nr() + ensures + - Let A denote the input matrix to this class's constructor. + Then this function solves A*X == B for X and returns X. + - Note that if A is singular (or very close to singular) then + the X returned by this function won't fit A*X == B very well (if at all). + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_exp_type + > + class cholesky_decomposition + { + /*! + REQUIREMENTS ON matrix_exp_type + must be some kind of matrix expression as defined in the + dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) + The matrix type must also contain float or double values. + + WHAT THIS OBJECT REPRESENTS + This object represents something that can compute a cholesky + decomposition of a real valued matrix. That is, for any + symmetric, positive definite matrix A, it computes a lower + triangular matrix L such that A == L*trans(L). + + If the matrix is not symmetric or positive definite, the function + computes only a partial decomposition. This can be tested with + the is_spd() flag. + + If DLIB_USE_LAPACK is defined then the LAPACK routine xPOTRF + is used to compute the cholesky decomposition. + !*/ + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef typename matrix_exp_type::matrix_type matrix_type; + typedef matrix column_vector_type; + + template + cholesky_decomposition( + const matrix_exp& A + ); + /*! + requires + - EXP::type == cholesky_decomposition::type + - A.size() > 0 + - A.nr() == A.nc() + (i.e. A must be a square matrix) + ensures + - if (A is symmetric positive-definite) then + - #is_spd() == true + - Constructs a lower triangular matrix L, such that L*trans(L) == A. + and #get_l() == L + - else + - #is_spd() == false + !*/ + + bool is_spd( + ) const; + /*! + ensures + - if (the input matrix was symmetric positive-definite) then + - returns true + - else + - returns false + !*/ + + const matrix_type& get_l( + ) const; + /*! + ensures + - returns the lower triangular factor, L, such that L*trans(L) == A + (where A is the input matrix to this class's constructor) + - Note that if A is not symmetric positive definite or positive semi-definite + then the equation L*trans(L) == A won't hold. + !*/ + + template + const matrix solve ( + const matrix_exp& B + ) const; + /*! + requires + - EXP::type == cholesky_decomposition::type + - B.nr() == get_l().nr() + (i.e. the number of rows in B must match the number of rows in the + input matrix A) + ensures + - Let A denote the input matrix to this class's constructor. Then + this function solves A*X = B for X and returns X. + - Note that if is_spd() == false or A was really close to being + non-SPD then the solver will fail to find an accurate solution. + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_exp_type + > + class qr_decomposition + { + /*! + REQUIREMENTS ON matrix_exp_type + must be some kind of matrix expression as defined in the + dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) + The matrix type must also contain float or double values. + + WHAT THIS OBJECT REPRESENTS + This object represents something that can compute a classical + QR decomposition of an m-by-n real valued matrix A with m >= n. + + The QR decomposition is an m-by-n orthogonal matrix Q and an + n-by-n upper triangular matrix R so that A == Q*R. The QR decomposition + always exists, even if the matrix does not have full rank, so the + constructor will never fail. The primary use of the QR decomposition + is in the least squares solution of non-square systems of simultaneous + linear equations. This will fail if is_full_rank() returns false or + A is very nearly not full rank. + + The Q and R factors can be retrieved via the get_q() and get_r() + methods. Furthermore, a solve() method is provided to find the + least squares solution of Ax=b using the QR factors. + + If DLIB_USE_LAPACK is #defined then the xGEQRF routine + from LAPACK is used to compute the QR decomposition. + !*/ + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef matrix matrix_type; + + template + qr_decomposition( + const matrix_exp& A + ); + /*! + requires + - EXP::type == qr_decomposition::type + - A.nr() >= A.nc() + - A.size() > 0 + ensures + - #nr() == A.nr() + - #nc() == A.nc() + - computes the QR decomposition of the given A matrix. + !*/ + + bool is_full_rank( + ) const; + /*! + ensures + - if (the input A matrix had full rank) then + - returns true + - else + - returns false + !*/ + + long nr( + ) const; + /*! + ensures + - returns the number of rows in the input matrix + !*/ + + long nc( + ) const; + /*! + ensures + - returns the number of columns in the input matrix + !*/ + + const matrix_type get_r ( + ) const; + /*! + ensures + - returns a matrix R such that: + - R is the upper triangular factor, R, of the QR factorization + - get_q()*R == input matrix A + - R.nr() == nc() + - R.nc() == nc() + !*/ + + const matrix_type get_q ( + ) const; + /*! + ensures + - returns a matrix Q such that: + - Q is the economy-sized orthogonal factor Q from the QR + factorization. + - trans(Q)*Q == identity matrix + - Q*get_r() == input matrix A + - Q.nr() == nr() + - Q.nc() == nc() + !*/ + + template + const matrix_type solve ( + const matrix_exp& B + ) const; + /*! + requires + - EXP::type == qr_decomposition::type + - B.nr() == nr() + ensures + - Let A denote the input matrix to this class's constructor. + Then this function finds the least squares solution to the equation A*X = B + and returns X. X has the following properties: + - X is the matrix that minimizes the two norm of A*X-B. That is, it + minimizes sum(squared(A*X - B)). + - X.nr() == nc() + - X.nc() == B.nc() + - Note that this function will fail to output a good solution if is_full_rank() == false + or the A matrix is close to not being full rank. + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename matrix_exp_type + > + class eigenvalue_decomposition + { + /*! + REQUIREMENTS ON matrix_exp_type + must be some kind of matrix expression as defined in the + dlib/matrix/matrix_abstract.h file. (e.g. a dlib::matrix object) + The matrix type must also contain float or double values. + + WHAT THIS OBJECT REPRESENTS + This object represents something that can compute an eigenvalue + decomposition of a real valued matrix. So it gives + you the set of eigenvalues and eigenvectors for a matrix. + + Let A denote the input matrix to this object's constructor. Then + what this object does is it finds two matrices, D and V, such that + - A*V == V*D + Where V is a square matrix that contains all the eigenvectors + of the A matrix (each column of V is an eigenvector) and + D is a diagonal matrix containing the eigenvalues of A. + + + It is important to note that if A is symmetric or non-symmetric you + get somewhat different results. If A is a symmetric matrix (i.e. A == trans(A)) + then: + - All the eigenvalues and eigenvectors of A are real numbers. + - Because of this there isn't really any point in using the + part of this class's interface that returns complex matrices. + All you need are the get_real_eigenvalues() and + get_pseudo_v() functions. + - V*trans(V) should be equal to the identity matrix. That is, all the + eigenvectors in V should be orthonormal. + - So A == V*D*trans(V) + - If DLIB_USE_LAPACK is #defined then this object uses the xSYEVR LAPACK + routine. + + On the other hand, if A is not symmetric then: + - Some of the eigenvalues and eigenvectors might be complex numbers. + - An eigenvalue is complex if and only if its corresponding eigenvector + is complex. So you can check for this case by just checking + get_imag_eigenvalues() to see if any values are non-zero. You don't + have to check the V matrix as well. + - V*trans(V) won't be equal to the identity matrix but it is usually + invertible. So A == V*D*inv(V) is usually a valid statement but + A == V*D*trans(V) won't be. + - If DLIB_USE_LAPACK is #defined then this object uses the xGEEV LAPACK + routine. + !*/ + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef typename matrix_exp_type::matrix_type matrix_type; + typedef matrix column_vector_type; + + typedef matrix,0,0,mem_manager_type,layout_type> complex_matrix_type; + typedef matrix,NR,1,mem_manager_type,layout_type> complex_column_vector_type; + + + template + eigenvalue_decomposition( + const matrix_exp& A + ); + /*! + requires + - A.nr() == A.nc() + - A.size() > 0 + - EXP::type == eigenvalue_decomposition::type + ensures + - #dim() == A.nr() + - computes the eigenvalue decomposition of A. + - #get_eigenvalues() == the eigenvalues of A + - #get_v() == all the eigenvectors of A + !*/ + + template + eigenvalue_decomposition( + const matrix_op >& A + ); + /*! + requires + - A.nr() == A.nc() + - A.size() > 0 + - EXP::type == eigenvalue_decomposition::type + ensures + - #dim() == A.nr() + - computes the eigenvalue decomposition of the symmetric matrix A. Does so + using a method optimized for symmetric matrices. + - #get_eigenvalues() == the eigenvalues of A + - #get_v() == all the eigenvectors of A + - moreover, since A is symmetric there won't be any imaginary eigenvalues. So + we will have: + - #get_imag_eigenvalues() == 0 + - #get_real_eigenvalues() == the eigenvalues of A + - #get_pseudo_v() == all the eigenvectors of A + - diagm(#get_real_eigenvalues()) == #get_pseudo_d() + + Note that the symmetric matrix operator is created by the + dlib::make_symmetric() function. This function simply reflects + the lower triangular part of a square matrix into the upper triangular + part to create a symmetric matrix. It can also be used to denote that a + matrix is already symmetric using the C++ type system. + !*/ + + long dim ( + ) const; + /*! + ensures + - dim() == the number of rows/columns in the input matrix A + !*/ + + const complex_column_vector_type get_eigenvalues ( + ) const; + /*! + ensures + - returns diag(get_d()). That is, returns a + vector that contains the eigenvalues of the input + matrix. + - the returned vector has dim() rows + - the eigenvalues are not sorted in any particular way + !*/ + + const column_vector_type& get_real_eigenvalues ( + ) const; + /*! + ensures + - returns the real parts of the eigenvalues. That is, + returns real(get_eigenvalues()) + - the returned vector has dim() rows + - the eigenvalues are not sorted in any particular way + !*/ + + const column_vector_type& get_imag_eigenvalues ( + ) const; + /*! + ensures + - returns the imaginary parts of the eigenvalues. That is, + returns imag(get_eigenvalues()) + - the returned vector has dim() rows + - the eigenvalues are not sorted in any particular way + !*/ + + const complex_matrix_type get_v ( + ) const; + /*! + ensures + - returns the eigenvector matrix V that is + dim() rows by dim() columns + - Each column in V is one of the eigenvectors of the input + matrix + !*/ + + const complex_matrix_type get_d ( + ) const; + /*! + ensures + - returns a matrix D such that: + - D.nr() == dim() + - D.nc() == dim() + - diag(D) == get_eigenvalues() + (i.e. the diagonal of D contains all the eigenvalues in the input matrix) + - all off diagonal elements of D are set to 0 + !*/ + + const matrix_type& get_pseudo_v ( + ) const; + /*! + ensures + - returns a matrix that is dim() rows by dim() columns + - Let A denote the input matrix given to this object's constructor. + - if (A has any imaginary eigenvalues) then + - returns the pseudo-eigenvector matrix V + - The matrix V returned by this function is structured such that: + - A*V == V*get_pseudo_d() + - else + - returns the eigenvector matrix V with A's eigenvectors as + the columns of V + - A*V == V*diagm(get_real_eigenvalues()) + !*/ + + const matrix_type get_pseudo_d ( + ) const; + /*! + ensures + - The returned matrix is dim() rows by dim() columns + - Computes and returns the block diagonal eigenvalue matrix. + If the original matrix A is not symmetric, then the eigenvalue + matrix D is block diagonal with the real eigenvalues in 1-by-1 + blocks and any complex eigenvalues, + a + i*b, in 2-by-2 blocks, (a, b; -b, a). That is, if the complex + eigenvalues look like + + u + iv . . . . . + . u - iv . . . . + . . a + ib . . . + . . . a - ib . . + . . . . x . + . . . . . y + + Then D looks like + + u v . . . . + -v u . . . . + . . a b . . + . . -b a . . + . . . . x . + . . . . . y + + This keeps V (The V you get from get_pseudo_v()) a real matrix in both + symmetric and non-symmetric cases, and A*V = V*D. + - the eigenvalues are not sorted in any particular way + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_LA_FUNCTS_ABSTRACT_ + diff --git a/libs/dlib/matrix/matrix_lu.h b/libs/dlib/matrix/matrix_lu.h new file mode 100644 index 0000000..3e49cd6 --- /dev/null +++ b/libs/dlib/matrix/matrix_lu.h @@ -0,0 +1,361 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +// This code was adapted from code from the JAMA part of NIST's TNT library. +// See: http://math.nist.gov/tnt/ +#ifndef DLIB_MATRIX_LU_DECOMPOSITION_H +#define DLIB_MATRIX_LU_DECOMPOSITION_H + +#include "matrix.h" +#include "matrix_utilities.h" +#include "matrix_subexp.h" +#include "matrix_trsm.h" +#include + +#ifdef DLIB_USE_LAPACK +#include "lapack/getrf.h" +#endif + + +namespace dlib +{ + + template < + typename matrix_exp_type + > + class lu_decomposition + { + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef matrix matrix_type; + typedef matrix column_vector_type; + typedef matrix pivot_column_vector_type; + + // You have supplied an invalid type of matrix_exp_type. You have + // to use this object with matrices that contain float or double type data. + COMPILE_TIME_ASSERT((is_same_type::value || + is_same_type::value )); + + template + lu_decomposition ( + const matrix_exp &A + ); + + bool is_square ( + ) const; + + bool is_singular ( + ) const; + + long nr( + ) const; + + long nc( + ) const; + + const matrix_type get_l ( + ) const; + + const matrix_type get_u ( + ) const; + + const pivot_column_vector_type& get_pivot ( + ) const; + + type det ( + ) const; + + template + const matrix_type solve ( + const matrix_exp &B + ) const; + + private: + + /* Array for internal storage of decomposition. */ + matrix LU; + long m, n, pivsign; + pivot_column_vector_type piv; + + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Public member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + template + lu_decomposition:: + lu_decomposition ( + const matrix_exp& A + ) : + LU(A), + m(A.nr()), + n(A.nc()) + { + using namespace std; + using std::abs; + + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(A.size() > 0, + "\tlu_decomposition::lu_decomposition(A)" + << "\n\tInvalid inputs were given to this function" + << "\n\tA.size(): " << A.size() + << "\n\tthis: " << this + ); + +#ifdef DLIB_USE_LAPACK + matrix piv_temp; + lapack::getrf(LU, piv_temp); + + pivsign = 1; + + // Turn the piv_temp vector into a more useful form. This way we will have the identity + // rowm(A,piv) == L*U. The permutation vector that comes out of LAPACK is somewhat + // different. + piv = trans(range(0,m-1)); + for (long i = 0; i < piv_temp.size(); ++i) + { + // -1 because FORTRAN is indexed starting with 1 instead of 0 + if (piv(piv_temp(i)-1) != piv(i)) + { + std::swap(piv(i), piv(piv_temp(i)-1)); + pivsign = -pivsign; + } + } + +#else + + // Use a "left-looking", dot-product, Crout/Doolittle algorithm. + + + piv = trans(range(0,m-1)); + pivsign = 1; + + column_vector_type LUcolj(m); + + // Outer loop. + for (long j = 0; j < n; j++) + { + + // Make a copy of the j-th column to localize references. + LUcolj = colm(LU,j); + + // Apply previous transformations. + for (long i = 0; i < m; i++) + { + // Most of the time is spent in the following dot product. + const long kmax = std::min(i,j); + type s; + if (kmax > 0) + s = rowm(LU,i, kmax)*colm(LUcolj,0,kmax); + else + s = 0; + + LU(i,j) = LUcolj(i) -= s; + } + + // Find pivot and exchange if necessary. + long p = j; + for (long i = j+1; i < m; i++) + { + if (abs(LUcolj(i)) > abs(LUcolj(p))) + { + p = i; + } + } + if (p != j) + { + long k=0; + for (k = 0; k < n; k++) + { + type t = LU(p,k); + LU(p,k) = LU(j,k); + LU(j,k) = t; + } + k = piv(p); + piv(p) = piv(j); + piv(j) = k; + pivsign = -pivsign; + } + + // Compute multipliers. + if ((j < m) && (LU(j,j) != 0.0)) + { + for (long i = j+1; i < m; i++) + { + LU(i,j) /= LU(j,j); + } + } + } + +#endif + } + +// ---------------------------------------------------------------------------------------- + + template + bool lu_decomposition:: + is_square ( + ) const + { + return m == n; + } + +// ---------------------------------------------------------------------------------------- + + template + long lu_decomposition:: + nr ( + ) const + { + return m; + } + +// ---------------------------------------------------------------------------------------- + + template + long lu_decomposition:: + nc ( + ) const + { + return n; + } + +// ---------------------------------------------------------------------------------------- + + template + bool lu_decomposition:: + is_singular ( + ) const + { + /* Is the matrix singular? + if upper triangular factor U (and hence A) is singular, false otherwise. + */ + // make sure requires clause is not broken + DLIB_ASSERT(is_square() == true, + "\tbool lu_decomposition::is_singular()" + << "\n\tYou can only use this on square matrices" + << "\n\tthis: " << this + ); + + type max_val, min_val; + find_min_and_max (abs(diag(LU)), min_val, max_val); + type eps = max_val; + if (eps != 0) + eps *= std::sqrt(std::numeric_limits::epsilon())/10; + else + eps = 1; // there is no max so just use 1 + + return min_val < eps; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename lu_decomposition::matrix_type lu_decomposition:: + get_l ( + ) const + { + if (LU.nr() >= LU.nc()) + return lowerm(LU,1.0); + else + return lowerm(subm(LU,0,0,m,m), 1.0); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename lu_decomposition::matrix_type lu_decomposition:: + get_u ( + ) const + { + if (LU.nr() >= LU.nc()) + return upperm(subm(LU,0,0,n,n)); + else + return upperm(LU); + } + +// ---------------------------------------------------------------------------------------- + + template + const typename lu_decomposition::pivot_column_vector_type& lu_decomposition:: + get_pivot ( + ) const + { + return piv; + } + +// ---------------------------------------------------------------------------------------- + + template + typename lu_decomposition::type lu_decomposition:: + det ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(is_square() == true, + "\ttype lu_decomposition::det()" + << "\n\tYou can only use this on square matrices" + << "\n\tthis: " << this + ); + + // Check if it is singular and if it is just return 0. + // We want to do this because a prod() operation can easily + // overcome a single diagonal element that is effectively 0 when + // LU is a big enough matrix. + if (is_singular()) + return 0; + + return prod(diag(LU))*static_cast(pivsign); + } + +// ---------------------------------------------------------------------------------------- + + template + template + const typename lu_decomposition::matrix_type lu_decomposition:: + solve ( + const matrix_exp &B + ) const + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(is_square() == true && B.nr() == nr(), + "\ttype lu_decomposition::solve()" + << "\n\tInvalid arguments to this function" + << "\n\tis_square(): " << (is_square()? "true":"false" ) + << "\n\tB.nr(): " << B.nr() + << "\n\tnr(): " << nr() + << "\n\tthis: " << this + ); + + // Copy right hand side with pivoting + matrix X(rowm(B, piv)); + + using namespace blas_bindings; + // Solve L*Y = B(piv,:) + triangular_solver(CblasLeft, CblasLower, CblasNoTrans, CblasUnit, LU, X); + // Solve U*X = Y; + triangular_solver(CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, LU, X); + return X; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIX_LU_DECOMPOSITION_H + + diff --git a/libs/dlib/matrix/matrix_math_functions.h b/libs/dlib/matrix/matrix_math_functions.h new file mode 100644 index 0000000..6bf6513 --- /dev/null +++ b/libs/dlib/matrix/matrix_math_functions.h @@ -0,0 +1,438 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_MATH_FUNCTIONS +#define DLIB_MATRIx_MATH_FUNCTIONS + +#include "matrix_math_functions_abstract.h" +#include "matrix_op.h" +#include "matrix_utilities.h" +#include "matrix.h" +#include "../algs.h" +#include +#include +#include + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + DLIB_DEFINE_FUNCTION_M(op_sqrt, sqrt, std::sqrt ,7); + DLIB_DEFINE_FUNCTION_M(op_log, log, std::log ,7); + DLIB_DEFINE_FUNCTION_M(op_log10, log10, std::log10 ,7); + DLIB_DEFINE_FUNCTION_M(op_exp, exp, std::exp ,7); + + DLIB_DEFINE_FUNCTION_M(op_conj, conj, std::conj ,2); + + DLIB_DEFINE_FUNCTION_M(op_ceil, ceil, std::ceil ,7); + DLIB_DEFINE_FUNCTION_M(op_floor, floor, std::floor ,7); + + DLIB_DEFINE_FUNCTION_M(op_sin, sin, std::sin ,7); + DLIB_DEFINE_FUNCTION_M(op_cos, cos, std::cos ,7); + DLIB_DEFINE_FUNCTION_M(op_tan, tan, std::tan ,7); + DLIB_DEFINE_FUNCTION_M(op_sinh, sinh, std::sinh ,7); + DLIB_DEFINE_FUNCTION_M(op_cosh, cosh, std::cosh ,7); + DLIB_DEFINE_FUNCTION_M(op_tanh, tanh, std::tanh ,7); + DLIB_DEFINE_FUNCTION_M(op_asin, asin, std::asin ,7); + DLIB_DEFINE_FUNCTION_M(op_acos, acos, std::acos ,7); + DLIB_DEFINE_FUNCTION_M(op_atan, atan, std::atan ,7); + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type sigmoid (const type& val) + { + return static_cast(1/(1 + std::exp(-val))); + } + + template + inline type round_zeros_eps (const type& val, const S& eps) + { + // you can only round matrices that contain built in scalar types like double, long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + if (val >= eps || val <= -eps) + return val; + else + return 0; + } + + template + inline type round_zeros (const type& val) + { + // you can only round matrices that contain built in scalar types like double, long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + const type eps = 10*std::numeric_limits::epsilon(); + if (val >= eps || val <= -eps) + return val; + else + return 0; + } + + template + inline type squared (const type& val) + { + return val*val; + } + + template + type cubed (const type& val) + { + return val*val*val; + } + + template + inline type pow1 (const type& val, const S& s) + { + // you can only call pow() on matrices that contain floats, doubles or long doubles. + COMPILE_TIME_ASSERT(( + is_same_type::value == true || + is_same_type::value == true || + is_same_type::value == true + )); + + return std::pow(val,static_cast(s)); + } + + template + inline type pow2 (const S& s, const type& val) + { + // you can only call pow() on matrices that contain floats, doubles or long doubles. + COMPILE_TIME_ASSERT(( + is_same_type::value == true || + is_same_type::value == true || + is_same_type::value == true + )); + + return std::pow(static_cast(s),val); + } + + template + inline type reciprocal (const type& val) + { + // you can only compute reciprocal matrices that contain floats, doubles or long doubles. + COMPILE_TIME_ASSERT(( + is_same_type::value == true || + is_same_type::value == true || + is_same_type::value == true || + is_same_type >::value == true || + is_same_type >::value == true || + is_same_type >::value == true + )); + + if (val != static_cast(0)) + return static_cast((type)1.0/val); + else + return 0; + } + + template + inline type reciprocal_max (const type& val) + { + // you can only compute reciprocal_max matrices that contain floats, doubles or long doubles. + COMPILE_TIME_ASSERT(( + is_same_type::value == true || + is_same_type::value == true || + is_same_type::value == true + )); + + if (val != static_cast(0)) + return static_cast((type)1.0/val); + else + return std::numeric_limits::max(); + } + + } + + DLIB_DEFINE_FUNCTION_M(op_sigmoid, sigmoid, impl::sigmoid, 7); + DLIB_DEFINE_FUNCTION_MS(op_round_zeros, round_zeros, impl::round_zeros_eps, 7); + DLIB_DEFINE_FUNCTION_M(op_round_zeros2, round_zeros, impl::round_zeros, 7); + DLIB_DEFINE_FUNCTION_M(op_cubed, cubed, impl::cubed, 7); + DLIB_DEFINE_FUNCTION_M(op_squared, squared, impl::squared, 6); + DLIB_DEFINE_FUNCTION_MS(op_pow1, pow, impl::pow1, 7); + DLIB_DEFINE_FUNCTION_SM(op_pow2, pow, impl::pow2, 7); + DLIB_DEFINE_FUNCTION_M(op_reciprocal, reciprocal, impl::reciprocal, 6); + DLIB_DEFINE_FUNCTION_M(op_reciprocal_max, reciprocal_max, impl::reciprocal_max, 6); + +// ---------------------------------------------------------------------------------------- + + template + struct op_round : basic_op_m + { + op_round( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+7; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return static_cast(std::floor(this->m(r,c)+0.5)); + } + }; + + template + struct op_round::is_integer>::type > + : basic_op_m + { + op_round( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + const_ret_type apply (long r, long c) const + { + return this->m(r,c); + } + }; + + template < + typename EXP + > + const matrix_op > round ( + const matrix_exp& m + ) + { + // you can only round matrices that contain built in scalar types like double, long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_round op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_normalize : basic_op_m + { + typedef typename M::type type; + + op_normalize( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+5; + typedef const typename M::type const_ret_type; + const_ret_type apply (long r, long c) const + { + return this->m(r,c)*s; + } + }; + + template < + typename EXP + > + const matrix_op > normalize ( + const matrix_exp& m + ) + { + // you can only compute normalized matrices that contain floats, doubles or long doubles. + COMPILE_TIME_ASSERT(( + is_same_type::value == true || + is_same_type::value == true || + is_same_type::value == true + )); + + + typedef op_normalize op; + typename EXP::type temp = std::sqrt(sum(squared(m))); + if (temp != 0.0) + temp = 1.0/temp; + + return matrix_op(op(m.ref(),temp)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_abs : basic_op_m + { + op_abs( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+7; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + const_ret_type apply ( long r, long c) const + { + return static_cast(std::abs(this->m(r,c))); + } + }; + + template + struct op_abs > : basic_op_m + { + op_abs( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost; + typedef T type; + typedef const T const_ret_type; + const_ret_type apply ( long r, long c) const + { + return static_cast(std::abs(this->m(r,c))); + } + }; + + template < + typename EXP + > + const matrix_op > abs ( + const matrix_exp& m + ) + { + typedef op_abs op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_complex_matrix : basic_op_m + { + op_complex_matrix( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+1; + typedef std::complex type; + typedef const std::complex const_ret_type; + const_ret_type apply ( long r, long c) const + { + return type(this->m(r,c)); + } + }; + + template < + typename EXP + > + const matrix_op > complex_matrix ( + const matrix_exp& m + ) + { + typedef op_complex_matrix op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_complex_matrix2 : basic_op_mm + { + op_complex_matrix2( const M1& m1_, const M2& m2_) : basic_op_mm(m1_,m2_){} + + const static long cost = M1::cost+M2::cost+1; + typedef std::complex type; + typedef const std::complex const_ret_type; + + const_ret_type apply ( long r, long c) const + { return type(this->m1(r,c), this->m2(r,c)); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > complex_matrix ( + const matrix_exp& real_part, + const matrix_exp& imag_part + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); + + DLIB_ASSERT(real_part.nr() == imag_part.nr() && + real_part.nc() == imag_part.nc(), + "\tconst matrix_exp::type complex_matrix(real_part, imag_part)" + << "\n\tYou can only make a complex matrix from two equally sized matrices" + << "\n\treal_part.nr(): " << real_part.nr() + << "\n\treal_part.nc(): " << real_part.nc() + << "\n\timag_part.nr(): " << imag_part.nr() + << "\n\timag_part.nc(): " << imag_part.nc() + ); + + typedef op_complex_matrix2 op; + return matrix_op(op(real_part.ref(),imag_part.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_norm : basic_op_m + { + op_norm( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+6; + typedef typename M::type::value_type type; + typedef const typename M::type::value_type const_ret_type; + const_ret_type apply ( long r, long c) const + { return std::norm(this->m(r,c)); } + }; + + template < + typename EXP + > + const matrix_op > norm ( + const matrix_exp& m + ) + { + typedef op_norm op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_real : basic_op_m + { + op_real( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost; + typedef typename M::type::value_type type; + typedef const typename M::type::value_type const_ret_type; + const_ret_type apply ( long r, long c) const + { return std::real(this->m(r,c)); } + }; + + template < + typename EXP + > + const matrix_op > real ( + const matrix_exp& m + ) + { + typedef op_real op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_imag : basic_op_m + { + op_imag( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost; + typedef typename M::type::value_type type; + typedef const typename M::type::value_type const_ret_type; + const_ret_type apply (long r, long c) const + { return std::imag(this->m(r,c)); } + }; + + template < + typename EXP + > + const matrix_op > imag ( + const matrix_exp& m + ) + { + typedef op_imag op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_MATH_FUNCTIONS + diff --git a/libs/dlib/matrix/matrix_math_functions_abstract.h b/libs/dlib/matrix/matrix_math_functions_abstract.h new file mode 100644 index 0000000..1ccc8de --- /dev/null +++ b/libs/dlib/matrix/matrix_math_functions_abstract.h @@ -0,0 +1,577 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ +#ifdef DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ + +#include "matrix_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Exponential Functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp exp ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::exp(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp log10 ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::log10(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp log ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::log(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp sqrt ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == sqrt(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp pow ( + const matrix_exp& m, + const T& e + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == pow(m(r,c),e) + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp pow ( + const T& b, + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == pow(b, m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp squared ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == m(r,c)*m(r,c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp cubed ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == m(r,c)*m(r,c)*m(r,c) + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Miscellaneous +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp sigmoid ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == 1/(1 + exp(-m(r,c))) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp abs ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - if (m contains std::complex objects) then + - R::type == T + - else + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::abs(m(r,c)) + (note that if m is complex then std::abs(val) performs sqrt(std::norm(val)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp reciprocal ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, long double, std::complex, + std::complex, or std::complex + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + - if (m(r,c) != 0) then + - R(r,c) == 1.0/m(r,c) + - else + - R(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp reciprocal_max ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + - if (m(r,c) != 0) then + - R(r,c) == 1.0/m(r,c) + - else + - R(r,c) == std::numeric_limits::max() + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp normalize ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - if (sqrt(sum(squared(m))) != 0) then + - returns m/sqrt(sum(squared(m))) + - else + - returns m + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Rounding numbers one way or another +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp round ( + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + (i.e. m must contain a type like int, float, double, long, etc.) + ensures + - if (m contains integers) then + - returns m unmodified + - else + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == m(r,c) rounded to the nearest integral value + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp ceil ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::ceil(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp floor ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::floor(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp round_zeros ( + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + (i.e. m must contain a type like int, float, double, long, etc.) + ensures + - if (m contains integers) then + - returns m unmodified + - else + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - let eps == 10*std::numeric_limits::epsilon() + - for all valid r and c: + - if (abs(m(r,c)) >= eps) then + - R(r,c) == m(r,c) + - else + - R(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp round_zeros ( + const matrix_exp& m, + matrix_exp::type eps + ); + /*! + requires + - is_built_in_scalar_type::value == true + (i.e. m must contain a type like int, float, double, long, etc.) + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + - if (abs(m(r,c)) >= eps) then + - R(r,c) == m(r,c) + - else + - R(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Complex number utility functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp conj ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == std::complex + ensures + - returns a matrix R such that: + - R::type == std::complex + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::conj(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp norm ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == std::complex + ensures + - returns a matrix R such that: + - R::type == T + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::norm(m(r,c)) + (note that std::norm(val) == val.real()*val.real() + val.imag()*val.imag()) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp imag ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == std::complex + ensures + - returns a matrix R such that: + - R::type == T + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::imag(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp real ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == std::complex + ensures + - returns a matrix R such that: + - R::type == T + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::real(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp complex_matrix ( + const matrix_exp& real_part + ); + /*! + ensures + - returns a matrix R such that: + - R::type == std::complex where T is whatever type real_part used. + - R has the same dimensions as real_part. + - for all valid r and c: + R(r,c) == std::complex(real_part(r,c), 0) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp complex_matrix ( + const matrix_exp& real_part, + const matrix_exp& imag_part + ); + /*! + requires + - real_part.nr() == imag_part.nr() + - real_part.nc() == imag_part.nc() + - real_part and imag_part both contain the same type of element + ensures + - returns a matrix R such that: + - R::type == std::complex where T is whatever type real_part and imag_part used. + - R has the same dimensions as real_part and imag_part + - for all valid r and c: + R(r,c) == std::complex(real_part(r,c),imag_part(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Trigonometric Functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp sin ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::sin(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp cos ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::cos(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp tan ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::tan(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp asin ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::asin(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp acos ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::acos(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp atan ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::atan(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp sinh ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::sinh(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp cosh ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::cosh(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp tanh ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == float, double, or long double + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R(r,c) == std::tanh(m(r,c)) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_MATH_FUNCTIONS_ABSTRACT_ + diff --git a/libs/dlib/matrix/matrix_op.h b/libs/dlib/matrix/matrix_op.h new file mode 100644 index 0000000..dd3e64d --- /dev/null +++ b/libs/dlib/matrix/matrix_op.h @@ -0,0 +1,479 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_OP_H_ +#define DLIB_MATRIx_OP_H_ + +#include "matrix_exp.h" + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template + class matrix_op; + + template < typename OP > + struct matrix_traits > + { + typedef typename OP::type type; + typedef typename OP::const_ret_type const_ret_type; + typedef typename OP::mem_manager_type mem_manager_type; + typedef typename OP::layout_type layout_type; + const static long NR = OP::NR; + const static long NC = OP::NC; + const static long cost = OP::cost; + }; + + template < + typename OP + > + class matrix_op : public matrix_exp > + { + /*! + WHAT THIS OBJECT REPRESENTS + The matrix_op is simply a tool for reducing the amount of boilerplate + you need to write when creating matrix expressions. + !*/ + + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + typedef typename matrix_traits::layout_type layout_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + matrix_op (T1); + public: + + matrix_op ( + const OP& op_ + ) : + op(op_) + {} + + const_ret_type operator() ( + long r, + long c + ) const { return op.apply(r,c); } + + const_ret_type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return op.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return op.destructively_aliases(item); } + + long nr ( + ) const { return op.nr(); } + + long nc ( + ) const { return op.nc(); } + + + const OP op; + }; + +// ---------------------------------------------------------------------------------------- + + template + class matrix_diag_op; + + template < typename OP > + struct matrix_traits > + { + typedef typename OP::type type; + typedef typename OP::const_ret_type const_ret_type; + typedef typename OP::mem_manager_type mem_manager_type; + typedef typename OP::layout_type layout_type; + const static long NR = OP::NR; + const static long NC = OP::NC; + const static long cost = OP::cost; + }; + + template < + typename OP + > + class matrix_diag_op : public matrix_diag_exp > + { + /*! + WHAT THIS OBJECT REPRESENTS + The matrix_diag_op is simply a tool for reducing the amount of boilerplate + you need to write when creating matrix expressions. + !*/ + + public: + typedef typename matrix_traits::type type; + typedef typename matrix_traits::const_ret_type const_ret_type; + typedef typename matrix_traits::mem_manager_type mem_manager_type; + typedef typename matrix_traits::layout_type layout_type; + const static long NR = matrix_traits::NR; + const static long NC = matrix_traits::NC; + const static long cost = matrix_traits::cost; + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + matrix_diag_op (T1); + public: + + matrix_diag_op ( + const OP& op_ + ) : + op(op_) + {} + + const_ret_type operator() ( + long r, + long c + ) const { return op.apply(r,c); } + + const_ret_type operator() ( long i ) const + { return matrix_exp::operator()(i); } + + template + bool aliases ( + const matrix_exp& item + ) const { return op.aliases(item); } + + template + bool destructively_aliases ( + const matrix_exp& item + ) const { return op.destructively_aliases(item); } + + long nr ( + ) const { return op.nr(); } + + long nc ( + ) const { return op.nc(); } + + + const OP op; + }; + +// ---------------------------------------------------------------------------------------- + + struct does_not_alias + { + /*! + This is a partial implementation of a matrix operator that never aliases + another expression. + !*/ + + template bool aliases ( const U& ) const { return false; } + template bool destructively_aliases ( const U& ) const { return false; } + }; + +// ---------------------------------------------------------------------------------------- + + template + struct basic_op_m + { + /*! + This is a partial implementation of a matrix operator that preserves + the dimensions of its argument and doesn't have destructive aliasing. + !*/ + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + basic_op_m (T1); + public: + + basic_op_m( + const M& m_ + ) : m(m_){} + + const M& m; + + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m.destructively_aliases(item); } + + }; + +// ---------------------------------------------------------------------------------------- + + template + struct basic_op_mm + { + /*! + This is a partial implementation of a matrix operator that preserves + the dimensions of its arguments and doesn't have destructive aliasing. + !*/ + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + basic_op_mm (T1, T2); + public: + + basic_op_mm( + const M1& m1_, + const M2& m2_ + ) : m1(m1_), m2(m2_){} + + const M1& m1; + const M2& m2; + + const static long NR = M1::NR; + const static long NC = M1::NC; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.destructively_aliases(item); } + + }; + +// ---------------------------------------------------------------------------------------- + + template + struct basic_op_mmm + { + /*! + This is a partial implementation of a matrix operator that preserves + the dimensions of its arguments and doesn't have destructive aliasing. + !*/ + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + basic_op_mmm (T1, T2, T3); + public: + + basic_op_mmm( + const M1& m1_, + const M2& m2_, + const M3& m3_ + ) : m1(m1_), m2(m2_), m3(m3_){} + + const M1& m1; + const M2& m2; + const M3& m3; + + const static long NR = M1::NR; + const static long NC = M1::NC; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.destructively_aliases(item) || + m3.destructively_aliases(item);} + + }; + +// ---------------------------------------------------------------------------------------- + + template + struct basic_op_mmmm + { + /*! + This is a partial implementation of a matrix operator that preserves + the dimensions of its arguments and doesn't have destructive aliasing. + !*/ + + private: + // This constructor exists simply for the purpose of causing a compile time error if + // someone tries to create an instance of this object with the wrong kind of object. + template + basic_op_mmmm (T1, T2, T3, T4); + public: + + basic_op_mmmm( + const M1& m1_, + const M2& m2_, + const M3& m3_, + const M4& m4_ + ) : m1(m1_), m2(m2_), m3(m3_), m4(m4_){} + + const M1& m1; + const M2& m2; + const M3& m3; + const M4& m4; + + const static long NR = M1::NR; + const static long NC = M1::NC; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) || m4.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.destructively_aliases(item) || + m3.destructively_aliases(item) || m4.destructively_aliases(item);} + + }; + +// ---------------------------------------------------------------------------------------- + +#define DLIB_DEFINE_OP_M(op_name, function, extra_cost) \ + template \ + struct op_name \ + { \ + op_name( \ + const M& m_ \ + ) : m(m_){} \ + \ + const M& m; \ + \ + const static long cost = M::cost+(extra_cost); \ + const static long NR = M::NR; \ + const static long NC = M::NC; \ + typedef typename M::type type; \ + typedef const typename M::type const_ret_type; \ + typedef typename M::mem_manager_type mem_manager_type; \ + typedef typename M::layout_type layout_type; \ + \ + const_ret_type apply (long r, long c) const { return function(m(r,c)); } \ + \ + long nr () const { return m.nr(); } \ + long nc () const { return m.nc(); } \ + \ + template bool aliases ( const matrix_exp& item) const \ + { return m.aliases(item); } \ + template bool destructively_aliases ( const matrix_exp& item) const \ + { return m.destructively_aliases(item); } \ + \ + }; + +#define DLIB_DEFINE_FUNCTION_M(op_name, name, function, extra_cost) \ + DLIB_DEFINE_OP_M(op_name, function, extra_cost) \ + template < typename M > \ + const matrix_op > name ( const matrix_exp& m) \ + { \ + typedef op_name op; \ + return matrix_op(op(m.ref())); \ + } + +// ---------------------------------------------------------------------------------------- + +#define DLIB_DEFINE_OP_MS(op_name, function, extra_cost) \ + template \ + struct op_name \ + { \ + op_name( \ + const M& m_, \ + const S& s_ \ + ) : m(m_), s(s_){} \ + \ + const M& m; \ + const S s; \ + \ + const static long cost = M::cost+(extra_cost); \ + const static long NR = M::NR; \ + const static long NC = M::NC; \ + typedef typename M::type type; \ + typedef const typename M::type const_ret_type; \ + typedef typename M::mem_manager_type mem_manager_type; \ + typedef typename M::layout_type layout_type; \ + \ + const_ret_type apply (long r, long c) const { return function(m(r,c), s); } \ + \ + long nr () const { return m.nr(); } \ + long nc () const { return m.nc(); } \ + \ + template bool aliases ( const matrix_exp& item) const \ + { return m.aliases(item); } \ + template bool destructively_aliases ( const matrix_exp& item) const \ + { return m.destructively_aliases(item); } \ + \ + }; + +#define DLIB_DEFINE_FUNCTION_MS(op_name, name, function, extra_cost) \ + DLIB_DEFINE_OP_MS(op_name, function, extra_cost) \ + template < typename M, typename S > \ + const matrix_op > name ( const matrix_exp& m, const S& s) \ + { \ + typedef op_name op; \ + return matrix_op(op(m.ref(), s)); \ + } + +// ---------------------------------------------------------------------------------------- + +#define DLIB_DEFINE_OP_SM(op_name, function, extra_cost) \ + template \ + struct op_name \ + { \ + op_name( \ + const S& s_, \ + const M& m_ \ + ) : m(m_), s(s_){} \ + \ + const M& m; \ + const S s; \ + \ + const static long cost = M::cost+(extra_cost); \ + const static long NR = M::NR; \ + const static long NC = M::NC; \ + typedef typename M::type type; \ + typedef const typename M::type const_ret_type; \ + typedef typename M::mem_manager_type mem_manager_type; \ + typedef typename M::layout_type layout_type; \ + \ + const_ret_type apply (long r, long c) const { return function(s, m(r,c)); } \ + \ + long nr () const { return m.nr(); } \ + long nc () const { return m.nc(); } \ + \ + template bool aliases ( const matrix_exp& item) const \ + { return m.aliases(item); } \ + template bool destructively_aliases ( const matrix_exp& item) const \ + { return m.destructively_aliases(item); } \ + \ + }; + +#define DLIB_DEFINE_FUNCTION_SM(op_name, name, function, extra_cost) \ + DLIB_DEFINE_OP_SM(op_name, function, extra_cost) \ + template < typename S, typename M > \ + const matrix_op > name (const S& s, const matrix_exp& m) \ + { \ + typedef op_name op; \ + return matrix_op(op(s, m.ref())); \ + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_OP_H_ + diff --git a/libs/dlib/matrix/matrix_qr.h b/libs/dlib/matrix/matrix_qr.h new file mode 100644 index 0000000..f13d04b --- /dev/null +++ b/libs/dlib/matrix/matrix_qr.h @@ -0,0 +1,450 @@ +// Copyright (C) 2009 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +// This code was adapted from code from the JAMA part of NIST's TNT library. +// See: http://math.nist.gov/tnt/ +#ifndef DLIB_MATRIX_QR_DECOMPOSITION_H +#define DLIB_MATRIX_QR_DECOMPOSITION_H + +#include "matrix.h" +//#include "matrix_utilities.h" +#include "matrix_subexp.h" + +#ifdef DLIB_USE_LAPACK +#include "lapack/geqrf.h" +#include "lapack/ormqr.h" +#endif + +#include "matrix_trsm.h" + +namespace dlib +{ + + template < + typename matrix_exp_type + > + class qr_decomposition + { + + public: + + const static long NR = matrix_exp_type::NR; + const static long NC = matrix_exp_type::NC; + typedef typename matrix_exp_type::type type; + typedef typename matrix_exp_type::mem_manager_type mem_manager_type; + typedef typename matrix_exp_type::layout_type layout_type; + + typedef matrix matrix_type; + + // You have supplied an invalid type of matrix_exp_type. You have + // to use this object with matrices that contain float or double type data. + COMPILE_TIME_ASSERT((is_same_type::value || + is_same_type::value )); + + + + template + qr_decomposition( + const matrix_exp& A + ); + + bool is_full_rank( + ) const; + + long nr( + ) const; + + long nc( + ) const; + + const matrix_type get_r ( + ) const; + + const matrix_type get_q ( + ) const; + + template + const matrix_type solve ( + const matrix_exp& B + ) const; + + private: + +#ifndef DLIB_USE_LAPACK + template + const matrix_type solve_mat ( + const matrix_exp& B + ) const; + + template + const matrix_type solve_vect ( + const matrix_exp& B + ) const; +#endif + + + /** Array for internal storage of decomposition. + @serial internal array storage. + */ + matrix QR_; + + /** Row and column dimensions. + @serial column dimension. + @serial row dimension. + */ + long m, n; + + /** Array for internal storage of diagonal of R. + @serial diagonal of R. + */ + typedef matrix column_vector_type; + column_vector_type tau; + column_vector_type Rdiag; + + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + template + qr_decomposition:: + qr_decomposition( + const matrix_exp& A + ) + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(A.nr() >= A.nc() && A.size() > 0, + "\tqr_decomposition::qr_decomposition(A)" + << "\n\tInvalid inputs were given to this function" + << "\n\tA.nr(): " << A.nr() + << "\n\tA.nc(): " << A.nc() + << "\n\tA.size(): " << A.size() + << "\n\tthis: " << this + ); + + + QR_ = A; + m = A.nr(); + n = A.nc(); + +#ifdef DLIB_USE_LAPACK + + lapack::geqrf(QR_, tau); + Rdiag = diag(QR_); + +#else + Rdiag.set_size(n); + long i=0, j=0, k=0; + + // Main loop. + for (k = 0; k < n; k++) + { + // Compute 2-norm of k-th column without under/overflow. + type nrm = 0; + for (i = k; i < m; i++) + { + nrm = hypot(nrm,QR_(i,k)); + } + + if (nrm != 0.0) + { + // Form k-th Householder vector. + if (QR_(k,k) < 0) + { + nrm = -nrm; + } + for (i = k; i < m; i++) + { + QR_(i,k) /= nrm; + } + QR_(k,k) += 1.0; + + // Apply transformation to remaining columns. + for (j = k+1; j < n; j++) + { + type s = 0.0; + for (i = k; i < m; i++) + { + s += QR_(i,k)*QR_(i,j); + } + s = -s/QR_(k,k); + for (i = k; i < m; i++) + { + QR_(i,j) += s*QR_(i,k); + } + } + } + Rdiag(k) = -nrm; + } +#endif + } + +// ---------------------------------------------------------------------------------------- + + template + long qr_decomposition:: + nr ( + ) const + { + return m; + } + +// ---------------------------------------------------------------------------------------- + + template + long qr_decomposition:: + nc ( + ) const + { + return n; + } + +// ---------------------------------------------------------------------------------------- + + template + bool qr_decomposition:: + is_full_rank( + ) const + { + type eps = max(abs(Rdiag)); + if (eps != 0) + eps *= std::sqrt(std::numeric_limits::epsilon())/100; + else + eps = 1; // there is no max so just use 1 + + // check if any of the elements of Rdiag are effectively 0 + return min(abs(Rdiag)) > eps; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename qr_decomposition::matrix_type qr_decomposition:: + get_r( + ) const + { + matrix_type R(n,n); + for (long i = 0; i < n; i++) + { + for (long j = 0; j < n; j++) + { + if (i < j) + { + R(i,j) = QR_(i,j); + } + else if (i == j) + { + R(i,j) = Rdiag(i); + } + else + { + R(i,j) = 0.0; + } + } + } + return R; + } + +// ---------------------------------------------------------------------------------------- + + template + const typename qr_decomposition::matrix_type qr_decomposition:: + get_q( + ) const + { +#ifdef DLIB_USE_LAPACK + matrix X; + // Take only the first n columns of an identity matrix. This way + // X ends up being an m by n matrix. + X = colm(identity_matrix(m), range(0,n-1)); + + // Compute Y = Q*X + lapack::ormqr('L','N', QR_, tau, X); + return X; + +#else + long i=0, j=0, k=0; + + matrix_type Q(m,n); + for (k = n-1; k >= 0; k--) + { + for (i = 0; i < m; i++) + { + Q(i,k) = 0.0; + } + Q(k,k) = 1.0; + for (j = k; j < n; j++) + { + if (QR_(k,k) != 0) + { + type s = 0.0; + for (i = k; i < m; i++) + { + s += QR_(i,k)*Q(i,j); + } + s = -s/QR_(k,k); + for (i = k; i < m; i++) + { + Q(i,j) += s*QR_(i,k); + } + } + } + } + return Q; +#endif + } + +// ---------------------------------------------------------------------------------------- + + template + template + const typename qr_decomposition::matrix_type qr_decomposition:: + solve( + const matrix_exp& B + ) const + { + COMPILE_TIME_ASSERT((is_same_type::value)); + + // make sure requires clause is not broken + DLIB_ASSERT(B.nr() == nr(), + "\tconst matrix_type qr_decomposition::solve(B)" + << "\n\tInvalid inputs were given to this function" + << "\n\tB.nr(): " << B.nr() + << "\n\tnr(): " << nr() + << "\n\tthis: " << this + ); + +#ifdef DLIB_USE_LAPACK + + using namespace blas_bindings; + matrix X(B); + // Compute Y = transpose(Q)*B + lapack::ormqr('L','T',QR_, tau, X); + // Solve R*X = Y; + triangular_solver(CblasLeft, CblasUpper, CblasNoTrans, CblasNonUnit, QR_, X, n); + + /* return n x nx portion of X */ + return subm(X,0,0,n,B.nc()); + +#else + // just call the right version of the solve function + if (B.nc() == 1) + return solve_vect(B); + else + return solve_mat(B); +#endif + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Private member functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +#ifndef DLIB_USE_LAPACK + + template + template + const typename qr_decomposition::matrix_type qr_decomposition:: + solve_vect( + const matrix_exp& B + ) const + { + + column_vector_type x(B); + + // Compute Y = transpose(Q)*B + for (long k = 0; k < n; k++) + { + type s = 0.0; + for (long i = k; i < m; i++) + { + s += QR_(i,k)*x(i); + } + s = -s/QR_(k,k); + for (long i = k; i < m; i++) + { + x(i) += s*QR_(i,k); + } + } + // Solve R*X = Y; + for (long k = n-1; k >= 0; k--) + { + x(k) /= Rdiag(k); + for (long i = 0; i < k; i++) + { + x(i) -= x(k)*QR_(i,k); + } + } + + + /* return n x 1 portion of x */ + return colm(x,0,n); + } + +// ---------------------------------------------------------------------------------------- + + template + template + const typename qr_decomposition::matrix_type qr_decomposition:: + solve_mat( + const matrix_exp& B + ) const + { + const long nx = B.nc(); + matrix_type X(B); + long i=0, j=0, k=0; + + // Compute Y = transpose(Q)*B + for (k = 0; k < n; k++) + { + for (j = 0; j < nx; j++) + { + type s = 0.0; + for (i = k; i < m; i++) + { + s += QR_(i,k)*X(i,j); + } + s = -s/QR_(k,k); + for (i = k; i < m; i++) + { + X(i,j) += s*QR_(i,k); + } + } + } + // Solve R*X = Y; + for (k = n-1; k >= 0; k--) + { + for (j = 0; j < nx; j++) + { + X(k,j) /= Rdiag(k); + } + for (i = 0; i < k; i++) + { + for (j = 0; j < nx; j++) + { + X(i,j) -= X(k,j)*QR_(i,k); + } + } + } + + /* return n x nx portion of X */ + return subm(X,0,0,n,nx); + } + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_USE_LAPACK not defined + +} + +#endif // DLIB_MATRIX_QR_DECOMPOSITION_H + + + diff --git a/libs/dlib/matrix/matrix_subexp.h b/libs/dlib/matrix/matrix_subexp.h new file mode 100644 index 0000000..77d06f9 --- /dev/null +++ b/libs/dlib/matrix/matrix_subexp.h @@ -0,0 +1,1002 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_SUBEXP_ +#define DLIB_MATRIx_SUBEXP_ + +#include "matrix_subexp_abstract.h" +#include "matrix_op.h" +#include "matrix.h" +#include "../geometry/rectangle.h" +#include "matrix_expressions.h" + + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + const matrix_range_static_exp range ( + ) + { + COMPILE_TIME_ASSERT(inc > 0); + return matrix_range_static_exp(); + } + + template + const matrix_range_static_exp range ( + ) + { + return matrix_range_static_exp(); + } + + inline const matrix_range_exp range ( + long start, + long end + ) + { + return matrix_range_exp(start,end); + } + + inline const matrix_range_exp range ( + long start, + long inc, + long end + ) + { + DLIB_ASSERT(inc > 0, + "\tconst matrix_exp range(start, inc, end)" + << "\n\tInvalid inputs to this function" + << "\n\tstart: " << start + << "\n\tinc: " << inc + << "\n\tend: " << end + ); + + return matrix_range_exp(start,inc,end); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_subm + { + op_subm ( + const M& m_, + const long& r__, + const long& c__, + const long& nr__, + const long& nc__ + ) : m(m_), r_(r__), c_(c__), nr_(nr__), nc_(nc__) { } + + const M& m; + const long r_; + const long c_; + const long nr_; + const long nc_; + + const static long cost = M::cost+1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const static long NR = 0; + const static long NC = 0; + + const_ret_type apply ( long r, long c) const { return m(r+r_,c+c_); } + + long nr () const { return nr_; } + long nc () const { return nc_; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > subm ( + const matrix_exp& m, + long r, + long c, + long nr, + long nc + ) + { + DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), + "\tconst matrix_exp subm(const matrix_exp& m, r, c, nr, nc)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tr: " << r + << "\n\tc: " << c + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + + typedef op_subm op; + return matrix_op(op(m.ref(),r,c,nr,nc)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const matrix_op > subm ( + const matrix_exp& m, + const rectangle& rect + ) + { + DLIB_ASSERT(get_rect(m).contains(rect) == true, + "\tconst matrix_exp subm(const matrix_exp& m, const rectangle& rect)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trect.left(): " << rect.left() + << "\n\trect.top(): " << rect.top() + << "\n\trect.right(): " << rect.right() + << "\n\trect.bottom(): " << rect.bottom() + ); + + typedef op_subm op; + return matrix_op(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_subm_range + { + op_subm_range( const M1& m1_, const M2& rows_, const M3& cols_) : + m1(m1_), rows(rows_), cols(cols_) {} + const M1& m1; + const M2& rows; + const M3& cols; + + const static long cost = M1::cost+M2::cost+M3::cost; + typedef typename M1::type type; + typedef typename M1::const_ret_type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M2::NC*M2::NR; + const static long NC = M3::NC*M3::NR; + + const_ret_type apply ( long r, long c) const { return m1(rows(r),cols(c)); } + + long nr () const { return rows.size(); } + long nc () const { return cols.size(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } + }; + + template < + typename EXP, + typename EXPr, + typename EXPc + > + const matrix_op > subm ( + const matrix_exp& m, + const matrix_exp& rows, + const matrix_exp& cols + ) + { + // the rows and cols matrices must contain elements of type long + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && + (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), + "\tconst matrix_exp subm(const matrix_exp& m, const matrix_exp& rows, const matrix_exp& cols)" + << "\n\tYou have given invalid arguments to this function" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(rows): " << min(rows) + << "\n\tmax(rows): " << max(rows) + << "\n\tmin(cols): " << min(cols) + << "\n\tmax(cols): " << max(cols) + << "\n\trows.nr(): " << rows.nr() + << "\n\trows.nc(): " << rows.nc() + << "\n\tcols.nr(): " << cols.nr() + << "\n\tcols.nc(): " << cols.nc() + ); + + typedef op_subm_range op; + return matrix_op(op(m.ref(),rows.ref(),cols.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_rowm + { + op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {} + const M& m; + const long row; + + const static long cost = M::cost; + const static long NR = 1; + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long, long c) const { return m(row,c); } + + long nr () const { return 1; } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > rowm ( + const matrix_exp& m, + long row + ) + { + DLIB_ASSERT(row >= 0 && row < m.nr(), + "\tconst matrix_exp rowm(const matrix_exp& m, row)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trow: " << row + ); + + typedef op_rowm op; + return matrix_op(op(m.ref(),row)); + } + + template + struct rowm_exp + { + typedef matrix_op > type; + }; + +// ---------------------------------------------------------------------------------------- + + template + struct op_rowm2 + { + op_rowm2(const M& m_, const long& row_, const long& len) : m(m_), row(row_), length(len) {} + const M& m; + const long row; + const long length; + + const static long cost = M::cost; + const static long NR = 1; + const static long NC = 0; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long , long c) const { return m(row,c); } + + long nr () const { return 1; } + long nc () const { return length; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > rowm ( + const matrix_exp& m, + long row, + long length + ) + { + DLIB_ASSERT(row >= 0 && row < m.nr() && + length >= 0 && length <= m.nc(), + "\tconst matrix_exp rowm(const matrix_exp& m, row, length)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trow: " << row + << "\n\tlength: " << length + ); + + typedef op_rowm2 op; + return matrix_op(op(m.ref(), row, length)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_rowm_range + { + op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {} + const M1& m1; + const M2& rows; + + const static long cost = M1::cost+M2::cost; + typedef typename M1::type type; + typedef typename M1::const_ret_type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M2::NC*M2::NR; + const static long NC = M1::NC; + + const_ret_type apply ( long r, long c) const { return m1(rows(r),c); } + + long nr () const { return rows.size(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || rows.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || rows.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > rowm ( + const matrix_exp& m, + const matrix_exp& rows + ) + { + // the rows matrix must contain elements of type long + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), + "\tconst matrix_exp rowm(const matrix_exp& m, const matrix_exp& rows)" + << "\n\tYou have given invalid arguments to this function" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(rows): " << min(rows) + << "\n\tmax(rows): " << max(rows) + << "\n\trows.nr(): " << rows.nr() + << "\n\trows.nc(): " << rows.nc() + ); + + typedef op_rowm_range op; + return matrix_op(op(m.ref(),rows.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_colm + { + op_colm(const M& m_, const long& col_) : m(m_), col(col_) {} + const M& m; + const long col; + + const static long cost = M::cost; + const static long NR = M::NR; + const static long NC = 1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long) const { return m(r,col); } + + long nr () const { return m.nr(); } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > colm ( + const matrix_exp& m, + long col + ) + { + DLIB_ASSERT(col >= 0 && col < m.nc(), + "\tconst matrix_exp colm(const matrix_exp& m, row)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tcol: " << col + ); + + typedef op_colm op; + return matrix_op(op(m.ref(),col)); + } + + template + struct colm_exp + { + typedef matrix_op > type; + }; + +// ---------------------------------------------------------------------------------------- + + template + struct op_colm2 + { + op_colm2(const M& m_, const long& col_, const long& len) : m(m_), col(col_), length(len) {} + const M& m; + const long col; + const long length; + + const static long cost = M::cost; + const static long NR = 0; + const static long NC = 1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long ) const { return m(r,col); } + + long nr () const { return length; } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > colm ( + const matrix_exp& m, + long col, + long length + ) + { + DLIB_ASSERT(col >= 0 && col < m.nc() && + length >= 0 && length <= m.nr(), + "\tconst matrix_exp colm(const matrix_exp& m, col, length)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tcol: " << col + << "\n\tlength: " << length + ); + + typedef op_colm2 op; + return matrix_op(op(m.ref(),col, length)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_colm_range + { + op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {} + const M1& m1; + const M2& cols; + + typedef typename M1::type type; + typedef typename M1::const_ret_type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR; + const static long NC = M2::NC*M2::NR; + const static long cost = M1::cost+M2::cost; + + const_ret_type apply (long r, long c) const { return m1(r,cols(c)); } + + long nr () const { return m1.nr(); } + long nc () const { return cols.size(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || cols.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || cols.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > colm ( + const matrix_exp& m, + const matrix_exp& cols + ) + { + // the cols matrix must contain elements of type long + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), + "\tconst matrix_exp colm(const matrix_exp& m, const matrix_exp& cols)" + << "\n\tYou have given invalid arguments to this function" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(cols): " << min(cols) + << "\n\tmax(cols): " << max(cols) + << "\n\tcols.nr(): " << cols.nr() + << "\n\tcols.nc(): " << cols.nc() + ); + + typedef op_colm_range op; + return matrix_op(op(m.ref(),cols.ref())); + } + +// ---------------------------------------------------------------------------------------- + + + template + class assignable_sub_matrix + { + public: + typedef T type; + typedef l layout_type; + typedef matrix matrix_type; + + assignable_sub_matrix( + matrix& m_, + const rectangle& rect_ + ) : m(m_), rect(rect_) {} + + T& operator() ( + long r, + long c + ) + { + return m(r+rect.top(),c+rect.left()); + } + + const T& operator() ( + long r, + long c + ) const + { + return m(r+rect.top(),c+rect.left()); + } + + long nr() const { return rect.height(); } + long nc() const { return rect.width(); } + + template + assignable_sub_matrix& operator= ( + const matrix_exp& exp + ) + { + DLIB_ASSERT( exp.nr() == (long)rect.height() && exp.nc() == (long)rect.width(), + "\tassignable_matrix_expression set_subm()" + << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" + << "\n\texp.nr() (source matrix): " << exp.nr() + << "\n\texp.nc() (source matrix): " << exp.nc() + << "\n\trect.width() (target matrix): " << rect.width() + << "\n\trect.height() (target matrix): " << rect.height() + ); + + if (exp.destructively_aliases(m) == false) + { + matrix_assign(*this, exp); + } + else + { + // make a temporary copy of the matrix we are going to assign to m to + // avoid aliasing issues during the copy + this->operator=(tmp(exp)); + } + + return *this; + } + + assignable_sub_matrix& operator= ( + const T& value + ) + { + for (long r = rect.top(); r <= rect.bottom(); ++r) + { + for (long c = rect.left(); c <= rect.right(); ++c) + { + m(r,c) = value; + } + } + + return *this; + } + + + matrix& m; + const rectangle rect; + }; + + + template + assignable_sub_matrix set_subm ( + matrix& m, + const rectangle& rect + ) + { + DLIB_ASSERT(get_rect(m).contains(rect) == true, + "\tassignable_matrix_expression set_subm(matrix& m, const rectangle& rect)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trect.left(): " << rect.left() + << "\n\trect.top(): " << rect.top() + << "\n\trect.right(): " << rect.right() + << "\n\trect.bottom(): " << rect.bottom() + ); + + + return assignable_sub_matrix(m,rect); + } + + + template + assignable_sub_matrix set_subm ( + matrix& m, + long r, + long c, + long nr, + long nc + ) + { + DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), + "\tassignable_matrix_expression set_subm(matrix& m, r, c, nr, nc)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tr: " << r + << "\n\tc: " << c + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + + return assignable_sub_matrix(m,rectangle(c,r, c+nc-1, r+nr-1)); + } + +// ---------------------------------------------------------------------------------------- + + template + class assignable_sub_range_matrix + { + public: + typedef T type; + typedef l layout_type; + typedef matrix matrix_type; + + assignable_sub_range_matrix( + matrix& m_, + const EXPr& rows_, + const EXPc& cols_ + ) : m(m_), rows(rows_), cols(cols_) {} + + T& operator() ( + long r, + long c + ) + { + return m(rows(r),cols(c)); + } + + long nr() const { return rows.size(); } + long nc() const { return cols.size(); } + + + template + assignable_sub_range_matrix& operator= ( + const matrix_exp& exp + ) + { + DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), + "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" + << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" + << "\n\texp.nr() (source matrix): " << exp.nr() + << "\n\texp.nc() (source matrix): " << exp.nc() + << "\n\trows.size() (target matrix): " << rows.size() + << "\n\tcols.size() (target matrix): " << cols.size() + ); + + if (exp.destructively_aliases(m) == false) + { + matrix_assign(*this, exp); + } + else + { + // make a temporary copy of the matrix we are going to assign to m to + // avoid aliasing issues during the copy + this->operator=(tmp(exp)); + } + + return *this; + } + + assignable_sub_range_matrix& operator= ( + const T& value + ) + { + for (long r = 0; r < rows.size(); ++r) + { + for (long c = 0; c < cols.size(); ++c) + { + m(rows(r),cols(c)) = value; + } + } + + return *this; + } + + private: + + matrix& m; + const EXPr rows; + const EXPc cols; + }; + + template + assignable_sub_range_matrix set_subm ( + matrix& m, + const matrix_exp& rows, + const matrix_exp& cols + ) + { + DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && + (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), + "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp& rows, const matrix_exp& cols)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(rows): " << min(rows) + << "\n\tmax(rows): " << max(rows) + << "\n\tmin(cols): " << min(cols) + << "\n\tmax(cols): " << max(cols) + << "\n\trows.nr(): " << rows.nr() + << "\n\trows.nc(): " << rows.nc() + << "\n\tcols.nr(): " << cols.nr() + << "\n\tcols.nc(): " << cols.nc() + ); + + return assignable_sub_range_matrix(m,rows.ref(),cols.ref()); + } + +// ---------------------------------------------------------------------------------------- + + template + assignable_sub_range_matrix > set_rowm ( + matrix& m, + const matrix_exp& rows + ) + { + DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), + "\tassignable_matrix_expression set_rowm(matrix& m, const matrix_exp& rows)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(rows): " << min(rows) + << "\n\tmax(rows): " << max(rows) + << "\n\trows.nr(): " << rows.nr() + << "\n\trows.nc(): " << rows.nc() + ); + + return assignable_sub_range_matrix >(m,rows.ref(),range(0,m.nc()-1)); + } + +// ---------------------------------------------------------------------------------------- + + template + assignable_sub_range_matrix,EXPc > set_colm ( + matrix& m, + const matrix_exp& cols + ) + { + DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), + "\tassignable_matrix_expression set_colm(matrix& m, const matrix_exp& cols)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tmin(cols): " << min(cols) + << "\n\tmax(cols): " << max(cols) + << "\n\tcols.nr(): " << cols.nr() + << "\n\tcols.nc(): " << cols.nc() + ); + + return assignable_sub_range_matrix,EXPc >(m,range(0,m.nr()-1),cols.ref()); + } + +// ---------------------------------------------------------------------------------------- + + template + class assignable_col_matrix + { + public: + typedef T type; + typedef l layout_type; + typedef matrix matrix_type; + + assignable_col_matrix( + matrix& m_, + const long col_ + ) : m(m_), col(col_) {} + + T& operator() ( + long r, + long + ) + { + return m(r,col); + } + + const T& operator() ( + long r, + long + ) const + { + return m(r,col); + } + + long nr() const { return m.nr(); } + long nc() const { return 1; } + + template + assignable_col_matrix& operator= ( + const matrix_exp& exp + ) + { + DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), + "\tassignable_matrix_expression set_colm()" + << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" + << "\n\texp.nr() (source matrix): " << exp.nr() + << "\n\texp.nc() (source matrix): " << exp.nc() + << "\n\tm.nr() (target matrix): " << m.nr() + ); + + if (exp.destructively_aliases(m) == false) + { + matrix_assign(*this, exp); + } + else + { + // make a temporary copy of the matrix we are going to assign to m to + // avoid aliasing issues during the copy + this->operator=(tmp(exp)); + } + + return *this; + } + + assignable_col_matrix& operator= ( + const T& value + ) + { + for (long i = 0; i < m.nr(); ++i) + { + m(i,col) = value; + } + + return *this; + } + + + matrix& m; + const long col; + }; + + + template + assignable_col_matrix set_colm ( + matrix& m, + const long col + ) + { + DLIB_ASSERT(col >= 0 && col < m.nc(), + "\tassignable_matrix_expression set_colm(matrix& m, col)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tcol: " << col + ); + + + return assignable_col_matrix(m,col); + } + +// ---------------------------------------------------------------------------------------- + + + template + class assignable_row_matrix + { + public: + typedef T type; + typedef l layout_type; + typedef matrix matrix_type; + + assignable_row_matrix( + matrix& m_, + const long row_ + ) : m(m_), row(row_) {} + + + T& operator() ( + long , + long c + ) + { + return m(row,c); + } + + const T& operator() ( + long , + long c + ) const + { + return m(row,c); + } + + long nr() const { return 1; } + long nc() const { return m.nc(); } + + + template + assignable_row_matrix& operator= ( + const matrix_exp& exp + ) + { + DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), + "\tassignable_matrix_expression set_rowm()" + << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" + << "\n\texp.nr() (source matrix): " << exp.nr() + << "\n\texp.nc() (source matrix): " << exp.nc() + << "\n\tm.nc() (target matrix): " << m.nc() + ); + + if (exp.destructively_aliases(m) == false) + { + matrix_assign(*this, exp); + } + else + { + // make a temporary copy of the matrix we are going to assign to m to + // avoid aliasing issues during the copy + this->operator=(tmp(exp)); + } + + return *this; + } + + assignable_row_matrix& operator= ( + const T& value + ) + { + for (long i = 0; i < m.nc(); ++i) + { + m(row,i) = value; + } + + return *this; + } + + + matrix& m; + const long row; + }; + + + template + assignable_row_matrix set_rowm ( + matrix& m, + const long row + ) + { + DLIB_ASSERT(row >= 0 && row < m.nr(), + "\tassignable_matrix_expression set_rowm(matrix& m, row)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trow: " << row + ); + + + return assignable_row_matrix(m,row); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_SUBEXP_ + diff --git a/libs/dlib/matrix/matrix_subexp_abstract.h b/libs/dlib/matrix/matrix_subexp_abstract.h new file mode 100644 index 0000000..2f0c850 --- /dev/null +++ b/libs/dlib/matrix/matrix_subexp_abstract.h @@ -0,0 +1,473 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_SUBEXP_ABSTRACT_ +#ifdef DLIB_MATRIx_SUBEXP_ABSTRACT_ + +#include "matrix_abstract.h" +#include "../geometry.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp range ( + ); + /*! + requires + - inc > 0 + ensures + - returns a matrix R such that: + - R::type == long + - R.nr() == 1 + - R.nc() == abs(end - start)/inc + 1 + - if (start <= end) then + - R(i) == start + i*inc + - else + - R(i) == start - i*inc + !*/ + + template + const matrix_exp range ( + ) { return range(); } + + const matrix_exp range ( + long start, + long inc, + long end + ); + /*! + requires + - inc > 0 + ensures + - returns a matrix R such that: + - R::type == long + - R.nr() == 1 + - R.nc() == abs(end - start)/inc + 1 + - if (start <= end) then + - R(i) == start + i*inc + - else + - R(i) == start - i*inc + !*/ + + const matrix_exp range ( + long start, + long end + ) { return range(start,1,end); } + +// ---------------------------------------------------------------------------------------- + + const matrix_exp subm ( + const matrix_exp& m, + const matrix_exp& rows, + const matrix_exp& cols, + ); + /*! + requires + - rows and cols contain elements of type long + - 0 <= min(rows) && max(rows) < m.nr() + - 0 <= min(cols) && max(cols) < m.nc() + - rows.nr() == 1 || rows.nc() == 1 + - cols.nr() == 1 || cols.nc() == 1 + (i.e. rows and cols must be vectors) + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R.nr() == rows.size() + - R.nc() == cols.size() + - for all valid r and c: + R(r,c) == m(rows(r),cols(c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp subm ( + const matrix_exp& m, + long row, + long col, + long nr, + long nc + ); + /*! + requires + - row >= 0 + - col >= 0 + - nr >= 0 + - nc >= 0 + - row + nr <= m.nr() + - col + nc <= m.nc() + ensures + - returns a matrix R such that: + - R.nr() == nr + - R.nc() == nc + - for all valid r and c: + R(r, c) == m(r+row,c+col) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp subm ( + const matrix_exp& m, + const rectangle& rect + ); + /*! + requires + - get_rect(m).contains(rect) == true + (i.e. rect is a region inside the matrix m) + ensures + - returns a matrix R such that: + - R.nr() == rect.height() + - R.nc() == rect.width() + - for all valid r and c: + R(r, c) == m(r+rect.top(), c+rect.left()) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp rowm ( + const matrix_exp& m, + long row + ); + /*! + requires + - 0 <= row < m.nr() + ensures + - returns a matrix R such that: + - R.nr() == 1 + - R.nc() == m.nc() + - for all valid i: + R(i) == m(row,i) + !*/ + + template + struct rowm_exp + { + /*! + WHAT THIS OBJECT REPRESENTS + This struct allows you to determine the type of matrix expression + object returned from the rowm(m,row) function. An example makes its + use clear: + + template + void do_something( const matrix_exp& mat) + { + // r is a matrix expression that aliases mat. + typename rowm_exp::type r = rowm(mat,0); + + // Print the first row of mat. So we see that by using + // rowm_exp we can save the object returned by rowm() in + // a local variable. + cout << r << endl; + + // Note that you can only save the return value of rowm() to + // a local variable if the argument to rowm() has a lifetime + // beyond the rowm() expression. The example shown above is + // OK but the following would result in undefined behavior: + typename rowm_exp::type bad = rowm(mat + mat,0); + } + !*/ + typedef type_of_expression_returned_by_rowm type; + }; + +// ---------------------------------------------------------------------------------------- + + const matrix_exp rowm ( + const matrix_exp& m, + long row, + long length + ); + /*! + requires + - 0 <= row < m.nr() + - 0 <= length <= m.nc() + ensures + - returns a matrix R such that: + - R.nr() == 1 + - R.nc() == length + - for all valid i: + R(i) == m(row,i) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp rowm ( + const matrix_exp& m, + const matrix_exp& rows + ); + /*! + requires + - rows contains elements of type long + - 0 <= min(rows) && max(rows) < m.nr() + - rows.nr() == 1 || rows.nc() == 1 + (i.e. rows must be a vector) + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R.nr() == rows.size() + - R.nc() == m.nc() + - for all valid r and c: + R(r,c) == m(rows(r),c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp colm ( + const matrix_exp& m, + long col + ); + /*! + requires + - 0 <= col < m.nc() + ensures + - returns a matrix R such that: + - R.nr() == m.nr() + - R.nc() == 1 + - for all valid i: + R(i) == m(i,col) + !*/ + + template + struct colm_exp + { + /*! + WHAT THIS OBJECT REPRESENTS + This struct allows you to determine the type of matrix expression + object returned from the colm(m,col) function. An example makes its + use clear: + + template + void do_something( const matrix_exp& mat) + { + // c is a matrix expression that aliases mat. + typename colm_exp::type c = colm(mat,0); + + // Print the first column of mat. So we see that by using + // colm_exp we can save the object returned by colm() in + // a local variable. + cout << c << endl; + + // Note that you can only save the return value of colm() to + // a local variable if the argument to colm() has a lifetime + // beyond the colm() expression. The example shown above is + // OK but the following would result in undefined behavior: + typename colm_exp::type bad = colm(mat + mat,0); + } + !*/ + typedef type_of_expression_returned_by_colm type; + }; + +// ---------------------------------------------------------------------------------------- + + const matrix_exp colm ( + const matrix_exp& m, + long col, + long length + ); + /*! + requires + - 0 <= col < m.nc() + - 0 <= length <= m.nr() + ensures + - returns a matrix R such that: + - R.nr() == length + - R.nc() == 1 + - for all valid i: + R(i) == m(i,col) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp colm ( + const matrix_exp& m, + const matrix_exp& cols + ); + /*! + requires + - cols contains elements of type long + - 0 <= min(cols) && max(cols) < m.nc() + - cols.nr() == 1 || cols.nc() == 1 + (i.e. cols must be a vector) + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R.nr() == m.nr() + - R.nc() == cols.size() + - for all valid r and c: + R(r,c) == m(r,cols(c)) + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_subm ( + matrix& m, + long row, + long col, + long nr, + long nc + ); + /*! + requires + - row >= 0 + - col >= 0 + - nr >= 0 + - nc >= 0 + - row + nr <= m.nr() + - col + nc <= m.nc() + ensures + - statements of the following form: + - set_subm(m,row,col,nr,nc) = some_matrix; + result in it being the case that: + - subm(m,row,col,nr,nc) == some_matrix. + + - statements of the following form: + - set_subm(m,row,col,nr,nc) = scalar_value; + result in it being the case that: + - subm(m,row,col,nr,nc) == uniform_matrix(nr,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_subm ( + matrix& m, + const rectangle& rect + ); + /*! + requires + - get_rect(m).contains(rect) == true + (i.e. rect is a region inside the matrix m) + ensures + - statements of the following form: + - set_subm(m,rect) = some_matrix; + result in it being the case that: + - subm(m,rect) == some_matrix. + + - statements of the following form: + - set_subm(m,rect) = scalar_value; + result in it being the case that: + - subm(m,rect) == uniform_matrix(nr,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_subm ( + matrix& m, + const matrix_exp& rows, + const matrix_exp& cols + ); + /*! + requires + - rows and cols contain elements of type long + - 0 <= min(rows) && max(rows) < m.nr() + - 0 <= min(cols) && max(cols) < m.nc() + - rows.nr() == 1 || rows.nc() == 1 + - cols.nr() == 1 || cols.nc() == 1 + (i.e. rows and cols must be vectors) + ensures + - statements of the following form: + - set_subm(m,rows,cols) = some_matrix; + result in it being the case that: + - subm(m,rows,cols) == some_matrix. + + - statements of the following form: + - set_subm(m,rows,cols) = scalar_value; + result in it being the case that: + - subm(m,rows,cols) == uniform_matrix(nr,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_rowm ( + matrix& m, + long row + ); + /*! + requires + - 0 <= row < m.nr() + ensures + - statements of the following form: + - set_rowm(m,row) = some_matrix; + result in it being the case that: + - rowm(m,row) == some_matrix. + + - statements of the following form: + - set_rowm(m,row) = scalar_value; + result in it being the case that: + - rowm(m,row) == uniform_matrix(1,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_rowm ( + matrix& m, + const matrix_exp& rows + ); + /*! + requires + - rows contains elements of type long + - 0 <= min(rows) && max(rows) < m.nr() + - rows.nr() == 1 || rows.nc() == 1 + (i.e. rows must be a vector) + ensures + - statements of the following form: + - set_rowm(m,rows) = some_matrix; + result in it being the case that: + - rowm(m,rows) == some_matrix. + + - statements of the following form: + - set_rowm(m,rows) = scalar_value; + result in it being the case that: + - rowm(m,rows) == uniform_matrix(nr,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_colm ( + matrix& m, + long col + ); + /*! + requires + - 0 <= col < m.nr() + ensures + - statements of the following form: + - set_colm(m,col) = some_matrix; + result in it being the case that: + - colm(m,col) == some_matrix. + + - statements of the following form: + - set_colm(m,col) = scalar_value; + result in it being the case that: + - colm(m,col) == uniform_matrix(nr,1,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + + assignable_matrix_expression set_colm ( + matrix& m, + const matrix_exp& cols + ); + /*! + requires + - cols contains elements of type long + - 0 <= min(cols) && max(cols) < m.nc() + - cols.nr() == 1 || cols.nc() == 1 + (i.e. cols must be a vector) + ensures + - statements of the following form: + - set_colm(m,cols) = some_matrix; + result in it being the case that: + - colm(m,cols) == some_matrix. + + - statements of the following form: + - set_colm(m,cols) = scalar_value; + result in it being the case that: + - colm(m,cols) == uniform_matrix(nr,nc,scalar_value). + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_SUBEXP_ABSTRACT_ + diff --git a/libs/dlib/matrix/matrix_trsm.h b/libs/dlib/matrix/matrix_trsm.h new file mode 100644 index 0000000..f43e45a --- /dev/null +++ b/libs/dlib/matrix/matrix_trsm.h @@ -0,0 +1,651 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRiX_TRSM_H__ +#define DLIB_MATRiX_TRSM_H__ +#include "lapack/fortran_id.h" +#include "cblas_constants.h" + +namespace dlib +{ + namespace blas_bindings + { + + extern "C" + { + void cblas_strsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb); + + void cblas_dtrsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb); + } + + // ------------------------------------------------------------------------------------ + +/* Purpose */ +/* ======= */ + +/* DTRSM solves one of the matrix equations */ + +/* op( A )*X = alpha*B, or X*op( A ) = alpha*B, */ + +/* where alpha is a scalar, X and B are m by n matrices, A is a unit, or */ +/* non-unit, upper or lower triangular matrix and op( A ) is one of */ + +/* op( A ) = A or op( A ) = A'. */ + +/* The matrix X is overwritten on B. */ + +/* Arguments */ +/* ========== */ + +/* SIDE - CHARACTER*1. */ +/* On entry, SIDE specifies whether op( A ) appears on the left */ +/* or right of X as follows: */ + +/* SIDE = 'L' or 'l' op( A )*X = alpha*B. */ + +/* SIDE = 'R' or 'r' X*op( A ) = alpha*B. */ + +/* Unchanged on exit. */ + +/* UPLO - CHARACTER*1. */ +/* On entry, UPLO specifies whether the matrix A is an upper or */ +/* lower triangular matrix as follows: */ + +/* UPLO = 'U' or 'u' A is an upper triangular matrix. */ + +/* UPLO = 'L' or 'l' A is a lower triangular matrix. */ + +/* Unchanged on exit. */ + +/* TRANSA - CHARACTER*1. */ +/* On entry, TRANSA specifies the form of op( A ) to be used in */ +/* the matrix multiplication as follows: */ + +/* TRANSA = 'N' or 'n' op( A ) = A. */ + +/* TRANSA = 'T' or 't' op( A ) = A'. */ + +/* TRANSA = 'C' or 'c' op( A ) = A'. */ + +/* Unchanged on exit. */ + +/* DIAG - CHARACTER*1. */ +/* On entry, DIAG specifies whether or not A is unit triangular */ +/* as follows: */ + +/* DIAG = 'U' or 'u' A is assumed to be unit triangular. */ + +/* DIAG = 'N' or 'n' A is not assumed to be unit */ +/* triangular. */ + +/* Unchanged on exit. */ + +/* M - INTEGER. */ +/* On entry, M specifies the number of rows of B. M must be at */ +/* least zero. */ +/* Unchanged on exit. */ + +/* N - INTEGER. */ +/* On entry, N specifies the number of columns of B. N must be */ +/* at least zero. */ +/* Unchanged on exit. */ + +/* ALPHA - DOUBLE PRECISION. */ +/* On entry, ALPHA specifies the scalar alpha. When alpha is */ +/* zero then A is not referenced and B need not be set before */ +/* entry. */ +/* Unchanged on exit. */ + +/* A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m */ +/* when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'. */ +/* Before entry with UPLO = 'U' or 'u', the leading k by k */ +/* upper triangular part of the array A must contain the upper */ +/* triangular matrix and the strictly lower triangular part of */ +/* A is not referenced. */ +/* Before entry with UPLO = 'L' or 'l', the leading k by k */ +/* lower triangular part of the array A must contain the lower */ +/* triangular matrix and the strictly upper triangular part of */ +/* A is not referenced. */ +/* Note that when DIAG = 'U' or 'u', the diagonal elements of */ +/* A are not referenced either, but are assumed to be unity. */ +/* Unchanged on exit. */ + +/* LDA - INTEGER. */ +/* On entry, LDA specifies the first dimension of A as declared */ +/* in the calling (sub) program. When SIDE = 'L' or 'l' then */ +/* LDA must be at least max( 1, m ), when SIDE = 'R' or 'r' */ +/* then LDA must be at least max( 1, n ). */ +/* Unchanged on exit. */ + +/* B - DOUBLE PRECISION array of DIMENSION ( LDB, n ). */ +/* Before entry, the leading m by n part of the array B must */ +/* contain the right-hand side matrix B, and on exit is */ +/* overwritten by the solution matrix X. */ + +/* LDB - INTEGER. */ +/* On entry, LDB specifies the first dimension of B as declared */ +/* in the calling (sub) program. LDB must be at least */ +/* max( 1, m ). */ +/* Unchanged on exit. */ + + +/* Level 3 Blas routine. */ + + +/* -- Written on 8-February-1989. */ +/* Jack Dongarra, Argonne National Laboratory. */ +/* Iain Duff, AERE Harwell. */ +/* Jeremy Du Croz, Numerical Algorithms Group Ltd. */ +/* Sven Hammarling, Numerical Algorithms Group Ltd. */ + + template + void local_trsm( + const enum CBLAS_ORDER Order, + enum CBLAS_SIDE Side, + enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, + long m, + long n, + T alpha, + const T *a, + long lda, + T *b, + long ldb + ) + /*! + This is a copy of the dtrsm routine from the netlib.org BLAS which was run though + f2c and converted into this form for use when a BLAS library is not available. + !*/ + { + if (Order == CblasRowMajor) + { + // since row major ordering looks like transposition to FORTRAN we need to flip a + // few things. + if (Side == CblasLeft) + Side = CblasRight; + else + Side = CblasLeft; + + if (Uplo == CblasUpper) + Uplo = CblasLower; + else + Uplo = CblasUpper; + + std::swap(m,n); + } + + /* System generated locals */ + long a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3; + + /* Local variables */ + long i__, j, k, info; + T temp; + bool lside; + long nrowa; + bool upper; + bool nounit; + + /* Parameter adjustments */ + a_dim1 = lda; + a_offset = 1 + a_dim1; + a -= a_offset; + b_dim1 = ldb; + b_offset = 1 + b_dim1; + b -= b_offset; + + /* Function Body */ + lside = (Side == CblasLeft); + if (lside) + { + nrowa = m; + } else + { + nrowa = n; + } + nounit = (Diag == CblasNonUnit); + upper = (Uplo == CblasUpper); + + info = 0; + if (! lside && ! (Side == CblasRight)) { + info = 1; + } else if (! upper && !(Uplo == CblasLower) ) { + info = 2; + } else if (!(TransA == CblasNoTrans) && + !(TransA == CblasTrans) && + !(TransA == CblasConjTrans)) { + info = 3; + } else if (!(Diag == CblasUnit) && + !(Diag == CblasNonUnit) ) { + info = 4; + } else if (m < 0) { + info = 5; + } else if (n < 0) { + info = 6; + } else if (lda < std::max(1,nrowa)) { + info = 9; + } else if (ldb < std::max(1,m)) { + info = 11; + } + DLIB_CASSERT( info == 0, "Invalid inputs given to local_trsm"); + + /* Quick return if possible. */ + + if (m == 0 || n == 0) { + return; + } + + /* And when alpha.eq.zero. */ + + if (alpha == 0.) { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] = 0.; + /* L10: */ + } + /* L20: */ + } + return; + } + + /* Start the operations. */ + + if (lside) { + if (TransA == CblasNoTrans) { + + /* Form B := alpha*inv( A )*B. */ + + if (upper) { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + if (alpha != 1.) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] + ; + /* L30: */ + } + } + for (k = m; k >= 1; --k) { + if (b[k + j * b_dim1] != 0.) { + if (nounit) { + b[k + j * b_dim1] /= a[k + k * a_dim1]; + } + i__2 = k - 1; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ + i__ + k * a_dim1]; + /* L40: */ + } + } + /* L50: */ + } + /* L60: */ + } + } else { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + if (alpha != 1.) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] + ; + /* L70: */ + } + } + i__2 = m; + for (k = 1; k <= i__2; ++k) { + if (b[k + j * b_dim1] != 0.) { + if (nounit) { + b[k + j * b_dim1] /= a[k + k * a_dim1]; + } + i__3 = m; + for (i__ = k + 1; i__ <= i__3; ++i__) { + b[i__ + j * b_dim1] -= b[k + j * b_dim1] * a[ + i__ + k * a_dim1]; + /* L80: */ + } + } + /* L90: */ + } + /* L100: */ + } + } + } else { + + /* Form B := alpha*inv( A' )*B. */ + + if (upper) { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + temp = alpha * b[i__ + j * b_dim1]; + i__3 = i__ - 1; + for (k = 1; k <= i__3; ++k) { + temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; + /* L110: */ + } + if (nounit) { + temp /= a[i__ + i__ * a_dim1]; + } + b[i__ + j * b_dim1] = temp; + /* L120: */ + } + /* L130: */ + } + } else { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + for (i__ = m; i__ >= 1; --i__) { + temp = alpha * b[i__ + j * b_dim1]; + i__2 = m; + for (k = i__ + 1; k <= i__2; ++k) { + temp -= a[k + i__ * a_dim1] * b[k + j * b_dim1]; + /* L140: */ + } + if (nounit) { + temp /= a[i__ + i__ * a_dim1]; + } + b[i__ + j * b_dim1] = temp; + /* L150: */ + } + /* L160: */ + } + } + } + } else { + if (TransA == CblasNoTrans) { + + /* Form B := alpha*B*inv( A ). */ + + if (upper) { + i__1 = n; + for (j = 1; j <= i__1; ++j) { + if (alpha != 1.) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] + ; + /* L170: */ + } + } + i__2 = j - 1; + for (k = 1; k <= i__2; ++k) { + if (a[k + j * a_dim1] != 0.) { + i__3 = m; + for (i__ = 1; i__ <= i__3; ++i__) { + b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ + i__ + k * b_dim1]; + /* L180: */ + } + } + /* L190: */ + } + if (nounit) { + temp = 1. / a[j + j * a_dim1]; + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; + /* L200: */ + } + } + /* L210: */ + } + } else { + for (j = n; j >= 1; --j) { + if (alpha != 1.) { + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__ + j * b_dim1] = alpha * b[i__ + j * b_dim1] + ; + /* L220: */ + } + } + i__1 = n; + for (k = j + 1; k <= i__1; ++k) { + if (a[k + j * a_dim1] != 0.) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] -= a[k + j * a_dim1] * b[ + i__ + k * b_dim1]; + /* L230: */ + } + } + /* L240: */ + } + if (nounit) { + temp = 1. / a[j + j * a_dim1]; + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1]; + /* L250: */ + } + } + /* L260: */ + } + } + } else { + + /* Form B := alpha*B*inv( A' ). */ + + if (upper) { + for (k = n; k >= 1; --k) { + if (nounit) { + temp = 1. / a[k + k * a_dim1]; + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; + /* L270: */ + } + } + i__1 = k - 1; + for (j = 1; j <= i__1; ++j) { + if (a[j + k * a_dim1] != 0.) { + temp = a[j + k * a_dim1]; + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + j * b_dim1] -= temp * b[i__ + k * + b_dim1]; + /* L280: */ + } + } + /* L290: */ + } + if (alpha != 1.) { + i__1 = m; + for (i__ = 1; i__ <= i__1; ++i__) { + b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] + ; + /* L300: */ + } + } + /* L310: */ + } + } else { + i__1 = n; + for (k = 1; k <= i__1; ++k) { + if (nounit) { + temp = 1. / a[k + k * a_dim1]; + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1]; + /* L320: */ + } + } + i__2 = n; + for (j = k + 1; j <= i__2; ++j) { + if (a[j + k * a_dim1] != 0.) { + temp = a[j + k * a_dim1]; + i__3 = m; + for (i__ = 1; i__ <= i__3; ++i__) { + b[i__ + j * b_dim1] -= temp * b[i__ + k * + b_dim1]; + /* L330: */ + } + } + /* L340: */ + } + if (alpha != 1.) { + i__2 = m; + for (i__ = 1; i__ <= i__2; ++i__) { + b[i__ + k * b_dim1] = alpha * b[i__ + k * b_dim1] + ; + /* L350: */ + } + } + /* L360: */ + } + } + } + } + } + + // ------------------------------------------------------------------------------------ + + inline void cblas_trsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const float alpha, const float *A, const int lda, + float *B, const int ldb) + { +#ifdef DLIB_USE_BLAS + if (M > 4) + { + cblas_strsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); + return; + } +#endif + local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); + } + + inline void cblas_trsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const double alpha, const double *A, const int lda, + double *B, const int ldb) + { +#ifdef DLIB_USE_BLAS + if (M > 4) + { + cblas_dtrsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); + return; + } +#endif + local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); + } + + inline void cblas_trsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, const int M, const int N, + const long double alpha, const long double *A, const int lda, + long double *B, const int ldb) + { + local_trsm(Order, Side, Uplo, TransA, Diag, M, N, alpha, A, lda, B, ldb); + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + inline void triangular_solver ( + const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, + const matrix& A, + const T alpha, + matrix& B + ) + { + cblas_trsm(CblasRowMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), + alpha, &A(0,0), A.nc(), &B(0,0), B.nc()); + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + inline void triangular_solver ( + const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, + const matrix& A, + const T alpha, + matrix& B + ) + { + cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, B.nr(), B.nc(), + alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM + > + inline void triangular_solver ( + const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, + const matrix& A, + matrix& B, + long rows_of_B + ) + { + const T alpha = 1; + cblas_trsm(CblasColMajor, Side, Uplo, TransA, Diag, rows_of_B, B.nc(), + alpha, &A(0,0), A.nr(), &B(0,0), B.nr()); + } + + // ------------------------------------------------------------------------------------ + + template < + typename T, + long NR1, long NR2, + long NC1, long NC2, + typename MM, + typename layout + > + inline void triangular_solver ( + const enum CBLAS_SIDE Side, + const enum CBLAS_UPLO Uplo, + const enum CBLAS_TRANSPOSE TransA, + const enum CBLAS_DIAG Diag, + const matrix& A, + matrix& B + ) + { + const T alpha = 1; + triangular_solver(Side, Uplo, TransA, Diag, A, alpha, B); + } + + // ------------------------------------------------------------------------------------ + + } +} + +#endif // DLIB_MATRiX_TRSM_H__ + diff --git a/libs/dlib/matrix/matrix_utilities.h b/libs/dlib/matrix/matrix_utilities.h new file mode 100644 index 0000000..7aabf0c --- /dev/null +++ b/libs/dlib/matrix/matrix_utilities.h @@ -0,0 +1,4108 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MATRIx_UTILITIES_ +#define DLIB_MATRIx_UTILITIES_ + +#include "matrix_utilities_abstract.h" +#include "matrix.h" +#include +#include +#include +#include "../pixel.h" +#include "../stl_checked.h" +#include +#include +#include "../std_allocator.h" +#include "matrix_expressions.h" +#include "matrix_math_functions.h" +#include "matrix_op.h" +#include "../general_hash/murmur_hash3.h" + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*!A is_complex + This is a template that can be used to determine if a type is a specialization + of the std::complex template class. + + For example: + is_complex::value == false + is_complex >::value == true + !*/ + + template + struct is_complex { static const bool value = false; }; + + template + struct is_complex > { static const bool value = true; }; + template + struct is_complex& > { static const bool value = true; }; + template + struct is_complex& > { static const bool value = true; }; + template + struct is_complex > { static const bool value = true; }; + +// ---------------------------------------------------------------------------------------- + + template + inline bool is_row_vector ( + const matrix_exp& m + ) { return m.nr() == 1; } + + template + inline bool is_col_vector ( + const matrix_exp& m + ) { return m.nc() == 1; } + + template + inline bool is_vector ( + const matrix_exp& m + ) { return is_row_vector(m) || is_col_vector(m); } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + const T& magnitude (const T& item) { return item; } + template + T magnitude (const std::complex& item) { return std::norm(item); } + } + + template < + typename EXP + > + void find_min_and_max ( + const matrix_exp& m, + typename EXP::type& min_val, + typename EXP::type& max_val + ) + { + DLIB_ASSERT(m.size() > 0, + "\ttype find_min_and_max(const matrix_exp& m, min_val, max_val)" + << "\n\tYou can't ask for the min and max of an empty matrix" + << "\n\tm.size(): " << m.size() + ); + typedef typename matrix_exp::type type; + + min_val = m(0,0); + max_val = min_val; + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + type temp = m(r,c); + if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(max_val)) + max_val = temp; + if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(min_val)) + min_val = temp; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + long index_of_max ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0 && is_vector(m) == true, + "\tlong index_of_max(const matrix_exp& m)" + << "\n\tm must be a row or column matrix" + << "\n\tm.size(): " << m.size() + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef typename matrix_exp::type type; + + type val = m(0); + long best_idx = 0; + for (long i = 1; i < m.size(); ++i) + { + type temp = m(i); + if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(val)) + { + val = temp; + best_idx = i; + } + } + return best_idx; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + long index_of_min ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0 && is_vector(m), + "\tlong index_of_min(const matrix_exp& m)" + << "\n\tm must be a row or column matrix" + << "\n\tm.size(): " << m.size() + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef typename matrix_exp::type type; + + type val = m(0); + long best_idx = 0; + for (long i = 1; i < m.size(); ++i) + { + type temp = m(i); + if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(val)) + { + val = temp; + best_idx = i; + } + } + return best_idx; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type max ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0, + "\ttype max(const matrix_exp& m)" + << "\n\tYou can't ask for the max() of an empty matrix" + << "\n\tm.size(): " << m.size() + ); + typedef typename matrix_exp::type type; + + type val = m(0,0); + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + type temp = m(r,c); + if (dlib::impl::magnitude(temp) > dlib::impl::magnitude(val)) + val = temp; + } + } + return val; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type min ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0, + "\ttype min(const matrix_exp& m)" + << "\n\tYou can't ask for the min() of an empty matrix" + << "\n\tm.size(): " << m.size() + ); + typedef typename matrix_exp::type type; + + type val = m(0,0); + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + type temp = m(r,c); + if (dlib::impl::magnitude(temp) < dlib::impl::magnitude(val)) + val = temp; + } + } + return val; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type length ( + const matrix_exp& m + ) + { + DLIB_ASSERT(is_vector(m) == true, + "\ttype length(const matrix_exp& m)" + << "\n\tm must be a row or column vector" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + return std::sqrt(sum(squared(m))); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type length_squared ( + const matrix_exp& m + ) + { + DLIB_ASSERT(is_vector(m) == true, + "\ttype length_squared(const matrix_exp& m)" + << "\n\tm must be a row or column vector" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + return sum(squared(m)); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename array_type + > + const typename enable_if,array_type>::type& + array_to_matrix ( + const array_type& array + ) + { + return array; + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_array2d_to_mat : does_not_alias + { + op_array2d_to_mat( const T& array_) : array(array_){} + + const T& array; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 0; + typedef typename T::type type; + typedef const typename T::type& const_ret_type; + typedef typename T::mem_manager_type mem_manager_type; + typedef row_major_layout layout_type; + + const_ret_type apply (long r, long c ) const { return array[r][c]; } + + long nr () const { return array.nr(); } + long nc () const { return array.nc(); } + }; + + template < + typename array_type + > + const typename disable_if,matrix_op > >::type + array_to_matrix ( + const array_type& array + ) + { + typedef op_array2d_to_mat op; + return matrix_op(op(array)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_array_to_mat : does_not_alias + { + op_array_to_mat( const T& vect_) : vect(vect_){} + + const T& vect; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 1; + typedef typename T::type type; + typedef const typename T::type& const_ret_type; + typedef typename T::mem_manager_type mem_manager_type; + typedef row_major_layout layout_type; + + const_ret_type apply (long r, long ) const { return vect[r]; } + + long nr () const { return vect.size(); } + long nc () const { return 1; } + }; + + template < + typename vector_type + > + const typename disable_if, matrix_op > >::type + vector_to_matrix ( + const vector_type& vector + ) + { + typedef op_array_to_mat op; + return matrix_op(op(vector)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename vector_type + > + const typename enable_if,vector_type>::type& vector_to_matrix ( + const vector_type& vector + ) + /*! + This overload catches the case where the argument to this function is + already a matrix. + !*/ + { + return vector; + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_std_vect_to_mat : does_not_alias + { + op_std_vect_to_mat( const T& vect_) : vect(vect_){} + + const T& vect; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 1; + typedef typename T::value_type type; + typedef const typename T::value_type& const_ret_type; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + + const_ret_type apply (long r, long ) const { return vect[r]; } + + long nr () const { return vect.size(); } + long nc () const { return 1; } + }; + + template < + typename value_type, + typename alloc + > + const matrix_op > > vector_to_matrix ( + const std::vector& vector + ) + { + typedef op_std_vect_to_mat > op; + return matrix_op(op(vector)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename value_type, + typename alloc + > + const matrix_op > > vector_to_matrix ( + const std_vector_c& vector + ) + { + typedef op_std_vect_to_mat > op; + return matrix_op(op(vector)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_pointer_to_col_vect : does_not_alias + { + op_pointer_to_col_vect( + const T* ptr_, + const long size_ + ) : ptr(ptr_), size(size_){} + + const T* ptr; + const long size; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 1; + typedef T type; + typedef const T& const_ret_type; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + + const_ret_type apply (long r, long ) const { return ptr[r]; } + + long nr () const { return size; } + long nc () const { return 1; } + }; + + template < + typename T + > + const matrix_op > pointer_to_column_vector ( + const T* ptr, + long nr + ) + { + DLIB_ASSERT(nr > 0 , + "\tconst matrix_exp pointer_to_column_vector(ptr, nr)" + << "\n\t nr must be bigger than 0" + << "\n\t nr: " << nr + ); + typedef op_pointer_to_col_vect op; + return matrix_op(op(ptr, nr)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_pointer_to_mat : does_not_alias + { + op_pointer_to_mat( + const T* ptr_, + const long nr_, + const long nc_ + ) : ptr(ptr_), rows(nr_), cols(nc_){} + + const T* ptr; + const long rows; + const long cols; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 0; + typedef T type; + typedef const T& const_ret_type; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + + const_ret_type apply (long r, long c) const { return ptr[r*cols + c]; } + + long nr () const { return rows; } + long nc () const { return cols; } + }; + + template < + typename T + > + const matrix_op > pointer_to_matrix ( + const T* ptr, + long nr, + long nc + ) + { + DLIB_ASSERT(nr > 0 && nc > 0 , + "\tconst matrix_exp pointer_to_matrix(ptr, nr, nc)" + << "\n\t nr and nc must be bigger than 0" + << "\n\t nr: " << nr + << "\n\t nc: " << nc + ); + typedef op_pointer_to_mat op; + return matrix_op(op(ptr,nr,nc)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_trans + { + op_trans( const M& m_) : m(m_){} + + const M& m; + + const static long cost = M::cost; + const static long NR = M::NC; + const static long NC = M::NR; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply (long r, long c) const { return m(c,r); } + + long nr () const { return m.nc(); } + long nc () const { return m.nr(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + + }; + + template < + typename M + > + const matrix_op > trans ( + const matrix_exp& m + ) + { + typedef op_trans op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + +// don't to anything at all for diagonal matrices + template < + typename M + > + const matrix_diag_exp& trans ( + const matrix_diag_exp& m + ) + { + return m; + } + +// ---------------------------------------------------------------------------------------- + +// I introduced this struct because it avoids an inane compiler warning from gcc + template + struct is_not_ct_vector{ static const bool value = (EXP::NR != 1 && EXP::NC != 1); }; + + template < + typename EXP1, + typename EXP2 + > + typename enable_if_c<(is_not_ct_vector::value) || (is_not_ct_vector::value), + typename EXP1::type>::type + dot ( + const matrix_exp& m1, + const matrix_exp& m2 + ) + { + // You are getting an error on this line because you are trying to + // compute the dot product between two matrices that aren't both vectors (i.e. + // they aren't column or row matrices). + COMPILE_TIME_ASSERT(EXP1::NR*EXP1::NC == 0 || + EXP2::NR*EXP2::NC == 0); + + DLIB_ASSERT(is_vector(m1) && is_vector(m2) && m1.size() == m2.size(), + "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" + << "\n\t You can only compute the dot product between vectors of equal length" + << "\n\t is_vector(m1): " << is_vector(m1) + << "\n\t is_vector(m2): " << is_vector(m2) + << "\n\t m1.size(): " << m1.size() + << "\n\t m2.size(): " << m2.size() + ); + + if (is_col_vector(m1) && is_col_vector(m2)) return (trans(m1)*m2)(0); + if (is_col_vector(m1) && is_row_vector(m2)) return (m2*m1)(0); + if (is_row_vector(m1) && is_col_vector(m2)) return (m1*m2)(0); + + //if (is_row_vector(m1) && is_row_vector(m2)) + return (m1*trans(m2))(0); + } + + template < typename EXP1, typename EXP2 > + typename enable_if_c::type + dot ( const matrix_exp& m1, const matrix_exp& m2) + { + DLIB_ASSERT(m1.size() == m2.size(), + "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" + << "\n\t You can only compute the dot product between vectors of equal length" + << "\n\t m1.size(): " << m1.size() + << "\n\t m2.size(): " << m2.size() + ); + + return m1*trans(m2); + } + + template < typename EXP1, typename EXP2 > + typename enable_if_c::type + dot ( const matrix_exp& m1, const matrix_exp& m2) + { + DLIB_ASSERT(m1.size() == m2.size(), + "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" + << "\n\t You can only compute the dot product between vectors of equal length" + << "\n\t m1.size(): " << m1.size() + << "\n\t m2.size(): " << m2.size() + ); + + return m1*m2; + } + + template < typename EXP1, typename EXP2 > + typename enable_if_c::type + dot ( const matrix_exp& m1, const matrix_exp& m2) + { + DLIB_ASSERT(m1.size() == m2.size(), + "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" + << "\n\t You can only compute the dot product between vectors of equal length" + << "\n\t m1.size(): " << m1.size() + << "\n\t m2.size(): " << m2.size() + ); + + return m2*m1; + } + + template < typename EXP1, typename EXP2 > + typename enable_if_c::type + dot ( const matrix_exp& m1, const matrix_exp& m2) + { + DLIB_ASSERT(m1.size() == m2.size(), + "\t type dot(const matrix_exp& m1, const matrix_exp& m2)" + << "\n\t You can only compute the dot product between vectors of equal length" + << "\n\t m1.size(): " << m1.size() + << "\n\t m2.size(): " << m2.size() + ); + + return trans(m1)*m2; + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_removerc + { + op_removerc( const M& m_) : m(m_){} + + const M& m; + + const static long cost = M::cost+2; + const static long NR = (M::NR==0) ? 0 : (M::NR - 1); + const static long NC = (M::NC==0) ? 0 : (M::NC - 1); + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply (long r, long c) const + { + if (r < R) + { + if (c < C) + return m(r,c); + else + return m(r,c+1); + } + else + { + if (c < C) + return m(r+1,c); + else + return m(r+1,c+1); + } + } + + long nr () const { return m.nr() - 1; } + long nc () const { return m.nc() - 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template + struct op_removerc2 + { + op_removerc2( const M& m_, const long R_, const long C_) : m(m_), R(R_), C(C_){} + const M& m; + const long R; + const long C; + + const static long cost = M::cost+2; + const static long NR = (M::NR==0) ? 0 : (M::NR - 1); + const static long NC = (M::NC==0) ? 0 : (M::NC - 1); + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply (long r, long c) const + { + if (r < R) + { + if (c < C) + return m(r,c); + else + return m(r,c+1); + } + else + { + if (c < C) + return m(r+1,c); + else + return m(r+1,c+1); + } + } + + long nr () const { return m.nr() - 1; } + long nc () const { return m.nc() - 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + long R, + long C, + typename EXP + > + const matrix_op > removerc ( + const matrix_exp& m + ) + { + // you can't remove a row from a matrix with only one row + COMPILE_TIME_ASSERT((EXP::NR > R && R >= 0) || EXP::NR == 0); + // you can't remove a column from a matrix with only one column + COMPILE_TIME_ASSERT((EXP::NC > C && C >= 0) || EXP::NR == 0); + DLIB_ASSERT(m.nr() > R && R >= 0 && m.nc() > C && C >= 0, + "\tconst matrix_exp removerc(const matrix_exp& m)" + << "\n\tYou can't remove a row/column from a matrix if it doesn't have that row/column" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tR: " << R + << "\n\tC: " << C + ); + typedef op_removerc op; + return matrix_op(op(m.ref())); + } + + template < + typename EXP + > + const matrix_op > removerc ( + const matrix_exp& m, + long R, + long C + ) + { + DLIB_ASSERT(m.nr() > R && R >= 0 && m.nc() > C && C >= 0, + "\tconst matrix_exp removerc(const matrix_exp& m,R,C)" + << "\n\tYou can't remove a row/column from a matrix if it doesn't have that row/column" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tR: " << R + << "\n\tC: " << C + ); + typedef op_removerc2 op; + return matrix_op(op(m.ref(),R,C)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_remove_col + { + op_remove_col( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost+2; + const static long NR = M::NR; + const static long NC = (M::NC==0) ? 0 : (M::NC - 1); + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (c < C) + { + return m(r,c); + } + else + { + return m(r,c+1); + } + } + + long nr () const { return m.nr(); } + long nc () const { return m.nc() - 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template + struct op_remove_col2 + { + op_remove_col2( const M& m_, const long C_) : m(m_), C(C_){} + const M& m; + const long C; + + const static long cost = M::cost+2; + const static long NR = M::NR; + const static long NC = (M::NC==0) ? 0 : (M::NC - 1); + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (c < C) + { + return m(r,c); + } + else + { + return m(r,c+1); + } + } + + long nr () const { return m.nr(); } + long nc () const { return m.nc() - 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + long C, + typename EXP + > + const matrix_op > remove_col ( + const matrix_exp& m + ) + { + // You can't remove the given column from the matrix because the matrix doesn't + // have a column with that index. + COMPILE_TIME_ASSERT((EXP::NC > C && C >= 0) || EXP::NC == 0); + DLIB_ASSERT(m.nc() > C && C >= 0 , + "\tconst matrix_exp remove_col(const matrix_exp& m)" + << "\n\tYou can't remove a col from a matrix if it doesn't have it" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tC: " << C + ); + typedef op_remove_col op; + return matrix_op(op(m.ref())); + } + + template < + typename EXP + > + const matrix_op > remove_col ( + const matrix_exp& m, + long C + ) + { + DLIB_ASSERT(m.nc() > C && C >= 0 , + "\tconst matrix_exp remove_col(const matrix_exp& m,C)" + << "\n\tYou can't remove a col from a matrix if it doesn't have it" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tC: " << C + ); + typedef op_remove_col2 op; + return matrix_op(op(m.ref(),C)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_remove_row + { + op_remove_row( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost+2; + const static long NR = (M::NR==0) ? 0 : (M::NR - 1); + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (r < R) + { + return m(r,c); + } + else + { + return m(r+1,c); + } + } + + long nr () const { return m.nr() - 1; } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template + struct op_remove_row2 + { + op_remove_row2( const M& m_, const long R_) : m(m_), R(R_){} + const M& m; + const long R; + + const static long cost = M::cost+2; + const static long NR = (M::NR==0) ? 0 : (M::NR - 1); + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (r < R) + { + return m(r,c); + } + else + { + return m(r+1,c); + } + } + + long nr () const { return m.nr() - 1; } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + long R, + typename EXP + > + const matrix_op > remove_row ( + const matrix_exp& m + ) + { + // You can't remove the given row from the matrix because the matrix doesn't + // have a row with that index. + COMPILE_TIME_ASSERT((EXP::NR > R && R >= 0) || EXP::NR == 0); + DLIB_ASSERT(m.nr() > R && R >= 0, + "\tconst matrix_exp remove_row(const matrix_exp& m)" + << "\n\tYou can't remove a row from a matrix if it doesn't have it" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tR: " << R + ); + typedef op_remove_row op; + return matrix_op(op(m.ref())); + } + + template < + typename EXP + > + const matrix_op > remove_row ( + const matrix_exp& m, + long R + ) + { + DLIB_ASSERT(m.nr() > R && R >= 0, + "\tconst matrix_exp remove_row(const matrix_exp& m, long R)" + << "\n\tYou can't remove a row from a matrix if it doesn't have it" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tR: " << R + ); + typedef op_remove_row2 op; + return matrix_op(op(m.ref(),R)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_diagm + { + op_diagm( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost+2; + const static long N = M::NC*M::NR; + const static long NR = N; + const static long NC = N; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (r==c) + return m(r); + else + return 0; + } + + long nr () const { return (m.nr()>m.nc())? m.nr():m.nc(); } + long nc () const { return (m.nr()>m.nc())? m.nr():m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_diag_op > diagm ( + const matrix_exp& m + ) + { + // You can only make a diagonal matrix out of a row or column vector + COMPILE_TIME_ASSERT(EXP::NR == 0 || EXP::NR == 1 || EXP::NC == 1 || EXP::NC == 0); + DLIB_ASSERT(is_vector(m), + "\tconst matrix_exp diagm(const matrix_exp& m)" + << "\n\tYou can only apply diagm() to a row or column matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef op_diagm op; + return matrix_diag_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_diagm_mult : basic_op_mm + { + op_diagm_mult( const M1& m1_, const M2& m2_) : basic_op_mm(m1_,m2_){} + + typedef typename M1::type type; + typedef const type const_ret_type; + const static long cost = M1::cost + M2::cost + 1; + + const_ret_type apply ( long r, long c) const + { + if (r == c) + return this->m1(r,c)*this->m2(r,c); + else + return 0; + } + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_diag_op > operator* ( + const matrix_diag_exp& a, + const matrix_diag_exp& b + ) + { + COMPILE_TIME_ASSERT((is_same_type::value)); + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); + DLIB_ASSERT(a.nr() == b.nr() && + a.nc() == b.nc(), + "\tconst matrix_exp operator(const matrix_diag_exp& a, const matrix_diag_exp& b)" + << "\n\tYou can only multiply diagonal matrices together if they are the same size" + << "\n\ta.nr(): " << a.nr() + << "\n\ta.nc(): " << a.nc() + << "\n\tb.nr(): " << b.nr() + << "\n\tb.nc(): " << b.nc() + ); + typedef op_diagm_mult op; + return matrix_diag_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_diag + { + op_diag( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost; + const static long NR = tmin::value; + const static long NC = 1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long ) const { return m(r,r); } + + long nr () const { return std::min(m.nc(),m.nr()); } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > diag ( + const matrix_exp& m + ) + { + typedef op_diag op; + return matrix_op(op(m.ref())); + } + + template + struct diag_exp + { + typedef matrix_op > type; + }; + +// ---------------------------------------------------------------------------------------- + + template + struct op_cast + { + op_cast( const M& m_) : m(m_){} + const M& m; + + const static long cost = M::cost+2; + const static long NR = M::NR; + const static long NC = M::NC; + typedef target_type type; + typedef const target_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const { return static_cast(m(r,c)); } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.destructively_aliases(item); } + }; + + template < + typename target_type, + typename EXP + > + const matrix_op > matrix_cast ( + const matrix_exp& m + ) + { + typedef op_cast op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type lessthan(const type& val, const S& s) + { + if (val < s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_lessthan, impl::lessthan, 1); + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator< ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_lessthan op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator> ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_lessthan op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type lessthan_eq(const type& val, const S& s) + { + if (val <= s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_lessthan_eq, impl::lessthan_eq, 1); + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator<= ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_lessthan_eq op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator>= ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_lessthan_eq op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type greaterthan(const type& val, const S& s) + { + if (val > s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_greaterthan, impl::greaterthan, 1); + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator> ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_greaterthan op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator< ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_greaterthan op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type greaterthan_eq(const type& val, const S& s) + { + if (val >= s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_greaterthan_eq, impl::greaterthan_eq, 1); + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator>= ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_greaterthan_eq op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator<= ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_greaterthan_eq op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type equal_to(const type& val, const S& s) + { + if (val == s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_equal_to, impl::equal_to, 1); + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator== ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT( is_built_in_scalar_type::value); + + typedef op_equal_to op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator== ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT( is_built_in_scalar_type::value); + + typedef op_equal_to op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + inline type not_equal_to(const type& val, const S& s) + { + if (val != s) + return 1; + else + return 0; + } + + } + DLIB_DEFINE_OP_MS(op_not_equal_to, impl::not_equal_to, 1); + + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator!= ( + const matrix_exp& m, + const S& s + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_not_equal_to op; + return matrix_op(op(m.ref(),s)); + } + + template < + typename EXP, + typename S + > + const typename enable_if, matrix_op > >::type operator!= ( + const S& s, + const matrix_exp& m + ) + { + // you can only use this relational operator with the built in scalar types like + // long, float, etc. + COMPILE_TIME_ASSERT(is_built_in_scalar_type::value); + + typedef op_not_equal_to op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename MM, + typename U, + typename L + > + typename disable_if,void>::type set_all_elements ( + matrix& m, + const U& value + ) + { + // The value you are trying to assign to each element of the m matrix + // doesn't have the appropriate type. + COMPILE_TIME_ASSERT(is_matrix::value == is_matrix::value); + + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + m(r,c) = static_cast(value); + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename MM, + typename U, + typename L + > + typename enable_if,void>::type set_all_elements ( + matrix& m, + const U& value + ) + { + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + m(r,c) = value; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + inline const typename matrix_exp::matrix_type tmp ( + const matrix_exp& m + ) + { + return typename matrix_exp::matrix_type (m); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename lazy_disable_if, EXP>::type sum ( + const matrix_exp& m + ) + { + typedef typename matrix_exp::type type; + + type val = 0; + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + val += m(r,c); + } + } + return val; + } + + template < + typename EXP + > + const typename lazy_enable_if, EXP>::type sum ( + const matrix_exp& m + ) + { + typedef typename matrix_exp::type type; + + type val; + if (m.size() > 0) + val.set_size(m(0,0).nr(),m(0,0).nc()); + set_all_elements(val,0); + + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + val += m(r,c); + } + } + return val; + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_sumr + { + op_sumr(const M& m_) : m(m_) {} + const M& m; + + const static long cost = M::cost+10; + const static long NR = 1; + const static long NC = M::NC; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long , long c) const + { + type temp = m(0,c); + for (long r = 1; r < m.nr(); ++r) + temp += m(r,c); + return temp; + } + + long nr () const { return 1; } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > sum_rows ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0 , + "\tconst matrix_exp sum_rows(m)" + << "\n\t The matrix can't be empty" + << "\n\t m.size(): " << m.size() + ); + typedef op_sumr op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_sumc + { + op_sumc(const M& m_) : m(m_) {} + const M& m; + + const static long cost = M::cost + 10; + const static long NR = M::NR; + const static long NC = 1; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long ) const + { + type temp = m(r,0); + for (long c = 1; c < m.nc(); ++c) + temp += m(r,c); + return temp; + } + + long nr () const { return m.nr(); } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > sum_cols ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.size() > 0 , + "\tconst matrix_exp sum_cols(m)" + << "\n\t The matrix can't be empty" + << "\n\t m.size(): " << m.size() + ); + typedef op_sumc op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + inline const typename disable_if, typename matrix_exp::type>::type mean ( + const matrix_exp& m + ) + { + return sum(m)/(m.nr()*m.nc()); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + inline const typename enable_if, typename matrix_exp::type>::type mean ( + const matrix_exp& m + ) + { + typedef typename EXP::type::value_type type; + return sum(m)/(type)(m.nr()*m.nc()); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type variance ( + const matrix_exp& m + ) + { + using std::pow; + using dlib::pow; + const typename matrix_exp::type avg = mean(m); + + typedef typename matrix_exp::type type; + + type val; + val = 0; + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + val += pow(m(r,c) - avg,2); + } + } + + if (m.nr() * m.nc() <= 1) + { + return val; + } + else + { + // Note, for some reason, in gcc 4.1 performing this division using a + // double instead of a long value avoids a segmentation fault. That is, + // using 1.0 instead of 1 does the trick. + return val/(m.nr()*m.nc() - 1.0); + } + } + +// ---------------------------------------------------------------------------------------- + +// this is a workaround for a bug in visual studio 7.1 + template + struct visual_studio_sucks_cov_helper + { + typedef typename EXP::type inner_type; + typedef matrix type; + }; + + template < + typename EXP + > + const typename visual_studio_sucks_cov_helper::type covariance ( + const matrix_exp& m + ) + { + // perform static checks to make sure m is a column vector + COMPILE_TIME_ASSERT(EXP::NR == 0 || EXP::NR > 1); + COMPILE_TIME_ASSERT(EXP::NC == 1 || EXP::NC == 0); + + // perform static checks to make sure the matrices contained in m are column vectors + COMPILE_TIME_ASSERT(EXP::type::NC == 1 || EXP::type::NC == 0 ); + + DLIB_ASSERT(m.size() > 1 && is_col_vector(m), + "\tconst matrix covariance(const matrix_exp& m)" + << "\n\tYou can only apply covariance() to a column matrix" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); +#ifdef ENABLE_ASSERTS + for (long i = 0; i < m.nr(); ++i) + { + DLIB_ASSERT(m(0).size() == m(i).size() && m(i).size() > 0 && is_col_vector(m(i)), + "\tconst matrix covariance(const matrix_exp& m)" + << "\n\tYou can only apply covariance() to a column matrix of column matrices" + << "\n\tm(0).size(): " << m(0).size() + << "\n\tm(i).size(): " << m(i).size() + << "\n\tis_col_vector(m(i)): " << (is_col_vector(m(i)) ? "true" : "false") + << "\n\ti: " << i + ); + } +#endif + + // now perform the actual calculation of the covariance matrix. + typename visual_studio_sucks_cov_helper::type cov(m(0).nr(),m(0).nr()); + set_all_elements(cov,0); + + const matrix avg = mean(m); + + for (long r = 0; r < m.nr(); ++r) + { + cov += (m(r) - avg)*trans(m(r) - avg); + } + + cov *= 1.0 / (m.nr() - 1.0); + return cov; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const typename matrix_exp::type prod ( + const matrix_exp& m + ) + { + typedef typename matrix_exp::type type; + + type val = 1; + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + val *= m(r,c); + } + } + return val; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + struct op_uniform_matrix_3 : does_not_alias + { + op_uniform_matrix_3(const long& rows_, const long& cols_, const T& val_ ) : + rows(rows_), cols(cols_), val(val_) {} + + const long rows; + const long cols; + const T val; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 0; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T& const_ret_type; + const_ret_type apply (long, long ) const { return val; } + + long nr() const { return rows; } + long nc() const { return cols; } + }; + + template < + typename T + > + const matrix_op > uniform_matrix ( + long nr, + long nc, + const T& val + ) + { + DLIB_ASSERT(nr > 0 && nc > 0, + "\tconst matrix_exp uniform_matrix(nr, nc, val)" + << "\n\tnr and nc have to be bigger than 0" + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + typedef op_uniform_matrix_3 op; + return matrix_op(op(nr, nc, val)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_op > zeros_matrix ( + long nr, + long nc + ) + { + DLIB_ASSERT(nr > 0 && nc > 0, + "\tconst matrix_exp zeros_matrix(nr, nc)" + << "\n\tnr and nc have to be bigger than 0" + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + typedef op_uniform_matrix_3 op; + return matrix_op(op(nr, nc, 0)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const matrix_op > zeros_matrix ( + const matrix_exp& mat + ) + { + DLIB_ASSERT(mat.nr() > 0 && mat.nc() > 0, + "\tconst matrix_exp zeros_matrix(mat)" + << "\n\t nr and nc have to be bigger than 0" + << "\n\t mat.nr(): " << mat.nr() + << "\n\t mat.nc(): " << mat.nc() + ); + typedef typename EXP::type T; + typedef op_uniform_matrix_3 op; + return matrix_op(op(mat.nr(), mat.nc(), 0)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_op > ones_matrix ( + long nr, + long nc + ) + { + DLIB_ASSERT(nr > 0 && nc > 0, + "\tconst matrix_exp ones_matrix(nr, nc)" + << "\n\tnr and nc have to be bigger than 0" + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + typedef op_uniform_matrix_3 op; + return matrix_op(op(nr, nc, 1)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP + > + const matrix_op > ones_matrix ( + const matrix_exp& mat + ) + { + DLIB_ASSERT(mat.nr() > 0 && mat.nc() > 0, + "\tconst matrix_exp ones_matrix(mat)" + << "\n\t nr and nc have to be bigger than 0" + << "\n\t mat.nr(): " << mat.nr() + << "\n\t mat.nc(): " << mat.nc() + ); + typedef typename EXP::type T; + typedef op_uniform_matrix_3 op; + return matrix_op(op(mat.nr(), mat.nc(), 1)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR_, + long NC_ + > + struct op_uniform_matrix_2 : does_not_alias + { + op_uniform_matrix_2( const T& val_ ) : val(val_) {} + const T val; + + const static long cost = 1; + const static long NR = NR_; + const static long NC = NC_; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T& const_ret_type; + + const_ret_type apply (long , long ) const { return val; } + + long nr() const { return NR; } + long nc() const { return NC; } + }; + + template < + typename T, + long NR, + long NC + > + const matrix_op > uniform_matrix ( + const T& val + ) + { + COMPILE_TIME_ASSERT(NR > 0 && NC > 0); + + typedef op_uniform_matrix_2 op; + return matrix_op(op(val)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR_, + long NC_, + T val + > + struct op_uniform_matrix : does_not_alias + { + const static long cost = 1; + const static long NR = NR_; + const static long NC = NC_; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T const_ret_type; + const_ret_type apply ( long , long ) const { return val; } + + long nr() const { return NR; } + long nc() const { return NC; } + }; + + template < + typename T, + long NR, + long NC, + T val + > + const matrix_op > uniform_matrix ( + ) + { + COMPILE_TIME_ASSERT(NR > 0 && NC > 0); + typedef op_uniform_matrix op; + return matrix_op(op()); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_add_diag + { + op_add_diag( const M& m_, const typename M::type& value_) : m(m_), value(value_){} + const M& m; + const typename M::type value; + + const static long cost = M::cost+1; + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const + { + if (r==c) + return m(r,c)+value; + else + return m(r,c); + } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.destructively_aliases(item); } + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + struct op_identity_matrix_2 : does_not_alias + { + op_identity_matrix_2(const long& size_) : size(size_) {} + + const long size; + + const static long cost = 1; + const static long NR = 0; + const static long NC = 0; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T const_ret_type; + const_ret_type apply (long r, long c) const { return static_cast(r == c); } + + long nr() const { return size; } + long nc() const { return size; } + }; + + template < + typename T + > + const matrix_diag_op > identity_matrix ( + const long& size + ) + { + DLIB_ASSERT(size > 0, + "\tconst matrix_exp identity_matrix(size)" + << "\n\tsize must be bigger than 0" + << "\n\tsize: " << size + ); + typedef op_identity_matrix_2 op; + return matrix_diag_op(op(size)); + } + + template < + typename EXP + > + const matrix_diag_op > identity_matrix ( + const matrix_exp& mat + ) + { + DLIB_ASSERT(mat.nr() == mat.nc(), + "\tconst matrix_exp identity_matrix(mat)" + << "\n\t mat must be a square matrix." + << "\n\t mat.nr(): " << mat.nr() + << "\n\t mat.nc(): " << mat.nc() + ); + typedef typename EXP::type T; + typedef op_identity_matrix_2 op; + return matrix_diag_op(op(mat.nr())); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + typename T + > + const matrix_op > operator+ ( + const matrix_exp& lhs, + const matrix_exp > >& DLIB_IF_ASSERT(rhs) + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(lhs.ref(),1)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + typename T + > + const matrix_op > operator+ ( + const matrix_exp > >& DLIB_IF_ASSERT(lhs), + const matrix_exp& rhs + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(rhs.ref(),1)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long N + > + struct op_const_diag_matrix : does_not_alias + { + op_const_diag_matrix(const long& size_, const T& value_) : size(size_),value(value_) {} + + const long size; + const T value; + + const static long cost = 1; + const static long NR = N; + const static long NC = N; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T const_ret_type; + const_ret_type apply (long r, long c) const + { + if (r == c) + return value; + else + return 0; + } + + long nr() const { return size; } + long nc() const { return size; } + }; + + template < + typename T, + typename U + > + const typename disable_if, matrix_diag_op > >::type operator* ( + const matrix_exp > >& m, + const U& value + ) + { + typedef op_const_diag_matrix op; + return matrix_diag_op(op(m.nr(), value)); + } + + template < + typename T, + typename U + > + const typename disable_if, matrix_diag_op > >::type operator* ( + const U& value, + const matrix_exp > >& m + ) + { + typedef op_const_diag_matrix op; + return matrix_diag_op(op(m.nr(), value)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + typename T, + long N + > + const matrix_op > operator+ ( + const matrix_exp& lhs, + const matrix_exp > >& rhs + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(lhs.ref(),rhs.ref().op.value)); + } + + template < + typename EXP, + typename T, + long N + > + const matrix_op > operator+ ( + const matrix_exp > >& lhs, + const matrix_exp& rhs + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(rhs.ref(),lhs.ref().op.value)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long N + > + struct op_identity_matrix : does_not_alias + { + const static long cost = 1; + const static long NR = N; + const static long NC = N; + typedef default_memory_manager mem_manager_type; + typedef row_major_layout layout_type; + typedef T type; + typedef const T const_ret_type; + const_ret_type apply ( long r, long c) const { return static_cast(r == c); } + + long nr () const { return NR; } + long nc () const { return NC; } + }; + + template < + typename T, + long N + > + const matrix_diag_op > identity_matrix ( + ) + { + COMPILE_TIME_ASSERT(N > 0); + + typedef op_identity_matrix op; + return matrix_diag_op(op()); + } + + template < + typename T, + typename U, + long N + > + const typename disable_if, matrix_diag_op > >::type operator* ( + const matrix_exp > >& m, + const U& value + ) + { + typedef op_const_diag_matrix op; + return matrix_diag_op(op(m.nr(), value)); + } + + template < + typename T, + typename U, + long N + > + const typename disable_if, matrix_diag_op > >::type operator* ( + const U& value, + const matrix_exp > >& m + ) + { + typedef op_const_diag_matrix op; + return matrix_diag_op(op(m.nr(), value)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + typename T, + long N + > + const matrix_op > operator+ ( + const matrix_exp > >& DLIB_IF_ASSERT(lhs), + const matrix_exp& rhs + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(rhs.ref(),1)); + } + + template < + typename EXP, + typename T, + long N + > + const matrix_op > operator+ ( + const matrix_exp& lhs, + const matrix_exp > >& DLIB_IF_ASSERT(rhs) + ) + { + // both matrices must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // You can only add matrices together if they both have the same number of rows and columns. + DLIB_ASSERT(lhs.nc() == rhs.nc() && + lhs.nr() == rhs.nr(), + "\tconst matrix_exp operator+(const matrix_exp& lhs, const matrix_exp& rhs)" + << "\n\tYou are trying to add two incompatible matrices together" + << "\n\tlhs.nr(): " << lhs.nr() + << "\n\tlhs.nc(): " << lhs.nc() + << "\n\trhs.nr(): " << rhs.nr() + << "\n\trhs.nc(): " << rhs.nc() + << "\n\t&lhs: " << &lhs + << "\n\t&rhs: " << &rhs + ); + + + typedef op_add_diag op; + return matrix_op(op(lhs.ref(),1)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_rotate + { + op_rotate(const M& m_) : m(m_) {} + const M& m; + + const static long cost = M::cost + 2; + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + const_ret_type apply ( long r, long c) const { return m((r+R)%m.nr(),(c+C)%m.nc()); } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + long R, + long C, + typename EXP + > + const matrix_op > rotate ( + const matrix_exp& m + ) + { + typedef op_rotate op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + // A template to tell me if two types can be multiplied together in a sensible way. Here + // I'm saying it is ok if they are both the same type or one is the complex version of the other. + template struct compatible { static const bool value = false; typedef T type; }; + template struct compatible { static const bool value = true; typedef T type; }; + template struct compatible,T> { static const bool value = true; typedef std::complex type; }; + template struct compatible > { static const bool value = true; typedef std::complex type; }; + } + + + template + struct op_pointwise_multiply : basic_op_mm + { + op_pointwise_multiply( const M1& m1_, const M2& m2_) : basic_op_mm(m1_,m2_){} + + typedef typename impl::compatible::type type; + typedef const type const_ret_type; + const static long cost = M1::cost + M2::cost + 1; + + const_ret_type apply ( long r, long c) const + { return this->m1(r,c)*this->m2(r,c); } + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_op > pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b + ) + { + COMPILE_TIME_ASSERT((impl::compatible::value == true)); + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0); + DLIB_ASSERT(a.nr() == b.nr() && + a.nc() == b.nc(), + "\tconst matrix_exp pointwise_multiply(const matrix_exp& a, const matrix_exp& b)" + << "\n\tYou can only make a do a pointwise multiply with two equally sized matrices" + << "\n\ta.nr(): " << a.nr() + << "\n\ta.nc(): " << a.nc() + << "\n\tb.nr(): " << b.nr() + << "\n\tb.nc(): " << b.nc() + ); + typedef op_pointwise_multiply op; + return matrix_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_pointwise_multiply3 : basic_op_mmm + { + op_pointwise_multiply3( const M1& m1_, const M2& m2_, const M3& m3_) : + basic_op_mmm(m1_,m2_,m3_){} + + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + const static long cost = M1::cost + M2::cost + M3::cost + 2; + + const_ret_type apply (long r, long c) const + { return this->m1(r,c)*this->m2(r,c)*this->m3(r,c); } + }; + + template < + typename EXP1, + typename EXP2, + typename EXP3 + > + inline const matrix_op > + pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp& c + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NR == 0 || EXP2::NC == 0); + COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); + COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); + DLIB_ASSERT(a.nr() == b.nr() && + a.nc() == b.nc() && + b.nr() == c.nr() && + b.nc() == c.nc(), + "\tconst matrix_exp pointwise_multiply(a,b,c)" + << "\n\tYou can only make a do a pointwise multiply between equally sized matrices" + << "\n\ta.nr(): " << a.nr() + << "\n\ta.nc(): " << a.nc() + << "\n\tb.nr(): " << b.nr() + << "\n\tb.nc(): " << b.nc() + << "\n\tc.nr(): " << c.nr() + << "\n\tc.nc(): " << c.nc() + ); + + typedef op_pointwise_multiply3 op; + return matrix_op(op(a.ref(),b.ref(),c.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_pointwise_multiply4 : basic_op_mmmm + { + op_pointwise_multiply4( const M1& m1_, const M2& m2_, const M3& m3_, const M4& m4_) : + basic_op_mmmm(m1_,m2_,m3_,m4_){} + + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + const static long cost = M1::cost + M2::cost + M3::cost + M4::cost + 3; + + const_ret_type apply (long r, long c) const + { return this->m1(r,c)*this->m2(r,c)*this->m3(r,c)*this->m4(r,c); } + }; + + + template < + typename EXP1, + typename EXP2, + typename EXP3, + typename EXP4 + > + inline const matrix_op > pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp& c, + const matrix_exp& d + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT((is_same_type::value == true)); + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || EXP1::NR == 0 || EXP2::NR == 0); + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || EXP1::NC == 0 || EXP2::NC == 0 ); + COMPILE_TIME_ASSERT(EXP2::NR == EXP3::NR || EXP2::NR == 0 || EXP3::NR == 0); + COMPILE_TIME_ASSERT(EXP2::NC == EXP3::NC || EXP2::NC == 0 || EXP3::NC == 0); + COMPILE_TIME_ASSERT(EXP3::NR == EXP4::NR || EXP3::NR == 0 || EXP4::NR == 0); + COMPILE_TIME_ASSERT(EXP3::NC == EXP4::NC || EXP3::NC == 0 || EXP4::NC == 0); + DLIB_ASSERT(a.nr() == b.nr() && + a.nc() == b.nc() && + b.nr() == c.nr() && + b.nc() == c.nc() && + c.nr() == d.nr() && + c.nc() == d.nc(), + "\tconst matrix_exp pointwise_multiply(a,b,c,d)" + << "\n\tYou can only make a do a pointwise multiply between equally sized matrices" + << "\n\ta.nr(): " << a.nr() + << "\n\ta.nc(): " << a.nc() + << "\n\tb.nr(): " << b.nr() + << "\n\tb.nc(): " << b.nc() + << "\n\tc.nr(): " << c.nr() + << "\n\tc.nc(): " << c.nc() + << "\n\td.nr(): " << d.nr() + << "\n\td.nc(): " << d.nc() + ); + + typedef op_pointwise_multiply4 op; + return matrix_op(op(a.ref(),b.ref(),c.ref(),d.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename P, + int type = static_switch< + pixel_traits

::grayscale, + pixel_traits

::rgb, + pixel_traits

::hsi, + pixel_traits

::rgb_alpha + >::value + > + struct pixel_to_vector_helper; + + template + struct pixel_to_vector_helper + { + template + static void assign ( + M& m, + const P& pixel + ) + { + m(0) = static_cast(pixel); + } + }; + + template + struct pixel_to_vector_helper + { + template + static void assign ( + M& m, + const P& pixel + ) + { + m(0) = static_cast(pixel.red); + m(1) = static_cast(pixel.green); + m(2) = static_cast(pixel.blue); + } + }; + + template + struct pixel_to_vector_helper + { + template + static void assign ( + M& m, + const P& pixel + ) + { + m(0) = static_cast(pixel.h); + m(1) = static_cast(pixel.s); + m(2) = static_cast(pixel.i); + } + }; + + template + struct pixel_to_vector_helper + { + template + static void assign ( + M& m, + const P& pixel + ) + { + m(0) = static_cast(pixel.red); + m(1) = static_cast(pixel.green); + m(2) = static_cast(pixel.blue); + m(3) = static_cast(pixel.alpha); + } + }; + + + template < + typename T, + typename P + > + inline const matrix::num,1> pixel_to_vector ( + const P& pixel + ) + { + COMPILE_TIME_ASSERT(pixel_traits

::num > 0); + matrix::num,1> m; + pixel_to_vector_helper

::assign(m,pixel); + return m; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename P, + int type = static_switch< + pixel_traits

::grayscale, + pixel_traits

::rgb, + pixel_traits

::hsi, + pixel_traits

::rgb_alpha + >::value + > + struct vector_to_pixel_helper; + + template + struct vector_to_pixel_helper + { + template + static void assign ( + P& pixel, + const M& m + ) + { + pixel = static_cast(m(0)); + } + }; + + template + struct vector_to_pixel_helper + { + template + static void assign ( + P& pixel, + const M& m + ) + { + pixel.red = static_cast(m(0)); + pixel.green = static_cast(m(1)); + pixel.blue = static_cast(m(2)); + } + }; + + template + struct vector_to_pixel_helper + { + template + static void assign ( + P& pixel, + const M& m + ) + { + pixel.h = static_cast(m(0)); + pixel.s = static_cast(m(1)); + pixel.i = static_cast(m(2)); + } + }; + + template + struct vector_to_pixel_helper + { + template + static void assign ( + P& pixel, + const M& m + ) + { + pixel.red = static_cast(m(0)); + pixel.green = static_cast(m(1)); + pixel.blue = static_cast(m(2)); + pixel.alpha = static_cast(m(3)); + } + }; + + template < + typename P, + typename EXP + > + inline void vector_to_pixel ( + P& pixel, + const matrix_exp& vector + ) + { + COMPILE_TIME_ASSERT(pixel_traits

::num == matrix_exp::NR); + COMPILE_TIME_ASSERT(matrix_exp::NC == 1); + vector_to_pixel_helper

::assign(pixel,vector); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_clamp : basic_op_m + { + op_clamp( const M& m_) : basic_op_m(m_){} + + typedef typename M::type type; + typedef const typename M::type const_ret_type; + const static long cost = M::cost + 2; + + const_ret_type apply ( long r, long c) const + { + const type temp = this->m(r,c); + if (temp > static_cast(upper)) + return static_cast(upper); + else if (temp < static_cast(lower)) + return static_cast(lower); + else + return temp; + } + }; + + template < + long l, + long u, + typename EXP + > + const matrix_op > clamp ( + const matrix_exp& m + ) + { + typedef op_clamp op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_clamp2 : basic_op_m + { + typedef typename M::type type; + + op_clamp2( const M& m_, const type& l, const type& u) : + basic_op_m(m_), lower(l), upper(u){} + + const type& lower; + const type& upper; + + typedef const typename M::type const_ret_type; + const static long cost = M::cost + 2; + + const_ret_type apply ( long r, long c) const + { + const type temp = this->m(r,c); + if (temp > upper) + return upper; + else if (temp < lower) + return lower; + else + return temp; + } + }; + + template < + typename EXP + > + const matrix_op > clamp ( + const matrix_exp& m, + const typename EXP::type& lower, + const typename EXP::type& upper + ) + { + typedef op_clamp2 op; + return matrix_op(op(m.ref(),lower, upper)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_reshape + { + op_reshape(const M& m_, const long& rows_, const long& cols_) : m(m_),rows(rows_),cols(cols_) {} + const M& m; + const long rows; + const long cols; + + const static long cost = M::cost+2; + const static long NR = 0; + const static long NC = 0; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply ( long r, long c) const + { + const long idx = r*cols + c; + return m(idx/m.nc(), idx%m.nc()); + } + + long nr () const { return rows; } + long nc () const { return cols; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > reshape ( + const matrix_exp& m, + const long& rows, + const long& cols + ) + { + DLIB_ASSERT(m.size() == rows*cols && rows > 0 && cols > 0, + "\tconst matrix_exp reshape(m, rows, cols)" + << "\n\t The size of m must match the dimensions you want to reshape it into." + << "\n\t m.size(): " << m.size() + << "\n\t rows*cols: " << rows*cols + << "\n\t rows: " << rows + << "\n\t cols: " << cols + ); + + typedef op_reshape op; + return matrix_op(op(m.ref(), rows, cols)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP1, + typename EXP2 + > + typename disable_if,bool>::type equal ( + const matrix_exp& a, + const matrix_exp& b, + const typename EXP1::type eps = 100*std::numeric_limits::epsilon() + ) + { + // check if the dimensions don't match + if (a.nr() != b.nr() || a.nc() != b.nc()) + return false; + + for (long r = 0; r < a.nr(); ++r) + { + for (long c = 0; c < a.nc(); ++c) + { + if (std::abs(a(r,c)-b(r,c)) > eps) + return false; + } + } + + // no non-equal points found so we return true + return true; + } + + template < + typename EXP1, + typename EXP2 + > + typename enable_if,bool>::type equal ( + const matrix_exp& a, + const matrix_exp& b, + const typename EXP1::type::value_type eps = 100*std::numeric_limits::epsilon() + ) + { + // check if the dimensions don't match + if (a.nr() != b.nr() || a.nc() != b.nc()) + return false; + + for (long r = 0; r < a.nr(); ++r) + { + for (long c = 0; c < a.nc(); ++c) + { + if (std::abs(real(a(r,c)-b(r,c))) > eps || + std::abs(imag(a(r,c)-b(r,c))) > eps) + return false; + } + } + + // no non-equal points found so we return true + return true; + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_scale_columns + { + op_scale_columns(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost + M2::cost + 1; + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR; + const static long NC = M1::NC; + + const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c); } + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) ; } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > scale_columns ( + const matrix_exp& m, + const matrix_exp& v + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + // The v argument must be a row or column vector. + COMPILE_TIME_ASSERT((EXP2::NC == 1 || EXP2::NC == 0) || (EXP2::NR == 1 || EXP2::NR == 0)); + + // figure out the compile time known length of v + const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax::value); + + // the length of v must match the number of columns in m + COMPILE_TIME_ASSERT(EXP1::NC == v_len || EXP1::NC == 0 || v_len == 0); + + DLIB_ASSERT(is_vector(v) == true && v.size() == m.nc(), + "\tconst matrix_exp scale_columns(m, v)" + << "\n\tv must be a row or column vector and its length must match the number of columns in m" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tv.nr(): " << v.nr() + << "\n\tv.nc(): " << v.nc() + ); + typedef op_scale_columns op; + return matrix_op(op(m.ref(),v.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_scale_columns_diag + { + op_scale_columns_diag(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost + M2::cost + 1; + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR; + const static long NC = M1::NC; + + const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(c,c); } + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) ; } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.aliases(item); } + }; + +// turn expressions of the form mat*diagonal_matrix into scale_columns(mat, d) + template < + typename EXP1, + typename EXP2 + > + const matrix_op > operator* ( + const matrix_exp& m, + const matrix_diag_exp& d + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // figure out the compile time known length of d + const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax::value); + + // the length of d must match the number of columns in m + COMPILE_TIME_ASSERT(EXP1::NC == v_len || EXP1::NC == 0 || v_len == 0); + + DLIB_ASSERT(m.nc() == d.nr(), + "\tconst matrix_exp operator*(m, d)" + << "\n\tmatrix dimensions don't match" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\td.nr(): " << d.nr() + << "\n\td.nc(): " << d.nc() + ); + typedef op_scale_columns_diag op; + return matrix_op(op(m.ref(),d.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_scale_rows + { + op_scale_rows(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost + M2::cost + 1; + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR; + const static long NC = M1::NC; + + const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(r); } + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) ; } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > scale_rows ( + const matrix_exp& m, + const matrix_exp& v + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + // The v argument must be a row or column vector. + COMPILE_TIME_ASSERT((EXP2::NC == 1 || EXP2::NC == 0) || (EXP2::NR == 1 || EXP2::NR == 0)); + + // figure out the compile time known length of v + const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax::value); + + // the length of v must match the number of rows in m + COMPILE_TIME_ASSERT(EXP1::NR == v_len || EXP1::NR == 0 || v_len == 0); + + DLIB_ASSERT(is_vector(v) == true && v.size() == m.nr(), + "\tconst matrix_exp scale_rows(m, v)" + << "\n\tv must be a row or column vector and its length must match the number of rows in m" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tv.nr(): " << v.nr() + << "\n\tv.nc(): " << v.nc() + ); + typedef op_scale_rows op; + return matrix_op(op(m.ref(),v.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_scale_rows_diag + { + op_scale_rows_diag(const M1& m1_, const M2& m2_) : m1(m1_), m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost + M2::cost + 1; + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR; + const static long NC = M1::NC; + + const_ret_type apply ( long r, long c) const { return m1(r,c)*m2(r,r); } + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) ; } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.destructively_aliases(item) || m2.aliases(item); } + }; + +// turn expressions of the form diagonal_matrix*mat into scale_rows(mat, d) + template < + typename EXP1, + typename EXP2 + > + const matrix_op > operator* ( + const matrix_diag_exp& d, + const matrix_exp& m + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // figure out the compile time known length of d + const long v_len = ((EXP2::NR)*(EXP2::NC) == 0)? 0 : (tmax::value); + + // the length of d must match the number of rows in m + COMPILE_TIME_ASSERT(EXP1::NR == v_len || EXP1::NR == 0 || v_len == 0); + + DLIB_ASSERT(d.nc() == m.nr(), + "\tconst matrix_exp operator*(d, m)" + << "\n\tThe dimensions of the d and m matrices don't match." + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\td.nr(): " << d.nr() + << "\n\td.nc(): " << d.nc() + ); + typedef op_scale_rows_diag op; + return matrix_op(op(m.ref(),d.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + /* + The idea here is to catch expressions of the form d*M*d where d is diagonal and M + is some square matrix and turn them into something equivalent to + pointwise_multiply(diag(d)*trans(diag(d)), M). + + The reason for this is that doing it this way is more numerically stable. In particular, + doing 2 matrix multiplies as suggested by d*M*d could result in an asymmetric matrix even + if M is symmetric to begin with. + */ + + template + struct op_diag_m_diag + { + // This operator represents M1*M2*M3 where M1 and M3 are diagonal + + op_diag_m_diag(const M1& m1_, const M2& m2_, const M3& m3_) : m1(m1_), m2(m2_), m3(m3_) {} + const M1& m1; + const M2& m2; + const M3& m3; + + const static long cost = M1::cost + M2::cost + M3::cost + 1; + typedef typename M2::type type; + typedef const typename M2::type const_ret_type; + typedef typename M2::mem_manager_type mem_manager_type; + typedef typename M2::layout_type layout_type; + const static long NR = M2::NR; + const static long NC = M2::NC; + + const_ret_type apply ( long r, long c) const { return (m1(r,r)*m3(c,c))*m2(r,c); } + + long nr () const { return m2.nr(); } + long nc () const { return m2.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item) || m3.aliases(item) ; } + template bool destructively_aliases ( const matrix_exp& item) const + { return m2.destructively_aliases(item) || m1.aliases(item) || m3.aliases(item) ; } + }; + + // catch d*(M*d) = EXP1*EXP2*EXP3 + template < + typename EXP1, + typename EXP2, + typename EXP3 + > + const matrix_op > operator* ( + const matrix_diag_exp& d, + const matrix_exp > >& m + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // figure out the compile time known length of d + const long v_len = ((EXP1::NR)*(EXP1::NC) == 0)? 0 : (tmax::value); + + // the length of d must match the number of rows in m + COMPILE_TIME_ASSERT(EXP2::NR == v_len || EXP2::NR == 0 || v_len == 0); + + DLIB_ASSERT(d.nc() == m.nr(), + "\tconst matrix_exp operator*(d, m)" + << "\n\tmatrix dimensions don't match" + << "\n\td.nr(): " << d.nr() + << "\n\td.nc(): " << d.nc() + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + ); + typedef op_diag_m_diag op; + return matrix_op(op(d.ref(), m.ref().op.m1, m.ref().op.m2)); + } + + // catch (d*M)*d = EXP1*EXP2*EXP3 + template < + typename EXP1, + typename EXP2, + typename EXP3 + > + const matrix_op > operator* ( + const matrix_exp > >& m, + const matrix_diag_exp& d + ) + { + // Both arguments to this function must contain the same type of element + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + // figure out the compile time known length of d + const long v_len = ((EXP3::NR)*(EXP3::NC) == 0)? 0 : (tmax::value); + + // the length of d must match the number of columns in m + COMPILE_TIME_ASSERT(EXP2::NC == v_len || EXP2::NC == 0 || v_len == 0); + + DLIB_ASSERT(m.nc() == d.nr(), + "\tconst matrix_exp operator*(m, d)" + << "\n\tmatrix dimensions don't match" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\td.nr(): " << d.nr() + << "\n\td.nc(): " << d.nc() + ); + typedef op_diag_m_diag op; + return matrix_op(op(m.ref().op.m2, m.ref().op.m1, d.ref())); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + struct sort_columns_sort_helper + { + template + bool operator() ( + const T& item1, + const T& item2 + ) const + { + return item1.first < item2.first; + } + }; + + template < + typename T, long NR, long NC, typename mm, typename l1, + long NR2, long NC2, typename mm2, typename l2 + > + void sort_columns ( + matrix& m, + matrix& v + ) + { + COMPILE_TIME_ASSERT(NC2 == 1 || NC2 == 0); + COMPILE_TIME_ASSERT(NC == NR2 || NC == 0 || NR2 == 0); + + DLIB_ASSERT(is_col_vector(v) == true && v.size() == m.nc(), + "\tconst matrix_exp sort_columns(m, v)" + << "\n\tv must be a column vector and its length must match the number of columns in m" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tv.nr(): " << v.nr() + << "\n\tv.nc(): " << v.nc() + ); + + + + // Now we have to sort the given vectors in the m matrix according + // to how big their corresponding v(column index) values are. + typedef std::pair > col_pair; + typedef std_allocator alloc; + std::vector colvalues; + col_pair p; + for (long r = 0; r < v.nr(); ++r) + { + p.first = v(r); + p.second = colm(m,r); + colvalues.push_back(p); + } + std::sort(colvalues.begin(), colvalues.end(), sort_columns_sort_helper()); + + for (long i = 0; i < v.nr(); ++i) + { + v(i) = colvalues[i].first; + set_colm(m,i) = colvalues[i].second; + } + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, long NR, long NC, typename mm, typename l1, + long NR2, long NC2, typename mm2, typename l2 + > + void rsort_columns ( + matrix& m, + matrix& v + ) + { + COMPILE_TIME_ASSERT(NC2 == 1 || NC2 == 0); + COMPILE_TIME_ASSERT(NC == NR2 || NC == 0 || NR2 == 0); + + DLIB_ASSERT(is_col_vector(v) == true && v.size() == m.nc(), + "\tconst matrix_exp rsort_columns(m, v)" + << "\n\tv must be a column vector and its length must match the number of columns in m" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tv.nr(): " << v.nr() + << "\n\tv.nc(): " << v.nc() + ); + + + + // Now we have to sort the given vectors in the m matrix according + // to how big their corresponding v(column index) values are. + typedef std::pair > col_pair; + typedef std_allocator alloc; + std::vector colvalues; + col_pair p; + for (long r = 0; r < v.nr(); ++r) + { + p.first = v(r); + p.second = colm(m,r); + colvalues.push_back(p); + } + std::sort(colvalues.rbegin(), colvalues.rend(), sort_columns_sort_helper()); + + for (long i = 0; i < v.nr(); ++i) + { + v(i) = colvalues[i].first; + set_colm(m,i) = colvalues[i].second; + } + + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_tensor_product + { + op_tensor_product(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost + M2::cost + 1; + const static long NR = M1::NR*M2::NR; + const static long NC = M1::NC*M2::NC; + typedef typename M1::type type; + typedef const typename M1::type const_ret_type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply ( long r, long c) const + { + return m1(r/m2.nr(),c/m2.nc())*m2(r%m2.nr(),c%m2.nc()); + } + + long nr () const { return m1.nr()*m2.nr(); } + long nc () const { return m1.nc()*m2.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_op > tensor_product ( + const matrix_exp& a, + const matrix_exp& b + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + typedef op_tensor_product op; + return matrix_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_make_symmetric : basic_op_m + { + op_make_symmetric ( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + const_ret_type apply ( long r, long c) const + { + if (r >= c) + return this->m(r,c); + else + return this->m(c,r); + } + }; + + template < + typename EXP + > + const matrix_op > make_symmetric ( + const matrix_exp& m + ) + { + DLIB_ASSERT(m.nr() == m.nc(), + "\tconst matrix make_symmetric(m)" + << "\n\t m must be a square matrix" + << "\n\t m.nr(): " << m.nr() + << "\n\t m.nc(): " << m.nc() + ); + + typedef op_make_symmetric op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_lowerm : basic_op_m + { + op_lowerm( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+2; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + const_ret_type apply ( long r, long c) const + { + if (r >= c) + return this->m(r,c); + else + return 0; + } + }; + + template + struct op_lowerm_s : basic_op_m + { + typedef typename M::type type; + op_lowerm_s( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+2; + typedef const typename M::type const_ret_type; + const_ret_type apply ( long r, long c) const + { + if (r > c) + return this->m(r,c); + else if (r==c) + return s; + else + return 0; + } + }; + + template < + typename EXP + > + const matrix_op > lowerm ( + const matrix_exp& m + ) + { + typedef op_lowerm op; + return matrix_op(op(m.ref())); + } + + template < + typename EXP + > + const matrix_op > lowerm ( + const matrix_exp& m, + typename EXP::type s + ) + { + typedef op_lowerm_s op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_upperm : basic_op_m + { + op_upperm( const M& m_) : basic_op_m(m_){} + + const static long cost = M::cost+2; + typedef typename M::type type; + typedef const typename M::type const_ret_type; + const_ret_type apply ( long r, long c) const + { + if (r <= c) + return this->m(r,c); + else + return 0; + } + }; + + template + struct op_upperm_s : basic_op_m + { + typedef typename M::type type; + op_upperm_s( const M& m_, const type& s_) : basic_op_m(m_), s(s_){} + + const type s; + + const static long cost = M::cost+2; + typedef const typename M::type const_ret_type; + const_ret_type apply ( long r, long c) const + { + if (r < c) + return this->m(r,c); + else if (r==c) + return s; + else + return 0; + } + }; + + template < + typename EXP + > + const matrix_op > upperm ( + const matrix_exp& m + ) + { + typedef op_upperm op; + return matrix_op(op(m.ref())); + } + + template < + typename EXP + > + const matrix_op > upperm ( + const matrix_exp& m, + typename EXP::type s + ) + { + typedef op_upperm_s op; + return matrix_op(op(m.ref(),s)); + } + +// ---------------------------------------------------------------------------------------- + + template + inline const matrix randm( + long nr, + long nc, + rand_gen& rnd + ) + { + DLIB_ASSERT(nr >= 0 && nc >= 0, + "\tconst matrix randm(nr, nc, rnd)" + << "\n\tInvalid inputs to this function" + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + + matrix m(nr,nc); + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + m(r,c) = rnd.get_random_double(); + } + } + + return m; + } + +// ---------------------------------------------------------------------------------------- + + inline const matrix randm( + long nr, + long nc + ) + { + DLIB_ASSERT(nr >= 0 && nc >= 0, + "\tconst matrix randm(nr, nc)" + << "\n\tInvalid inputs to this function" + << "\n\tnr: " << nr + << "\n\tnc: " << nc + ); + + matrix m(nr,nc); + // make a double that contains RAND_MAX + the smallest number that still + // makes the resulting double slightly bigger than static_cast(RAND_MAX) + double max_val = RAND_MAX; + max_val += std::numeric_limits::epsilon()*RAND_MAX; + + for (long r = 0; r < m.nr(); ++r) + { + for (long c = 0; c < m.nc(); ++c) + { + m(r,c) = std::rand()/max_val; + } + } + + return m; + } + +// ---------------------------------------------------------------------------------------- + + inline const matrix_range_exp linspace ( + double start, + double end, + long num + ) + { + DLIB_ASSERT(num >= 0, + "\tconst matrix_exp linspace(start, end, num)" + << "\n\tInvalid inputs to this function" + << "\n\tstart: " << start + << "\n\tend: " << end + << "\n\tnum: " << num + ); + + return matrix_range_exp(start,end,num,false); + } + +// ---------------------------------------------------------------------------------------- + + inline const matrix_log_range_exp logspace ( + double start, + double end, + long num + ) + { + DLIB_ASSERT(num >= 0, + "\tconst matrix_exp logspace(start, end, num)" + << "\n\tInvalid inputs to this function" + << "\n\tstart: " << start + << "\n\tend: " << end + << "\n\tnum: " << num + ); + + return matrix_log_range_exp(start,end,num); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_cart_prod + { + op_cart_prod(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} + const M1& m1; + const M2& m2; + + const static long cost = M1::cost+M2::cost+1; + typedef typename M1::type type; + typedef const typename M1::const_ret_type const_ret_type; + + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + const static long NR = M1::NR+M2::NR; + const static long NC = M1::NC*M2::NC; + + const_ret_type apply ( long r, long c) const + { + if (r < m1.nr()) + return m1(r, c/m2.nc()); + else + return m2(r-m1.nr(), c%m2.nc()); + } + + long nr () const { return m1.nr() + m2.nr(); } + long nc () const { return m1.nc() * m2.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + const matrix_op > cartesian_product ( + const matrix_exp& a, + const matrix_exp& b + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + + typedef op_cart_prod op; + return matrix_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_mat_to_vect + { + op_mat_to_vect(const M& m_) : m(m_) {} + const M& m; + + const static long cost = M::cost+2; + const static long NR = M::NC*M::NR; + const static long NC = 1; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply ( long r, long ) const { return m(r/m.nc(), r%m.nc()); } + + long nr () const { return m.size(); } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP + > + const matrix_op > reshape_to_column_vector ( + const matrix_exp& m + ) + { + typedef op_mat_to_vect op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_join_rows + { + op_join_rows(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} + const M1& m1; + const M2& m2; + + template + struct type_selector; + template + struct type_selector { typedef T type; }; + template + struct type_selector { typedef U type; }; + + // If both const_ret_types are references then we should use them as the const_ret_type type + // but otherwise we should use the normal type. + typedef typename M1::const_ret_type T1; + typedef typename M1::type T2; + typedef typename M2::const_ret_type T3; + typedef typename type_selector::value && is_reference_type::value>::type const_ret_type; + + const static long cost = M1::cost + M2::cost + 1; + const static long NR = tmax::value; + const static long NC = (M1::NC*M2::NC != 0)? (M1::NC+M2::NC) : (0); + typedef typename M1::type type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply (long r, long c) const + { + if (c < m1.nc()) + return m1(r,c); + else + return m2(r,c-m1.nc()); + } + + long nr () const { return m1.nr(); } + long nc () const { return m1.nc()+m2.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_op > join_rows ( + const matrix_exp& a, + const matrix_exp& b + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + // You are getting an error on this line because you are trying to join two matrices that + // don't have the same number of rows + COMPILE_TIME_ASSERT(EXP1::NR == EXP2::NR || (EXP1::NR*EXP2::NR == 0)); + + DLIB_ASSERT(a.nr() == b.nr(), + "\tconst matrix_exp join_rows(const matrix_exp& a, const matrix_exp& b)" + << "\n\tYou can only use join_rows() if both matrices have the same number of rows" + << "\n\ta.nr(): " << a.nr() + << "\n\tb.nr(): " << b.nr() + ); + + typedef op_join_rows op; + return matrix_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_join_cols + { + op_join_cols(const M1& m1_, const M2& m2_) : m1(m1_),m2(m2_) {} + const M1& m1; + const M2& m2; + + template + struct type_selector; + template + struct type_selector { typedef T type; }; + template + struct type_selector { typedef U type; }; + + // If both const_ret_types are references then we should use them as the const_ret_type type + // but otherwise we should use the normal type. + typedef typename M1::const_ret_type T1; + typedef typename M1::type T2; + typedef typename M2::const_ret_type T3; + typedef typename type_selector::value && is_reference_type::value>::type const_ret_type; + + + + const static long cost = M1::cost + M2::cost + 1; + const static long NC = tmax::value; + const static long NR = (M1::NR*M2::NR != 0)? (M1::NR+M2::NR) : (0); + typedef typename M1::type type; + typedef typename M1::mem_manager_type mem_manager_type; + typedef typename M1::layout_type layout_type; + + const_ret_type apply ( long r, long c) const + { + if (r < m1.nr()) + return m1(r,c); + else + return m2(r-m1.nr(),c); + } + + long nr () const { return m1.nr()+m2.nr(); } + long nc () const { return m1.nc(); } + + template bool aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const + { return m1.aliases(item) || m2.aliases(item); } + }; + + template < + typename EXP1, + typename EXP2 + > + inline const matrix_op > join_cols ( + const matrix_exp& a, + const matrix_exp& b + ) + { + COMPILE_TIME_ASSERT((is_same_type::value == true)); + // You are getting an error on this line because you are trying to join two matrices that + // don't have the same number of columns + COMPILE_TIME_ASSERT(EXP1::NC == EXP2::NC || (EXP1::NC*EXP2::NC == 0)); + + DLIB_ASSERT(a.nc() == b.nc(), + "\tconst matrix_exp join_cols(const matrix_exp& a, const matrix_exp& b)" + << "\n\tYou can only use join_cols() if both matrices have the same number of columns" + << "\n\ta.nc(): " << a.nc() + << "\n\tb.nc(): " << b.nc() + ); + + typedef op_join_cols op; + return matrix_op(op(a.ref(),b.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_fliplr + { + op_fliplr( const M& m_) : m(m_){} + + const M& m; + + const static long cost = M::cost; + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply (long r, long c) const { return m(r,m.nc()-c-1); } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + + }; + + template < + typename M + > + const matrix_op > fliplr ( + const matrix_exp& m + ) + { + typedef op_fliplr op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_flipud + { + op_flipud( const M& m_) : m(m_){} + + const M& m; + + const static long cost = M::cost; + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply (long r, long c) const { return m(m.nr()-r-1,c); } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + + }; + + template < + typename M + > + const matrix_op > flipud ( + const matrix_exp& m + ) + { + typedef op_flipud op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_flip + { + op_flip( const M& m_) : m(m_){} + + const M& m; + + const static long cost = M::cost; + const static long NR = M::NR; + const static long NC = M::NC; + typedef typename M::type type; + typedef typename M::const_ret_type const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + + const_ret_type apply (long r, long c) const { return m(m.nr()-r-1, m.nc()-c-1); } + + long nr () const { return m.nr(); } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + + }; + + template < + typename M + > + const matrix_op > flip ( + const matrix_exp& m + ) + { + typedef op_flip op; + return matrix_op(op(m.ref())); + } + +// ---------------------------------------------------------------------------------------- + + template + uint32 hash ( + const matrix& item, + uint32 seed = 0 + ) + { + DLIB_ASSERT_HAS_STANDARD_LAYOUT(T); + + if (item.size() == 0) + return 0; + else + return murmur_hash3(&item(0,0), sizeof(T)*item.size(), seed); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_UTILITIES_ + diff --git a/libs/dlib/matrix/matrix_utilities_abstract.h b/libs/dlib/matrix/matrix_utilities_abstract.h new file mode 100644 index 0000000..596d6c9 --- /dev/null +++ b/libs/dlib/matrix/matrix_utilities_abstract.h @@ -0,0 +1,1715 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MATRIx_UTILITIES_ABSTRACT_ +#ifdef DLIB_MATRIx_UTILITIES_ABSTRACT_ + +#include "matrix_abstract.h" +#include +#include "../pixel.h" +#include "../geometry.h" +#inclue + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Simple matrix utilities +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp diag ( + const matrix_exp& m + ); + /*! + ensures + - returns a column vector R that contains the elements from the diagonal + of m in the order R(0)==m(0,0), R(1)==m(1,1), R(2)==m(2,2) and so on. + !*/ + + template + struct diag_exp + { + /*! + WHAT THIS OBJECT REPRESENTS + This struct allows you to determine the type of matrix expression + object returned from the diag() function. An example makes its + use clear: + + template + void do_something( const matrix_exp& mat) + { + // d is a matrix expression that aliases mat. + typename diag_exp::type d = diag(mat); + + // Print the diagonal of mat. So we see that by using + // diag_exp we can save the object returned by diag() in + // a local variable. + cout << d << endl; + + // Note that you can only save the return value of diag() to + // a local variable if the argument to diag() has a lifetime + // beyond the diag() expression. The example shown above is + // OK but the following would result in undefined behavior: + typename diag_exp::type bad = diag(mat + mat); + } + !*/ + typedef type_of_expression_returned_by_diag type; + }; + +// ---------------------------------------------------------------------------------------- + + const matrix_exp diagm ( + const matrix_exp& m + ); + /*! + requires + - is_vector(m) == true + (i.e. m is a row or column matrix) + ensures + - returns a square matrix M such that: + - diag(M) == m + - non diagonal elements of M are 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp trans ( + const matrix_exp& m + ); + /*! + ensures + - returns the transpose of the matrix m + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_type::type dot ( + const matrix_exp& m1, + const matrix_exp& m2 + ); + /*! + requires + - is_vector(m1) == true + - is_vector(m2) == true + - m1.size() == m2.size() + ensures + - returns the dot product between m1 and m2. That is, this function + computes and returns the sum, for all i, of m1(i)*m2(i). + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp lowerm ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - M is the lower triangular part of m. That is: + - if (r >= c) then + - M(r,c) == m(r,c) + - else + - M(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp lowerm ( + const matrix_exp& m, + const matrix_exp::type scalar_value + ); + /*! + ensures + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - M is the lower triangular part of m except that the diagonal has + been set to scalar_value. That is: + - if (r > c) then + - M(r,c) == m(r,c) + - else if (r == c) then + - M(r,c) == scalar_value + - else + - M(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp upperm ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - M is the upper triangular part of m. That is: + - if (r <= c) then + - M(r,c) == m(r,c) + - else + - M(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp upperm ( + const matrix_exp& m, + const matrix_exp::type scalar_value + ); + /*! + ensures + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - M is the upper triangular part of m except that the diagonal has + been set to scalar_value. That is: + - if (r < c) then + - M(r,c) == m(r,c) + - else if (r == c) then + - M(r,c) == scalar_value + - else + - M(r,c) == 0 + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp make_symmetric ( + const matrix_exp& m + ); + /*! + requires + - m.nr() == m.nc() + (i.e. m must be a square matrix) + ensures + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - M is a symmetric matrix, that is, M == trans(M) and + it is constructed from the lower triangular part of m. Specifically, + we have: + - lowerm(M) == lowerm(m) + - upperm(M) == trans(lowerm(m)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + T val + > + const matrix_exp uniform_matrix ( + ); + /*! + requires + - NR > 0 && NC > 0 + ensures + - returns an NR by NC matrix with elements of type T and all set to val. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC + > + const matrix_exp uniform_matrix ( + const T& val + ); + /*! + requires + - NR > 0 && NC > 0 + ensures + - returns an NR by NC matrix with elements of type T and all set to val. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp uniform_matrix ( + long nr, + long nc, + const T& val + ); + /*! + requires + - nr > 0 && nc > 0 + ensures + - returns an nr by nc matrix with elements of type T and all set to val. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp ones_matrix ( + const matrix_exp& mat + ); + /*! + requires + - mat.nr() > 0 && mat.nc() > 0 + ensures + - Let T denote the type of element in mat. Then this function + returns uniform_matrix(mat.nr(), mat.nc(), 1) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp ones_matrix ( + long nr, + long nc + ); + /*! + requires + - nr > 0 && nc > 0 + ensures + - returns uniform_matrix(nr, nc, 1) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp zeros_matrix ( + const matrix_exp& mat + ); + /*! + requires + - mat.nr() > 0 && mat.nc() > 0 + ensures + - Let T denote the type of element in mat. Then this function + returns uniform_matrix(mat.nr(), mat.nc(), 0) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp zeros_matrix ( + long nr, + long nc + ); + /*! + requires + - nr > 0 && nc > 0 + ensures + - returns uniform_matrix(nr, nc, 0) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp identity_matrix ( + const matrix_exp& mat + ); + /*! + requires + - mat.nr() == mat.nc() + ensures + - returns an identity matrix with the same dimensions as mat and + containing the same type of elements as mat. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp identity_matrix ( + long N + ); + /*! + requires + - N > 0 + ensures + - returns an N by N identity matrix with elements of type T. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long N + > + const matrix_exp identity_matrix ( + ); + /*! + requires + - N > 0 + ensures + - returns an N by N identity matrix with elements of type T. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp linspace ( + double start, + double end, + long num + ); + /*! + requires + - num >= 0 + ensures + - returns a matrix M such that: + - M::type == double + - is_row_vector(M) == true + - M.size() == num + - M == a row vector with num linearly spaced values beginning with start + and stopping with end. + - M(num-1) == end + - if (num > 1) then + - M(0) == start + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp logspace ( + double start, + double end, + long num + ); + /*! + requires + - num >= 0 + ensures + - returns a matrix M such that: + - M::type == double + - is_row_vector(M) == true + - M.size() == num + - M == a row vector with num logarithmically spaced values beginning with + 10^start and stopping with 10^end. + (i.e. M == pow(10, linspace(start, end, num))) + - M(num-1) == 10^end + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + long R, + long C + > + const matrix_exp rotate ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + R( (r+R)%m.nr() , (c+C)%m.nc() ) == m(r,c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp fliplr ( + const matrix_exp& m + ); + /*! + ensures + - flips the matrix m from left to right and returns the result. + I.e. reverses the order of the columns. + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - for all valid r and c: + M(r,c) == m(r, m.nc()-c-1) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp flipud ( + const matrix_exp& m + ); + /*! + ensures + - flips the matrix m from up to down and returns the result. + I.e. reverses the order of the rows. + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - for all valid r and c: + M(r,c) == m(m.nr()-r-1, c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp flip ( + const matrix_exp& m + ); + /*! + ensures + - flips the matrix m from up to down and left to right and returns the + result. I.e. returns flipud(fliplr(m)). + - returns a matrix M such that: + - M::type == the same type that was in m + - M has the same dimensions as m + - for all valid r and c: + M(r,c) == m(m.nr()-r-1, m.nc()-c-1) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename vector_type + > + const matrix_exp vector_to_matrix ( + const vector_type& vector + ); + /*! + requires + - vector_type is an implementation of array/array_kernel_abstract.h or + std::vector or dlib::std_vector_c or dlib::matrix + ensures + - if (vector_type is a dlib::matrix) then + - returns a reference to vector + - else + - returns a matrix R such that: + - is_col_vector(R) == true + - R.size() == vector.size() + - for all valid r: + R(r) == vector[r] + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename array_type + > + const matrix_exp array_to_matrix ( + const array_type& array + ); + /*! + requires + - array_type is an implementation of array2d/array2d_kernel_abstract.h + or dlib::matrix + ensures + - if (array_type is a dlib::matrix) then + - returns a reference to array + - else + - returns a matrix R such that: + - R.nr() == array.nr() + - R.nc() == array.nc() + - for all valid r and c: + R(r, c) == array[r][c] + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp pointer_to_matrix ( + const T* ptr, + long nr, + long nc + ); + /*! + requires + - nr > 0 + - nc > 0 + - ptr == a pointer to at least nr*nc T objects + ensures + - returns a matrix M such that: + - M.nr() == nr + - m.nc() == nc + - for all valid r and c: + M(r,c) == ptr[r*nc + c] + (i.e. the pointer is interpreted as a matrix laid out in memory + in row major order) + - Note that the returned matrix doesn't take "ownership" of + the pointer and thus will not delete or free it. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp pointer_to_column_vector ( + const T* ptr, + long nr + ); + /*! + requires + - nr > 0 + - ptr == a pointer to at least nr T objects + ensures + - returns a matrix M such that: + - M.nr() == nr + - m.nc() == 1 + - for all valid i: + M(i) == ptr[i] + - Note that the returned matrix doesn't take "ownership" of + the pointer and thus will not delete or free it. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp reshape ( + const matrix_exp& m, + long rows, + long cols + ); + /*! + requires + - m.size() == rows*cols + - rows > 0 + - cols > 0 + ensures + - returns a matrix M such that: + - M.nr() == rows + - M.nc() == cols + - M.size() == m.size() + - for all valid r and c: + - let IDX = r*cols + c + - M(r,c) == m(IDX/m.nc(), IDX%m.nc()) + + - i.e. The matrix m is reshaped into a new matrix of rows by cols + dimension. Additionally, the elements of m are laid into M in row major + order. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp reshape_to_column_vector ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix M such that: + - is_col_vector(M) == true + - M.size() == m.size() + - for all valid r and c: + - m(r,c) == M(r*m.nc() + c) + + - i.e. The matrix m is reshaped into a column vector. Note that + the elements are pulled out in row major order. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + long R, + long C + > + const matrix_exp removerc ( + const matrix_exp& m + ); + /*! + requires + - m.nr() > R >= 0 + - m.nc() > C >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() - 1 + - M.nc() == m.nc() - 1 + - M == m with its R row and C column removed + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp removerc ( + const matrix_exp& m, + long R, + long C + ); + /*! + requires + - m.nr() > R >= 0 + - m.nc() > C >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() - 1 + - M.nc() == m.nc() - 1 + - M == m with its R row and C column removed + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + long R + > + const matrix_exp remove_row ( + const matrix_exp& m + ); + /*! + requires + - m.nr() > R >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() - 1 + - M.nc() == m.nc() + - M == m with its R row removed + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp remove_row ( + const matrix_exp& m, + long R + ); + /*! + requires + - m.nr() > R >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() - 1 + - M.nc() == m.nc() + - M == m with its R row removed + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + long C + > + const matrix_exp remove_col ( + const matrix_exp& m + ); + /*! + requires + - m.nc() > C >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() + - M.nc() == m.nc() - 1 + - M == m with its C column removed + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp remove_col ( + const matrix_exp& m, + long C + ); + /*! + requires + - m.nc() > C >= 0 + ensures + - returns a matrix M such that: + - M.nr() == m.nr() + - M.nc() == m.nc() - 1 + - M == m with its C column removed + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename target_type + > + const matrix_exp matrix_cast ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R where for all valid r and c: + R(r,c) == static_cast(m(r,c)) + also, R has the same dimensions as m. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename MM, + typename U, + typename L + > + void set_all_elements ( + matrix& m, + U value + ); + /*! + ensures + - for all valid r and c: + m(r,c) == value + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::matrix_type tmp ( + const matrix_exp& m + ); + /*! + ensures + - returns a temporary matrix object that is a copy of m. + (This allows you to easily force a matrix_exp to fully evaluate) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + long NR, + long NC, + typename MM, + typename L + > + uint32 hash ( + const matrix& item, + uint32 seed = 0 + ); + /*! + requires + - T is a standard layout type (e.g. a POD type like int, float, + or a simple struct). + ensures + - returns a 32bit hash of the data stored in item. + - Each value of seed results in a different hash function being used. + (e.g. hash(item,0) should generally not be equal to hash(item,1)) + - uses the murmur_hash3() routine to compute the actual hash. + - Note that if the memory layout of the elements in item change between + hardware platforms then hash() will give different outputs. If you want + hash() to always give the same output for the same input then you must + ensure that elements of item always have the same layout in memory. + Typically this means using fixed width types and performing byte swapping + to account for endianness before passing item to hash(). + !*/ + +// ---------------------------------------------------------------------------------------- + + // if matrix_exp contains non-complex types (e.g. float, double) + bool equal ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp::type epsilon = 100*std::numeric_limits::epsilon() + ); + /*! + ensures + - if (a and b don't have the same dimensions) then + - returns false + - else if (there exists an r and c such that abs(a(r,c)-b(r,c)) > epsilon) then + - returns false + - else + - returns true + !*/ + +// ---------------------------------------------------------------------------------------- + + // if matrix_exp contains std::complex types + bool equal ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp::type::value_type epsilon = 100*std::numeric_limits::epsilon() + ); + /*! + ensures + - if (a and b don't have the same dimensions) then + - returns false + - else if (there exists an r and c such that abs(real(a(r,c)-b(r,c))) > epsilon + or abs(imag(a(r,c)-b(r,c))) > epsilon) then + - returns false + - else + - returns true + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b + ); + /*! + requires + - a.nr() == b.nr() + - a.nc() == b.nc() + - a and b both contain the same type of element (one or both + can also be of type std::complex so long as the underlying type + in them is the same) + ensures + - returns a matrix R such that: + - R::type == the same type that was in a and b. + - R has the same dimensions as a and b. + - for all valid r and c: + R(r,c) == a(r,c) * b(r,c) + !*/ + + const matrix_exp pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp& c + ); + /*! + performs pointwise_multiply(a,pointwise_multiply(b,c)); + !*/ + + const matrix_exp pointwise_multiply ( + const matrix_exp& a, + const matrix_exp& b, + const matrix_exp& c, + const matrix_exp& d + ); + /*! + performs pointwise_multiply(pointwise_multiply(a,b),pointwise_multiply(c,d)); + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp join_rows ( + const matrix_exp& a, + const matrix_exp& b + ); + /*! + requires + - a.nr() == b.nr() + - a and b both contain the same type of element + ensures + - This function joins two matrices together by concatenating their rows. + - returns a matrix R such that: + - R::type == the same type that was in a and b. + - R.nr() == a.nr() == b.nr() + - R.nc() == a.nc() + b.nc() + - for all valid r and c: + - if (c < a.nc()) then + - R(r,c) == a(r,c) + - else + - R(r,c) == b(r, c-a.nc()) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp join_cols ( + const matrix_exp& a, + const matrix_exp& b + ); + /*! + requires + - a.nc() == b.nc() + - a and b both contain the same type of element + ensures + - This function joins two matrices together by concatenating their columns. + - returns a matrix R such that: + - R::type == the same type that was in a and b. + - R.nr() == a.nr() + b.nr() + - R.nc() == a.nc() == b.nc() + - for all valid r and c: + - if (r < a.nr()) then + - R(r,c) == a(r,c) + - else + - R(r,c) == b(r-a.nr(), c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp tensor_product ( + const matrix_exp& a, + const matrix_exp& b + ); + /*! + requires + - a and b both contain the same type of element + ensures + - returns a matrix R such that: + - R::type == the same type that was in a and b. + - R.nr() == a.nr() * b.nr() + - R.nc() == a.nc() * b.nc() + - for all valid r and c: + R(r,c) == a(r/b.nr(), c/b.nc()) * b(r%b.nr(), c%b.nc()) + - I.e. R is the tensor product of matrix a with matrix b + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp cartesian_product ( + const matrix_exp& A, + const matrix_exp& B + ); + /*! + requires + - A and B both contain the same type of element + ensures + - Think of A and B as sets of column vectors. Then this function + returns a matrix that contains a set of column vectors that is + the Cartesian product of the sets A and B. That is, the resulting + matrix contains every possible combination of vectors from both A and + B. + - returns a matrix R such that: + - R::type == the same type that was in A and B. + - R.nr() == A.nr() + B.nr() + - R.nc() == A.nc() * B.nc() + - Each column of R is the concatenation of a column vector + from A with a column vector from B. + - for all valid r and c: + - if (r < A.nr()) then + - R(r,c) == A(r, c/B.nc()) + - else + - R(r,c) == B(r-A.nr(), c%B.nc()) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp scale_columns ( + const matrix_exp& m, + const matrix_exp& v + ); + /*! + requires + - is_vector(v) == true + - v.size() == m.nc() + - m and v both contain the same type of element + ensures + - returns a matrix R such that: + - R::type == the same type that was in m and v. + - R has the same dimensions as m. + - for all valid r and c: + R(r,c) == m(r,c) * v(c) + - i.e. R is the result of multiplying each of m's columns by + the corresponding scalar in v. + + - Note that this function is identical to the expression m*diagm(v). + That is, the * operator is overloaded for this case and will invoke + scale_columns() automatically as appropriate. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp scale_rows ( + const matrix_exp& m, + const matrix_exp& v + ); + /*! + requires + - is_vector(v) == true + - v.size() == m.nr() + - m and v both contain the same type of element + ensures + - returns a matrix R such that: + - R::type == the same type that was in m and v. + - R has the same dimensions as m. + - for all valid r and c: + R(r,c) == m(r,c) * v(r) + - i.e. R is the result of multiplying each of m's rows by + the corresponding scalar in v. + + - Note that this function is identical to the expression diagm(v)*m. + That is, the * operator is overloaded for this case and will invoke + scale_rows() automatically as appropriate. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void sort_columns ( + matrix& m, + matrix& v + ); + /*! + requires + - is_col_vector(v) == true + - v.size() == m.nc() + - m and v both contain the same type of element + ensures + - the dimensions for m and v are not changed + - sorts the columns of m according to the values in v. + i.e. + - #v == the contents of v but in sorted order according to + operator<. So smaller elements come first. + - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) + - colm(#m,new(i)) == colm(m,i) + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void rsort_columns ( + matrix& m, + matrix& v + ); + /*! + requires + - is_col_vector(v) == true + - v.size() == m.nc() + - m and v both contain the same type of element + ensures + - the dimensions for m and v are not changed + - sorts the columns of m according to the values in v. + i.e. + - #v == the contents of v but in sorted order according to + operator>. So larger elements come first. + - Let #v(new(i)) == v(i) (i.e. new(i) is the index element i moved to) + - colm(#m,new(i)) == colm(m,i) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type length_squared ( + const matrix_exp& m + ); + /*! + requires + - is_vector(m) == true + ensures + - returns sum(squared(m)) + (i.e. returns the square of the length of the vector m) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type length ( + const matrix_exp& m + ); + /*! + requires + - is_vector(m) == true + ensures + - returns sqrt(sum(squared(m))) + (i.e. returns the length of the vector m) + !*/ + +// ---------------------------------------------------------------------------------------- + + bool is_row_vector ( + const matrix_exp& m + ); + /*! + ensures + - if (m.nr() == 1) then + - return true + - else + - returns false + !*/ + + bool is_col_vector ( + const matrix_exp& m + ); + /*! + ensures + - if (m.nc() == 1) then + - return true + - else + - returns false + !*/ + + bool is_vector ( + const matrix_exp& m + ); + /*! + ensures + - if (is_row_vector(m) || is_col_vector(m)) then + - return true + - else + - returns false + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Thresholding relational operators +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator< ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) < s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator< ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s < m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator<= ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) <= s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator<= ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s <= m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator> ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) > s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator> ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s > m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator>= ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) >= s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator>= ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s >= m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator== ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) == s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator== ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s == m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator!= ( + const matrix_exp& m, + const S& s + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (m(r,c) != s) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix_exp operator!= ( + const S& s, + const matrix_exp& m + ); + /*! + requires + - is_built_in_scalar_type::value == true + - is_built_in_scalar_type::value == true + ensures + - returns a matrix R such that: + - R::type == the same type that was in m. + - R has the same dimensions as m. + - for all valid r and c: + - if (s != m(r,c)) then + - R(r,c) == 1 + - else + - R(r,c) == 0 + - i.e. R is a binary matrix of all 1s or 0s. + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Statistics +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type min ( + const matrix_exp& m + ); + /*! + requires + - m.size() > 0 + ensures + - returns the value of the smallest element of m. If m contains complex + elements then the element returned is the one with the smallest norm + according to std::norm(). + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type max ( + const matrix_exp& m + ); + /*! + requires + - m.size() > 0 + ensures + - returns the value of the biggest element of m. If m contains complex + elements then the element returned is the one with the largest norm + according to std::norm(). + !*/ + +// ---------------------------------------------------------------------------------------- + + void find_min_and_max ( + const matrix_exp& m, + matrix_exp::type& min_val, + matrix_exp::type& max_val + ); + /*! + requires + - m.size() > 0 + ensures + - #min_val == min(m) + - #max_val == max(m) + - This function computes both the min and max in just one pass + over the elements of the matrix m. + !*/ + +// ---------------------------------------------------------------------------------------- + + long index_of_max ( + const matrix_exp& m + ); + /*! + requires + - is_vector(m) == true + - m.size() > 0 + ensures + - returns the index of the largest element in m. + (i.e. m(index_of_max(m)) == max(m)) + !*/ + +// ---------------------------------------------------------------------------------------- + + long index_of_min ( + const matrix_exp& m + ); + /*! + requires + - is_vector(m) == true + - m.size() > 0 + ensures + - returns the index of the smallest element in m. + (i.e. m(index_of_min(m)) == min(m)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type sum ( + const matrix_exp& m + ); + /*! + ensures + - returns the sum of all elements in m + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp sum_rows ( + const matrix_exp& m + ); + /*! + requires + - m.size() > 0 + ensures + - returns a row matrix that contains the sum of all the rows in m. + - returns a matrix M such that + - M::type == the same type that was in m + - M.nr() == 1 + - M.nc() == m.nc() + - for all valid i: + - M(i) == sum(colm(m,i)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp sum_cols ( + const matrix_exp& m + ); + /*! + requires + - m.size() > 0 + ensures + - returns a column matrix that contains the sum of all the columns in m. + - returns a matrix M such that + - M::type == the same type that was in m + - M.nr() == m.nr() + - M.nc() == 1 + - for all valid i: + - M(i) == sum(rowm(m,i)) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type prod ( + const matrix_exp& m + ); + /*! + ensures + - returns the results of multiplying all elements of m together. + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type mean ( + const matrix_exp& m + ); + /*! + ensures + - returns the mean of all elements in m. + (i.e. returns sum(m)/(m.nr()*m.nc())) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp::type variance ( + const matrix_exp& m + ); + /*! + ensures + - returns the unbiased sample variance of all elements in m + (i.e. 1.0/(m.nr()*m.nc() - 1)*(sum of all pow(m(i,j) - mean(m),2))) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix covariance ( + const matrix_exp& m + ); + /*! + requires + - matrix_exp::type == a dlib::matrix object + - is_col_vector(m) == true + - m.size() > 1 + - for all valid i, j: + - is_col_vector(m(i)) == true + - m(i).size() > 0 + - m(i).size() == m(j).size() + - i.e. m contains only column vectors and all the column vectors + have the same non-zero length + ensures + - returns the unbiased sample covariance matrix for the set of samples + in m. + (i.e. 1.0/(m.nr()-1)*(sum of all (m(i) - mean(m))*trans(m(i) - mean(m)))) + - the returned matrix will contain elements of type matrix_exp::type::type. + - the returned matrix will have m(0).nr() rows and columns. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + const matrix randm( + long nr, + long nc, + rand_gen& rnd + ); + /*! + requires + - nr >= 0 + - nc >= 0 + - rand_gen == an object that implements the rand/rand_float_abstract.h interface + ensures + - generates a random matrix using the given rnd random number generator + - returns a matrix M such that + - M::type == double + - M.nr() == nr + - M.nc() == nc + - for all valid i, j: + - M(i,j) == a random number such that 0 <= M(i,j) < 1 + !*/ + +// ---------------------------------------------------------------------------------------- + + inline const matrix randm( + long nr, + long nc + ); + /*! + requires + - nr >= 0 + - nc >= 0 + ensures + - generates a random matrix using std::rand() + - returns a matrix M such that + - M::type == double + - M.nr() == nr + - M.nc() == nc + - for all valid i, j: + - M(i,j) == a random number such that 0 <= M(i,j) < 1 + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Pixel and Image Utilities +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename P + > + const matrix_exp pixel_to_vector ( + const P& pixel + ); + /*! + requires + - pixel_traits

must be defined + ensures + - returns a matrix M such that: + - M::type == T + - M::NC == 1 + - M::NR == pixel_traits

::num + - if (pixel_traits

::grayscale) then + - M(0) == pixel + - if (pixel_traits

::rgb) then + - M(0) == pixel.red + - M(1) == pixel.green + - M(2) == pixel.blue + - if (pixel_traits

::hsi) then + - M(0) == pixel.h + - M(1) == pixel.s + - M(2) == pixel.i + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename P + > + void vector_to_pixel ( + P& pixel, + const matrix_exp& vector + ); + /*! + requires + - vector::NR == pixel_traits

::num + - vector::NC == 1 + (i.e. you have to use a statically dimensioned vector) + ensures + - if (pixel_traits

::grayscale) then + - pixel == M(0) + - if (pixel_traits

::rgb) then + - pixel.red == M(0) + - pixel.green == M(1) + - pixel.blue == M(2) + - if (pixel_traits

::hsi) then + - pixel.h == M(0) + - pixel.s == M(1) + - pixel.i == M(2) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + long lower, + long upper + > + const matrix_exp clamp ( + const matrix_exp& m + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + - if (m(r,c) > upper) then + - R(r,c) == upper + - else if (m(r,c) < lower) then + - R(r,c) == lower + - else + - R(r,c) == m(r,c) + !*/ + +// ---------------------------------------------------------------------------------------- + + const matrix_exp clamp ( + const matrix_exp& m, + const matrix_exp::type& lower, + const matrix_exp::type& upper + ); + /*! + ensures + - returns a matrix R such that: + - R::type == the same type that was in m + - R has the same dimensions as m + - for all valid r and c: + - if (m(r,c) > upper) then + - R(r,c) == upper + - else if (m(r,c) < lower) then + - R(r,c) == lower + - else + - R(r,c) == m(r,c) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MATRIx_UTILITIES_ABSTRACT_ + diff --git a/libs/dlib/matrix/symmetric_matrix_cache.h b/libs/dlib/matrix/symmetric_matrix_cache.h new file mode 100644 index 0000000..b93b9e5 --- /dev/null +++ b/libs/dlib/matrix/symmetric_matrix_cache.h @@ -0,0 +1,464 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SYMMETRIC_MATRIX_CAcHE_H__ +#define DLIB_SYMMETRIC_MATRIX_CAcHE_H__ + +#include "symmetric_matrix_cache_abstract.h" +#include +#include "../matrix.h" +#include "../algs.h" +#include "../array.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template + struct op_symm_cache : basic_op_m + { + inline op_symm_cache( + const M& m_, + long max_size_megabytes_ + ) : + basic_op_m(m_), + max_size_megabytes(max_size_megabytes_), + is_initialized(false) + { + lookup.assign(this->m.nr(), -1); + + diag_cache = matrix_cast(dlib::diag(m_)); + } + + op_symm_cache ( + const op_symm_cache& item + ) : + basic_op_m(item.m), + diag_cache(item.diag_cache), + max_size_megabytes(item.max_size_megabytes), + is_initialized(false) + { + lookup.assign(this->m.nr(), -1); + } + + typedef cache_element_type type; + typedef const cache_element_type& const_ret_type; + const static long cost = M::cost + 3; + + inline const_ret_type apply ( long r, long c) const + { + if (lookup[c] != -1) + { + return cache[lookup[c]](r); + } + else if (r == c) + { + return diag_cache(r); + } + else if (lookup[r] != -1) + { + // the matrix is symmetric so this is legit + return cache[lookup[r]](c); + } + else + { + add_col_to_cache(c); + return cache[lookup[c]](r); + } + } + + inline std::pair col(long i) const + /*! + requires + - 0 <= i < nc() + ensures + - returns a pair P such that: + - P.first == a pointer to the first element of the ith column + - P.second == a pointer to the integer used to count the number of + outstanding references to the ith column. + !*/ + { + if (is_cached(i) == false) + add_col_to_cache(i); + + // find where this column is in the cache + long idx = lookup[i]; + if (idx == next) + { + // if this column was the next to be replaced + // then make sure that doesn't happen + next = (next + 1)%cache.size(); + } + + return std::make_pair(&cache[idx](0), &references[idx]); + } + + const type* diag() const { init(); return &diag_cache(0); } + + long* diag_ref_count() const + { + return &diag_reference_count; + } + + private: + inline bool is_cached ( + long r + ) const + { + return (lookup[r] != -1); + } + + inline void init() const + { + if (is_initialized == false) + { + // figure out how many columns of the matrix we can have + // with the given amount of memory. + long max_size = (max_size_megabytes*1024*1024)/(this->m.nr()*sizeof(type)); + // don't let it be 0 or 1 + if (max_size <= 1) + max_size = 2; + + const long size = std::min(max_size,this->m.nr()); + + diag_reference_count = 0; + + references.set_max_size(this->m.nr()); + references.set_size(size); + for (unsigned long i = 0; i < references.size(); ++i) + references[i] = 0; + + cache.set_max_size(this->m.nr()); + cache.set_size(size); + + rlookup.assign(size,-1); + next = 0; + + is_initialized = true; + } + } + + void make_sure_next_is_unreferenced ( + ) const + { + if (references[next] != 0) + { + // find an unreferenced element of the cache + unsigned long i; + for (i = 1; i < references.size(); ++i) + { + const unsigned long idx = (next+i)%references.size(); + if (references[idx] == 0) + { + next = idx; + break; + } + } + + // if all elements of the cache are referenced then make the cache bigger + // and use the new element. + if (references[next] != 0) + { + cache.resize(cache.size()+1); + + next = references.size(); + references.resize(references.size()+1); + references[next] = 0; + + rlookup.push_back(-1); + } + } + } + + inline void add_col_to_cache( + long c + ) const + { + init(); + make_sure_next_is_unreferenced(); + + // if the lookup table is pointing to cache[next] then clear lookup[next] + if (rlookup[next] != -1) + lookup[rlookup[next]] = -1; + + // make the lookup table so that it says c is now cached at the spot indicated by next + lookup[c] = next; + rlookup[next] = c; + + // compute this column in the matrix and store it in the cache + cache[next] = matrix_cast(colm(this->m,c)); + + next = (next + 1)%cache.size(); + } + + /*! + INITIAL VALUE + - for all valid x: + - lookup(x) == -1 + + - diag_cache == the diagonal of the original matrix + - is_initialized == false + - max_size_megabytes == the max_size_megabytes from symmetric_matrix_cache() + + CONVENTION + - diag_cache == the diagonal of the original matrix + - lookup.size() == diag_cache.size() + + - if (is_initialized) then + - if (lookup[c] != -1) then + - cache[lookup[c]] == the cached column c of the matrix + - rlookup[lookup[c]] == c + + - if (rlookup[x] != -1) then + - lookup[rlookup[x]] == x + - cache[x] == the cached column rlookup[x] of the matrix + + - next == the next element in the cache table to use to cache something + - references[i] == the number of outstanding references to cache element cache[i] + + - diag_reference_count == the number of outstanding references to diag_cache. + (this isn't really needed. It's just here so that we can reuse the matrix + expression from colm() to implement diag()) + !*/ + + + mutable array > cache; + mutable array references; + matrix diag_cache; + mutable std::vector lookup; + mutable std::vector rlookup; + mutable long next; + + const long max_size_megabytes; + mutable bool is_initialized; + mutable long diag_reference_count; + + }; + + template < + typename cache_element_type, + typename EXP + > + const matrix_op > symmetric_matrix_cache ( + const matrix_exp& m, + long max_size_megabytes + ) + { + // Don't check that m is symmetric since doing so would be extremely onerous for the + // kinds of matrices intended for use with the symmetric_matrix_cache. Check everything + // else though. + DLIB_ASSERT(m.size() > 0 && m.nr() == m.nc() && max_size_megabytes >= 0, + "\tconst matrix_exp symmetric_matrix_cache(const matrix_exp& m, max_size_megabytes)" + << "\n\t You have given invalid arguments to this function" + << "\n\t m.nr(): " << m.nr() + << "\n\t m.nc(): " << m.nc() + << "\n\t m.size(): " << m.size() + << "\n\t max_size_megabytes: " << max_size_megabytes + ); + + typedef op_symm_cache op; + return matrix_op(op(m.ref(), max_size_megabytes)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_colm_symm_cache + { + typedef cache_element_type type; + + op_colm_symm_cache( + const M& m_, + const type* data_, + long* ref_count_ + ) : + m(m_), + data(data_), + ref_count(ref_count_) + { + *ref_count += 1; + } + + op_colm_symm_cache ( + const op_colm_symm_cache& item + ) : + m(item.m), + data(item.data), + ref_count(item.ref_count) + { + *ref_count += 1; + } + + ~op_colm_symm_cache( + ) + { + *ref_count -= 1; + } + + const M& m; + + const type* const data; + long* const ref_count; + + const static long cost = M::cost; + const static long NR = M::NR; + const static long NC = 1; + typedef const type& const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + inline const_ret_type apply ( long r, long) const { return data[r]; } + + long nr () const { return m.nr(); } + long nc () const { return 1; } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP, + typename cache_element_type + > + inline const matrix_op > colm ( + const matrix_exp > >& m, + long col + ) + { + DLIB_ASSERT(col >= 0 && col < m.nc(), + "\tconst matrix_exp colm(const matrix_exp& m, row)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\tcol: " << col + ); + + std::pair p = m.ref().op.col(col); + + typedef op_colm_symm_cache op; + return matrix_op(op(m.ref().op.m, + p.first, + p.second)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename EXP, + typename cache_element_type + > + inline const matrix_op > diag ( + const matrix_exp > >& m + ) + { + typedef op_colm_symm_cache op; + return matrix_op(op(m.ref().op.m, + m.ref().op.diag(), + m.ref().op.diag_ref_count())); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_rowm_symm_cache + { + typedef cache_element_type type; + + op_rowm_symm_cache( + const M& m_, + const type* data_, + long* ref_count_ + ) : + m(m_), + data(data_), + ref_count(ref_count_) + { + *ref_count += 1; + } + + op_rowm_symm_cache ( + const op_rowm_symm_cache& item + ) : + m(item.m), + data(item.data), + ref_count(item.ref_count) + { + *ref_count += 1; + } + + ~op_rowm_symm_cache( + ) + { + *ref_count -= 1; + } + + const M& m; + + const type* const data; + long* const ref_count; + + const static long cost = M::cost; + const static long NR = 1; + const static long NC = M::NC; + typedef const type& const_ret_type; + typedef typename M::mem_manager_type mem_manager_type; + typedef typename M::layout_type layout_type; + inline const_ret_type apply ( long , long c) const { return data[c]; } + + long nr () const { return 1; } + long nc () const { return m.nc(); } + + template bool aliases ( const matrix_exp& item) const { return m.aliases(item); } + template bool destructively_aliases ( const matrix_exp& item) const { return m.aliases(item); } + }; + + template < + typename EXP, + typename cache_element_type + > + inline const matrix_op > rowm ( + const matrix_exp > >& m, + long row + ) + { + DLIB_ASSERT(row >= 0 && row < m.nr(), + "\tconst matrix_exp rowm(const matrix_exp& m, row)" + << "\n\tYou have specified invalid sub matrix dimensions" + << "\n\tm.nr(): " << m.nr() + << "\n\tm.nc(): " << m.nc() + << "\n\trow: " << row + ); + + std::pair p = m.ref().op.col(row); + + typedef op_rowm_symm_cache op; + return matrix_op(op(m.ref().op.m, + p.first, + p.second)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct colm_exp > > + { + typedef matrix_op > type; + }; + + template + struct rowm_exp > > + { + typedef matrix_op > type; + }; + + template + struct diag_exp > > + { + typedef matrix_op > type; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SYMMETRIC_MATRIX_CAcHE_H__ + diff --git a/libs/dlib/matrix/symmetric_matrix_cache_abstract.h b/libs/dlib/matrix/symmetric_matrix_cache_abstract.h new file mode 100644 index 0000000..392f4ad --- /dev/null +++ b/libs/dlib/matrix/symmetric_matrix_cache_abstract.h @@ -0,0 +1,63 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#define DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_H__ +#ifndef DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_H__ + +#include "matrix_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename cache_element_type + > + const matrix_exp symmetric_matrix_cache ( + const matrix_exp& m, + long max_size_megabytes + ); + /*! + requires + - m.size() > 0 + - m.nr() == m.nc() + - max_size_megabytes >= 0 + ensures + - This function assumes that m is symmetric. If m is not symmetric then it won't + crash but you will get incorrect results. + - This method creates a matrix expression which internally caches the elements + of m so that they can be accessed quickly. It is useful if m is some kind of + complex matrix expression which is both very large and expensive to evaluate. + An example would be a kernel_matrix() expression with an expensive kernel and + a large number of samples. Such an expression would result in a huge matrix, + potentially too big to store in memory. The symmetric_matrix_cache() then makes + it easy to store just the parts of a matrix expression which are accessed most + often in memory. The specific details are defined below. + - returns a matrix M such that + - M == m + (i.e. M represents the same matrix as m) + - M will cache elements of m and hold them internally so they can be quickly + accessed. In particular, M will attempt to allocate no more than + max_size_megabytes megabytes of memory for the purposes of caching + elements of m. When an element of the matrix is accessed it is either + retrieved from the cache, or if this is not possible, then an entire + column of m is loaded into a part of the cache which hasn't been used + recently and the needed element returned. + - diag(m) is always loaded into the cache and is stored separately from + the cached columns. That means accesses to the diagonal elements of m + are always fast. + - M will store the cached elements of m as cache_element_type objects. + Typically, cache_element_type will be float or double. + - To avoid repeated cache lookups, the following operations are optimized for + use with the symmetric_matrix_cache(): + - diag(M), rowm(M,row_idx), colm(M,col_idx) + These methods will perform only one cache lookup operation for an + entire row/column/diagonal worth of data. + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SYMMETRIC_MATRIX_CAcHE_ABSTRACT_H__ + diff --git a/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h new file mode 100644 index 0000000..0d5794d --- /dev/null +++ b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h @@ -0,0 +1,86 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_STATELESs_1_ +#define DLIB_MEMORY_MANAGER_STATELESs_1_ + +#include "memory_manager_stateless_kernel_abstract.h" + +namespace dlib +{ + template < + typename T + > + class memory_manager_stateless_kernel_1 + { + /*! + this implementation just calls new and delete directly + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless_kernel_1 other; + }; + + memory_manager_stateless_kernel_1( + ) + {} + + virtual ~memory_manager_stateless_kernel_1( + ) {} + + T* allocate ( + ) + { + return new T; + } + + void deallocate ( + T* item + ) + { + delete item; + } + + T* allocate_array ( + unsigned long size + ) + { + return new T[size]; + } + + void deallocate_array ( + T* item + ) + { + delete [] item; + } + + void swap (memory_manager_stateless_kernel_1&) + {} + + private: + + // restricted functions + memory_manager_stateless_kernel_1(memory_manager_stateless_kernel_1&); // copy constructor + memory_manager_stateless_kernel_1& operator=(memory_manager_stateless_kernel_1&); // assignment operator + }; + + template < + typename T + > + inline void swap ( + memory_manager_stateless_kernel_1& a, + memory_manager_stateless_kernel_1& b + ) { a.swap(b); } + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_1_ + + + diff --git a/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h new file mode 100644 index 0000000..7c4bf76 --- /dev/null +++ b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h @@ -0,0 +1,119 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_STATELESs_2_ +#define DLIB_MEMORY_MANAGER_STATELESs_2_ + +#include "../algs.h" +#include "memory_manager_stateless_kernel_abstract.h" +#include "../threads.h" + +namespace dlib +{ + template < + typename T, + typename mem_manager + > + class memory_manager_stateless_kernel_2 + { + /*! + REQUIREMENTS ON mem_manager + mem_manager must be an implementation of memory_manager/memory_manager_kernel_abstract.h + + CONVENTION + this object has a single global instance of mem_manager + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless_kernel_2 other; + }; + + memory_manager_stateless_kernel_2( + ) + { + // call this just to make sure the mutex is is initialized before + // multiple threads start calling the member functions. + global_mutex(); + } + + virtual ~memory_manager_stateless_kernel_2( + ) {} + + T* allocate ( + ) + { + auto_mutex M(global_mutex()); + return global_mm().allocate(); + } + + void deallocate ( + T* item + ) + { + auto_mutex M(global_mutex()); + return global_mm().deallocate(item); + } + + T* allocate_array ( + unsigned long size + ) + { + auto_mutex M(global_mutex()); + return global_mm().allocate_array(size); + } + + void deallocate_array ( + T* item + ) + { + auto_mutex M(global_mutex()); + return global_mm().deallocate_array(item); + } + + void swap (memory_manager_stateless_kernel_2&) + {} + + private: + + static mutex& global_mutex ( + ) + { + static mutex lock; + return lock; + } + + typedef typename mem_manager::template rebind::other rebound_mm_type; + + static rebound_mm_type& global_mm ( + ) + { + static rebound_mm_type mm; + return mm; + } + + // restricted functions + memory_manager_stateless_kernel_2(memory_manager_stateless_kernel_2&); // copy constructor + memory_manager_stateless_kernel_2& operator=(memory_manager_stateless_kernel_2&); // assignment operator + }; + + template < + typename T, + typename mem_manager + > + inline void swap ( + memory_manager_stateless_kernel_2& a, + memory_manager_stateless_kernel_2& b + ) { a.swap(b); } + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_2_ + + + + diff --git a/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h new file mode 100644 index 0000000..2c5b1e7 --- /dev/null +++ b/libs/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h @@ -0,0 +1,142 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ +#ifdef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ + +#include "../algs.h" + +namespace dlib +{ + template < + typename T + > + class memory_manager_stateless + { + /*! + REQUIREMENTS ON T + T must have a default constructor. + + WHAT THIS OBJECT REPRESENTS + This object represents some kind of stateless memory manager or memory pool. + Stateless means that all instances (instances of the same kernel implementation that is) + of this object are identical and can be used interchangeably. Note that + implementations are allowed to have some shared global state such as a + global memory pool. + + THREAD SAFETY + This object is thread safe. You may access it from any thread at any time + without synchronizing access. + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless other; + }; + + memory_manager_stateless( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~memory_manager_stateless( + ); + /*! + ensures + - frees any resources used by *this but has no effect on any shared global + resources used by the implementation. + !*/ + + T* allocate ( + ); + /*! + ensures + - allocates a new object of type T and returns a pointer to it. + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate(). (i.e. The pointer you are deallocating must have + come from the same implementation of memory_manager_stateless + that is trying to deallocate it.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the object pointed to by item + !*/ + + T* allocate_array ( + unsigned long size + ); + /*! + ensures + - allocates a new array of size objects of type T and returns a + pointer to it. + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate_array ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate_array(). (i.e. The pointer you are deallocating must have + come from the same implementation of memory_manager_stateless + that is trying to deallocate it.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the array pointed to by item + !*/ + + void swap ( + memory_manager_stateless& item + ); + /*! + ensures + - this function has no effect on *this or item. It is just provided + to make this object's interface more compatable with the other + memory managers. + !*/ + + private: + + // restricted functions + memory_manager_stateless(memory_manager_stateless&); // copy constructor + memory_manager_stateless& operator=(memory_manager_stateless&); // assignment operator + }; + + template < + typename T + > + inline void swap ( + memory_manager_stateless& a, + memory_manager_stateless& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ + + diff --git a/libs/dlib/noncopyable.h b/libs/dlib/noncopyable.h new file mode 100644 index 0000000..04e6c72 --- /dev/null +++ b/libs/dlib/noncopyable.h @@ -0,0 +1,47 @@ +// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// Contributed by Dave Abrahams +// See http://www.boost.org/libs/utility for documentation. + +#ifndef DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED +#define DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED + +#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED +#define BOOST_NONCOPYABLE_HPP_INCLUDED + +namespace boost +{ + + namespace noncopyable_ // protection from unintended ADL + { + class noncopyable + { + /*! + This class makes it easier to declare a class as non-copyable. + If you want to make an object that can't be copied just inherit + from this object. + !*/ + + protected: + noncopyable() {} + ~noncopyable() {} + private: // emphasize the following members are private + noncopyable( const noncopyable& ); + const noncopyable& operator=( const noncopyable& ); + }; + } + + typedef noncopyable_::noncopyable noncopyable; + +} // namespace boost + +#endif // BOOST_NONCOPYABLE_HPP_INCLUDED + +namespace dlib +{ + using boost::noncopyable; +} + +#endif // DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED + diff --git a/libs/dlib/platform.h b/libs/dlib/platform.h new file mode 100644 index 0000000..6aaae61 --- /dev/null +++ b/libs/dlib/platform.h @@ -0,0 +1,60 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_PLATFORm_ +#define DLIB_PLATFORm_ + + +/*! + This file ensures that: + - if (we are compiling under a posix platform) then + - POSIX will be defined + - if (this is also Mac OS X) then + - MACOSX will be defined + - if (this is also HP-UX) then + - HPUX will be defined + - if (we are compiling under an MS Windows platform) then + - WIN32 will be defined +!*/ + + +/* + A good reference for this sort of information is + http://predef.sourceforge.net/ +*/ + +// Define WIN32 if this is MS Windows +#ifndef WIN32 + #if defined( _MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) + #define WIN32 + #endif +#endif + +#ifndef WIN32 + // since this is the only other platform the library currently supports + // just assume it is POSIX if it isn't WIN32 + #ifndef POSIX + #define POSIX + #endif + + #ifndef HPUX + #if defined(__hpux ) || defined(hpux) || defined (_hpux) + #define HPUX + #endif + #endif + + #ifndef MACOSX + #ifdef __MACOSX__ + #define MACOSX + #endif + #ifdef __APPLE__ + #define MACOSX + #endif + #endif + +#endif + + + + +#endif // DLIB_PLATFORm_ + diff --git a/libs/dlib/serialize.h b/libs/dlib/serialize.h new file mode 100644 index 0000000..d4ce399 --- /dev/null +++ b/libs/dlib/serialize.h @@ -0,0 +1,1047 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SERIALIZe_ +#define DLIB_SERIALIZe_ + +/*! + There are two global functions in the dlib namespace that provide + serialization and deserialization support. Their signatures and specifications + are as follows: + + void serialize ( + const serializable_type& item, + std::ostream& out + ); + /!* + ensures + - writes the state of item to the output stream out + - if (serializable_type implements the enumerable interface) then + - item.at_start() == true + throws + - serialization_error + This exception is thrown if there is some problem which prevents + us from successfully writing item to the output stream. + - any other exception + *!/ + + void deserialize ( + serializable_type& item, + std::istream& in + ); + /!* + ensures + - #item == a deserialized copy of the serializable_type that was + in the input stream in. + - if (serializable_type implements the enumerable interface) then + - item.at_start() == true + throws + - serialization_error + This exception is thrown if there is some problem which prevents + us from successfully deserializing item from the input stream. + If this exception is thrown then item will have an initial value + for its type. + - any other exception + *!/ + + + This file provides serialization support to the following object types: + - The C++ base types (NOT including pointer types) + - std::string + - std::wstring + - std::vector + - std::map + - std::pair + - std::complex + - dlib::uint64 + - dlib::int64 + - enumerable where T is a serializable type + - map_pair where D and R are both serializable types. + - C style arrays of serializable types + + This file provides deserialization support to the following object types: + - The C++ base types (NOT including pointer types) + - std::string + - std::wstring + - std::vector + - std::map + - std::pair + - std::complex + - dlib::uint64 + - dlib::int64 + - C style arrays of serializable types + + Support for deserialization of objects which implement the enumerable or + map_pair interfaces is the responsibility of those objects. + + Note that you can deserialize an integer value to any integral type (except for a + char type) if its value will fit into the target integer type. I.e. the types + short, int, long, unsigned short, unsigned int, unsigned long, and dlib::uint64 + can all receive serialized data from each other so long as the actual serizlied + value fits within the receiving integral type's range. + + Also note that for any container to be serializable the type of object it contains + must be serializable. + + FILE STREAMS + If you are serializing to and from file streams it is important to + remember to set the file streams to binary mode using the std::ios::binary + flag. + + + INTEGRAL SERIALIZATION FORMAT + All C++ integral types (except the char types) are serialized to the following + format: + The first byte is a control byte. It tells you if the serialized number is + positive or negative and also tells you how many of the following bytes are + part of the number. The absolute value of the number is stored in little + endian byte order and follows the control byte. + + The control byte: + The high order bit of the control byte is a flag that tells you if the + encoded number is negative or not. It is set to 1 when the number is + negative and 0 otherwise. + The 4 low order bits of the control byte represent an unsigned number + and tells you how many of the following bytes are part of the encoded + number. + + +!*/ + + +#include "algs.h" +#include "assert.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "uintn.h" +#include "interfaces/enumerable.h" +#include "interfaces/map_pair.h" +#include "enable_if.h" +#include "unicode.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class serialization_error : public error + { + public: + serialization_error(const std::string& e):error(e) {} + }; + +// ---------------------------------------------------------------------------------------- + + namespace ser_helper + { + + template < + typename T + > + typename enable_if_c::is_signed,bool>::type pack_int ( + T item, + std::ostream& out + ) + /*! + requires + - T is a signed integral type + ensures + - if (no problems occur serializing item) then + - writes item to out + - returns false + - else + - returns true + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + unsigned char buf[8]; + unsigned char size = 0; + unsigned char neg; + if (item < 0) + { + neg = 0x80; + item *= -1; + } + else + { + neg = 0; + } + + for (unsigned char i = 0; i < sizeof(T); ++i) + { + buf[i] = static_cast(item&0xFF); + item >>= 8; + if (item == 0) { size = i+1; break; } + } + if (size == 0) + size = sizeof(T); + size |= neg; + + out.write(reinterpret_cast(&size),1); + size &= 0x7F; // strip off the neg flag + out.write(reinterpret_cast(buf),size); + + // check if there was an error + if (!out) + return true; + else + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename enable_if_c::is_signed,bool>::type unpack_int ( + T& item, + std::istream& in + ) + /*! + requires + - T is a signed integral type + ensures + - if (there are no problems deserializing item) then + - returns false + - #item == the value stored in in + - else + - returns true + + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + + + unsigned char buf[8]; + unsigned char size; + bool is_negative; + + item = 0; + in.read(reinterpret_cast(&size),1); + // check if an error occurred + if (!in) + return true; + if (size&0x80) + is_negative = true; + else + is_negative = false; + size &= 0x0F; + + // check if the serialized object is too big + if (size > sizeof(T)) + return true; + + in.read(reinterpret_cast(&buf),size); + + // check if there was an error reading from in. + if (!in) + return true; + + for (unsigned char i = size-1; true; --i) + { + item <<= 8; + item |= buf[i]; + if (i == 0) + break; + } + + if (is_negative) + item *= -1; + + + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename disable_if_c::is_signed,bool>::type pack_int ( + T item, + std::ostream& out + ) + /*! + requires + - T is an unsigned integral type + ensures + - if (no problems occur serializing item) then + - writes item to out + - returns false + - else + - returns true + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + unsigned char buf[8]; + unsigned char size = 0; + + for (unsigned char i = 0; i < sizeof(T); ++i) + { + buf[i] = static_cast(item&0xFF); + item >>= 8; + if (item == 0) { size = i+1; break; } + } + if (size == 0) + size = sizeof(T); + + out.write(reinterpret_cast(&size),1); + out.write(reinterpret_cast(buf),size); + + // check if there was an error + if (!out) + return true; + else + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename disable_if_c::is_signed,bool>::type unpack_int ( + T& item, + std::istream& in + ) + /*! + requires + - T is an unsigned integral type + ensures + - if (there are no problems deserializing item) then + - returns false + - #item == the value stored in in + - else + - returns true + + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + + unsigned char buf[8]; + unsigned char size; + + item = 0; + in.read(reinterpret_cast(&size),1); + // mask out the 3 reserved bits + size &= 0x8F; + // check if an error occurred + if (!in || size > sizeof(T)) + return true; + + + in.read(reinterpret_cast(&buf),size); + + // check if the serialized object is too big to fit into something of type T. + // or if there was an error reading from in. + if (!in) + return true; + + for (unsigned char i = size-1; true; --i) + { + item <<= 8; + item |= buf[i]; + if (i == 0) + break; + } + + return false; + } + + } + +// ---------------------------------------------------------------------------------------- + + #define USE_DEFAULT_INT_SERIALIZATION_FOR(T) \ + inline void serialize (const T& item, std::ostream& out) \ + { if (ser_helper::pack_int(item,out)) throw serialization_error("Error serializing object of type " + std::string(#T)); } \ + inline void deserialize (T& item, std::istream& in) \ + { if (ser_helper::unpack_int(item,in)) throw serialization_error("Error deserializing object of type " + std::string(#T)); } + + #define USE_DEFAULT_BYTE_SERIALIZATION_FOR(T) \ + inline void serialize (const T& item,std::ostream& out) \ + { out.write(reinterpret_cast(&item),1); if (!out) throw serialization_error("Error serializing object of type " + std::string(#T)); } \ + inline void deserialize (T& item, std::istream& in) \ + { in.read(reinterpret_cast(&item),1); if (!in) throw serialization_error("Error deserializing object of type " + std::string(#T)); } + +// ---------------------------------------------------------------------------------------- + + USE_DEFAULT_INT_SERIALIZATION_FOR(short) + USE_DEFAULT_INT_SERIALIZATION_FOR(int) + USE_DEFAULT_INT_SERIALIZATION_FOR(long) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned short) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned int) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned long) + USE_DEFAULT_INT_SERIALIZATION_FOR(uint64) + USE_DEFAULT_INT_SERIALIZATION_FOR(int64) + + USE_DEFAULT_BYTE_SERIALIZATION_FOR(char) + USE_DEFAULT_BYTE_SERIALIZATION_FOR(signed char) + USE_DEFAULT_BYTE_SERIALIZATION_FOR(unsigned char) + + // Don't define serialization for wchar_t when using visual studio and + // _NATIVE_WCHAR_T_DEFINED isn't defined since if it isn't they improperly set + // wchar_t to be a typedef rather than its own type as required by the C++ + // standard. +#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED + USE_DEFAULT_INT_SERIALIZATION_FOR(wchar_t) +#endif + +// ---------------------------------------------------------------------------------------- + + template + inline bool serialize_floating_point ( + const T& item, + std::ostream& out + ) + { + std::ios::fmtflags oldflags = out.flags(); + out.flags(); + std::streamsize ss = out.precision(35); + if (item == std::numeric_limits::infinity()) + out << "inf "; + else if (item == -std::numeric_limits::infinity()) + out << "ninf "; + else if (item < std::numeric_limits::infinity()) + out << item << ' '; + else + out << "NaN "; + out.flags(oldflags); + out.precision(ss); + return (!out); + } + + template + inline bool deserialize_floating_point ( + T& item, + std::istream& in + ) + { + std::ios::fmtflags oldflags = in.flags(); + in.flags(); + std::streamsize ss = in.precision(35); + if (in.peek() == 'i') + { + item = std::numeric_limits::infinity(); + in.get(); + in.get(); + in.get(); + } + else if (in.peek() == 'n') + { + item = -std::numeric_limits::infinity(); + in.get(); + in.get(); + in.get(); + in.get(); + } + else if (in.peek() == 'N') + { + item = std::numeric_limits::quiet_NaN(); + in.get(); + in.get(); + in.get(); + } + else + { + in >> item; + } + in.flags(oldflags); + in.precision(ss); + return (in.get() != ' '); + } + + inline void serialize ( const float& item, std::ostream& out) + { + if (serialize_floating_point(item,out)) + throw serialization_error("Error serializing object of type float"); + } + + inline void deserialize (float& item, std::istream& in) + { + if (deserialize_floating_point(item,in)) + throw serialization_error("Error deserializing object of type float"); + } + + inline void serialize ( const double& item, std::ostream& out) + { + if (serialize_floating_point(item,out)) + throw serialization_error("Error serializing object of type double"); + } + + inline void deserialize (double& item, std::istream& in) + { + if (deserialize_floating_point(item,in)) + throw serialization_error("Error deserializing object of type double"); + } + + inline void serialize ( const long double& item, std::ostream& out) + { + if (serialize_floating_point(item,out)) + throw serialization_error("Error serializing object of type long double"); + } + + inline void deserialize ( long double& item, std::istream& in) + { + if (deserialize_floating_point(item,in)) + throw serialization_error("Error deserializing object of type long double"); + } + +// ---------------------------------------------------------------------------------------- +// prototypes + + template + void serialize ( + const std::map& item, + std::ostream& out + ); + + template + void deserialize ( + std::map& item, + std::istream& in + ); + + template + void serialize ( + const std::vector& item, + std::ostream& out + ); + + template + void deserialize ( + std::vector& item, + std::istream& in + ); + + inline void serialize ( + const std::string& item, + std::ostream& out + ); + + inline void deserialize ( + std::string& item, + std::istream& in + ); + + template < + typename T + > + inline void serialize ( + const enumerable& item, + std::ostream& out + ); + + template < + typename domain, + typename range + > + inline void serialize ( + const map_pair& item, + std::ostream& out + ); + + template < + typename T, + size_t length + > + inline void serialize ( + const T (&array)[length], + std::ostream& out + ); + + template < + typename T, + size_t length + > + inline void deserialize ( + T (&array)[length], + std::istream& in + ); + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + bool item, + std::ostream& out + ) + { + if (item) + out << '1'; + else + out << '0'; + + if (!out) + throw serialization_error("Error serializing object of type bool"); + } + + inline void deserialize ( + bool& item, + std::istream& in + ) + { + int ch = in.get(); + if (ch != EOF) + { + if (ch == '1') + item = true; + else if (ch == '0') + item = false; + else + throw serialization_error("Error deserializing object of type bool"); + } + else + { + throw serialization_error("Error deserializing object of type bool"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::pair& item, + std::ostream& out + ) + { + try + { + serialize(item.first,out); + serialize(item.second,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::pair"); } + } + + template + void deserialize ( + std::pair& item, + std::istream& in + ) + { + try + { + deserialize(item.first,in); + deserialize(item.second,in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::pair"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::map& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + typename std::map::const_iterator i; + for (i = item.begin(); i != item.end(); ++i) + { + serialize(i->first,out); + serialize(i->second,out); + } + + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::map"); } + } + + template + void deserialize ( + std::map& item, + std::istream& in + ) + { + try + { + item.clear(); + + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item[d] = r; + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::map"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (unsigned long i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + serialize(size,out); + out.write(&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + in.read(&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + serialize(size,out); + out.write((char*)&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + in.read((char*)&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const std::string& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::string"); } + + out.write(item.c_str(),size); + if (!out) throw serialization_error("Error serializing object of type std::string"); + } + + inline void deserialize ( + std::string& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::string"); } + + item.resize(size); + if (size != 0) + { + in.read(&item[0],size); + if (!in) throw serialization_error("Error deserializing object of type std::string"); + } + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const std::wstring& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::wstring"); } + + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i], out); + if (!out) throw serialization_error("Error serializing object of type std::wstring"); + } + + inline void deserialize ( + std::wstring& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::wstring"); } + + item.resize(size); + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + + if (!in) throw serialization_error("Error deserializing object of type std::wstring"); + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const ustring& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type ustring"); } + + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i], out); + if (!out) throw serialization_error("Error serializing object of type ustring"); + } + + inline void deserialize ( + ustring& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type ustring"); } + + item.resize(size); + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + + if (!in) throw serialization_error("Error deserializing object of type ustring"); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void serialize ( + const enumerable& item, + std::ostream& out + ) + { + try + { + item.reset(); + serialize(item.size(),out); + while (item.move_next()) + serialize(item.element(),out); + item.reset(); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type enumerable"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range + > + inline void serialize ( + const map_pair& item, + std::ostream& out + ) + { + try + { + serialize(item.key(),out); + serialize(item.value(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type map_pair"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t length + > + inline void serialize ( + const T (&array)[length], + std::ostream& out + ) + { + try + { + serialize(length,out); + for (size_t i = 0; i < length; ++i) + serialize(array[i],out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing a C style array"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t length + > + inline void deserialize ( + T (&array)[length], + std::istream& in + ) + { + size_t size; + try + { + deserialize(size,in); + if (size == length) + { + for (size_t i = 0; i < length; ++i) + deserialize(array[i],in); + } + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing a C style array"); + } + + if (size != length) + throw serialization_error("Error deserializing a C style array, lengths do not match"); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void serialize ( + const std::complex& item, + std::ostream& out + ) + { + try + { + serialize(item.real(),out); + serialize(item.imag(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type std::complex"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void deserialize ( + std::complex& item, + std::istream& in + ) + { + try + { + T real, imag; + deserialize(real,in); + deserialize(imag,in); + item = std::complex(real,imag); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type std::complex"); + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SERIALIZe_ + diff --git a/libs/dlib/stack_trace.h b/libs/dlib/stack_trace.h new file mode 100644 index 0000000..729e1cb --- /dev/null +++ b/libs/dlib/stack_trace.h @@ -0,0 +1,118 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STACK_TRACe_ +#define DLIB_STACK_TRACe_ + +/*! + This file defines 3 things. Two of them are preprocessor macros that + enable you to tag functions with the dlib stack trace watcher. The + third thing is a function named get_stack_trace() which returns the + current stack trace in std::string form. + + To enable the stack trace you must #define DLIB_ENABLE_STACK_TRACE. + When this #define isn't set then the 3 things described above + still exist but they don't do anything. + + Also note that when the stack trace is enabled it changes the DLIB_ASSERT + and DLIB_CASSERT macros so that they print stack traces when + an assert fails. + + See the following example program for details: + + #include + #include + + void funct2() + { + // put this macro at the top of each function you would + // like to appear in stack traces + DLIB_STACK_TRACE; + + // you may print the current stack trace as follows. + std::cout << dlib::get_stack_trace() << endl; + } + + void funct() + { + // This alternate form of DLIB_STACK_TRACE allows you to specify + // the string used to name the current function. The other form + // will usually output an appropriate function name automatically + // so this may not be needed. + DLIB_STACK_TRACE_NAMED("funct"); + funct2(); + } + + int main() + { + funct(); + } +!*/ + + +#include +#include "assert.h" + +// only setup the stack trace stuff if the asserts are enabled (which happens in debug mode +// basically). Also, this stuff doesn't work if you use NO_MAKEFILE +#if defined(DLIB_ENABLE_STACK_TRACE) +#ifdef NO_MAKEFILE +#error "You can't use the dlib stack trace stuff and NO_MAKEFILE at the same time" +#endif + +namespace dlib +{ + const std::string get_stack_trace(); +} + +// redefine the DLIB_CASSERT macro to include the stack trace +#undef DLIB_CASSERT +#define DLIB_CASSERT(_exp,_message) \ + {if ( !(_exp) ) \ + { \ + std::ostringstream dlib__out; \ + dlib__out << "\n\nError occurred at line " << __LINE__ << ".\n"; \ + dlib__out << "Error occurred in file " << __FILE__ << ".\n"; \ + dlib__out << "Error occurred in function " << DLIB_FUNCTION_NAME << ".\n\n"; \ + dlib__out << "Failing expression was " << #_exp << ".\n"; \ + dlib__out << _message << "\n\n"; \ + dlib__out << "Stack Trace: \n" << dlib::get_stack_trace() << "\n"; \ + dlib_assert_breakpoint(); \ + throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib__out.str()); \ + }} + + + +namespace dlib +{ + + class stack_tracer + { + public: + stack_tracer ( + const char* funct_name, + const char* file_name, + const int line_number + ); + + ~stack_tracer(); + + }; +} + +#define DLIB_STACK_TRACE_NAMED(x) dlib::stack_tracer dlib_stack_tracer_object(x,__FILE__,__LINE__) +#define DLIB_STACK_TRACE dlib::stack_tracer dlib_stack_tracer_object(DLIB_FUNCTION_NAME,__FILE__,__LINE__) + +#else // don't do anything if ENABLE_ASSERTS isn't defined +#define DLIB_STACK_TRACE_NAMED(x) +#define DLIB_STACK_TRACE + +namespace dlib +{ + inline const std::string get_stack_trace() { return std::string("stack trace not enabled");} +} + +#endif + + +#endif // DLIB_STACK_TRACe_ + diff --git a/libs/dlib/uintn.h b/libs/dlib/uintn.h new file mode 100644 index 0000000..a636de7 --- /dev/null +++ b/libs/dlib/uintn.h @@ -0,0 +1,96 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifndef DLIB_UINtn_ +#define DLIB_UINtn_ + +#include "dassert.h" + +namespace dlib +{ + + /*! + uint64 is a typedef for an unsigned integer that is exactly 64 bits wide. + uint32 is a typedef for an unsigned integer that is exactly 32 bits wide. + uint16 is a typedef for an unsigned integer that is exactly 16 bits wide. + uint8 is a typedef for an unsigned integer that is exactly 8 bits wide. + + int64 is a typedef for an integer that is exactly 64 bits wide. + int32 is a typedef for an integer that is exactly 32 bits wide. + int16 is a typedef for an integer that is exactly 16 bits wide. + int8 is a typedef for an integer that is exactly 8 bits wide. + !*/ + + +#ifdef __GNUC__ + typedef unsigned long long uint64; + typedef long long int64; +#elif __BORLANDC__ + typedef unsigned __int64 uint64; + typedef __int64 int64; +#elif _MSC_VER + typedef unsigned __int64 uint64; + typedef __int64 int64; +#else + typedef unsigned long long uint64; + typedef long long int64; +#endif + + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef unsigned char uint8; + + typedef short int16; + typedef int int32; + typedef char int8; + + + // make sure these types have the right sizes on this platform + COMPILE_TIME_ASSERT(sizeof(uint8) == 1); + COMPILE_TIME_ASSERT(sizeof(uint16) == 2); + COMPILE_TIME_ASSERT(sizeof(uint32) == 4); + COMPILE_TIME_ASSERT(sizeof(uint64) == 8); + + COMPILE_TIME_ASSERT(sizeof(int8) == 1); + COMPILE_TIME_ASSERT(sizeof(int16) == 2); + COMPILE_TIME_ASSERT(sizeof(int32) == 4); + COMPILE_TIME_ASSERT(sizeof(int64) == 8); + + + + template + struct unsigned_type; + template + struct unsigned_type { typedef uint8 type; }; + template + struct unsigned_type { typedef uint16 type; }; + template + struct unsigned_type { typedef uint32 type; }; + template + struct unsigned_type { typedef uint64 type; }; + /*! + ensures + - sizeof(unsigned_type::type) == sizeof(T) + - unsigned_type::type is an unsigned integral type + !*/ + + template + T zero_extend_cast( + const U val + ) + /*! + requires + - U and T are integral types + ensures + - let ut be a typedef for unsigned_type::type + - return static_cast(static_cast(val)); + !*/ + { + typedef typename unsigned_type::type ut; + return static_cast(static_cast(val)); + } + +} + +#endif // DLIB_UINtn_ + diff --git a/libs/dlib/unicode.h b/libs/dlib/unicode.h new file mode 100644 index 0000000..3c15988 --- /dev/null +++ b/libs/dlib/unicode.h @@ -0,0 +1,9 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_TOP_ +#define DLIB_UNICODe_TOP_ + +#include "unicode/unicode.h" + +#endif // DLIB_UNICODe_TOP_ + diff --git a/libs/dlib/unicode/unicode.cpp b/libs/dlib/unicode/unicode.cpp new file mode 100644 index 0000000..e0ba416 --- /dev/null +++ b/libs/dlib/unicode/unicode.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2008 Keita Mochizuki, Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_CPp_ +#define DLIB_UNICODe_CPp_ +#include "unicode.h" +#include +//#include "../string.h" +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + static const unichar SURROGATE_FIRST_TOP = 0xD800; + static const unichar SURROGATE_SECOND_TOP = 0xDC00; + static const unichar SURROGATE_CLEARING_MASK = 0x03FF; + static const unichar SURROGATE_TOP = SURROGATE_FIRST_TOP; + static const unichar SURROGATE_END = 0xE000; + static const unichar SMP_TOP = 0x10000; + static const int VALID_BITS = 10; + +// ---------------------------------------------------------------------------------------- + + template bool is_surrogate(T ch) + { + return (zero_extend_cast(ch) >= SURROGATE_TOP && + zero_extend_cast(ch) < SURROGATE_END); + } + +// ---------------------------------------------------------------------------------------- + + template unichar surrogate_pair_to_unichar(T first, T second) + { + return ((first & SURROGATE_CLEARING_MASK) << VALID_BITS) | ((second & SURROGATE_CLEARING_MASK) + SMP_TOP); + } + //110110 0000000000 + //110111 0000000000 + +// ---------------------------------------------------------------------------------------- + + void unichar_to_surrogate_pair(unichar input, unichar &first, unichar &second) + { + first = ((input - SMP_TOP) >> VALID_BITS) | SURROGATE_FIRST_TOP; + second = (input & SURROGATE_CLEARING_MASK) | SURROGATE_SECOND_TOP; + } + +// ---------------------------------------------------------------------------------------- + + template void wstr2ustring_t(const wchar_t *src, size_t src_len, ustring &dest); + + template <> void wstr2ustring_t<4>(const wchar_t *src, size_t , ustring &dest) + { + dest.assign((const unichar *)(src)); + } + + template <> void wstr2ustring_t<2>(const wchar_t *src, size_t src_len, ustring &dest) + { + size_t wlen = 0; + for (size_t i = 0; i < src_len; i++) + { + is_surrogate(src[i]) ? i++, wlen++ : wlen++; + } + dest.resize(wlen); + for (size_t i = 0, ii = 0; ii < src_len; ++i) + { + if (is_surrogate(src[ii])) + { + dest[i] = surrogate_pair_to_unichar(src[ii], src[ii+1]); + ii += 2; + }else + { + dest[i] = zero_extend_cast(src[ii]); + ii++; + } + } + } + +// ---------------------------------------------------------------------------------------- + + const ustring convert_wstring_to_utf32(const std::wstring &src) + { + ustring dest; + wstr2ustring_t(src.c_str(), src.size(), dest); + return dest; + } + +// ---------------------------------------------------------------------------------------- + + template struct ustring2wstr + { + }; + + // for the environment of sizeof(wchar_t) == 2 (i.e. Win32) + template <> struct ustring2wstr<2> + { + wchar_t *wstr; + size_t wlen; + ustring2wstr(const ustring &src){ + wlen = 0; + for (size_t i = 0; i < src.length(); ++i) + { + if (src[i] < SMP_TOP) wlen++; + else wlen += 2; + } + wstr = new wchar_t[wlen+1]; + wstr[wlen] = L'\0'; + + size_t wi = 0; + for (size_t i = 0; i < src.length(); ++i) + { + if (src[i] < SMP_TOP) + { + wstr[wi++] = (wchar_t)src[i]; + }else + { + unichar high, low; + unichar_to_surrogate_pair(src[i], high, low); + wstr[wi++] = (wchar_t)high; + wstr[wi++] = (wchar_t)low; + } + } + } + ~ustring2wstr() + { + delete[] wstr; + } + }; + + // for the environment of sizeof(wchar_t) == 4 (i.e. Unix gcc) + template <> struct ustring2wstr<4> + { + const wchar_t *wstr; + size_t wlen; + ustring2wstr(const ustring &src){ + wstr = (const wchar_t *)(src.c_str()); + wlen = src.size(); + } + }; + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_utf32_to_wstring(const ustring &src) + { + ustring2wstr conv(src); + std::wstring dest(conv.wstr); + return dest; + } + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_mbstring_to_wstring(const std::string &src) + { + std::vector wstr(src.length()+1); + std::mbstowcs(&wstr.front(), src.c_str(), src.length()+1); + return std::wstring(&wstr.front()); + } + +// ---------------------------------------------------------------------------------------- + + const std::string convert_wstring_to_mbstring(const std::wstring &src) + { + using namespace std; + std::string str; + str.resize((src.length() + 1) * MB_CUR_MAX); + wcstombs(&str[0], src.c_str(), str.size()); + return std::string(&str[0]); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_UNICODe_CPp_ + diff --git a/libs/dlib/unicode/unicode.h b/libs/dlib/unicode/unicode.h new file mode 100644 index 0000000..a6feaa2 --- /dev/null +++ b/libs/dlib/unicode/unicode.h @@ -0,0 +1,612 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net), and Nils Labugt +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_H_ +#define DLIB_UNICODe_H_ + +#include "../uintn.h" +#include "../algs.h" +#include "unicode_abstract.h" +#include +#include + +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + typedef uint32 unichar; + +#if defined(__GNUC__) && __GNUC__ < 4 && __GNUC_MINOR__ < 4 + struct unichar_traits + { + typedef dlib::unichar char_type; + typedef dlib::unichar int_type; + typedef std::streamoff off_type; + typedef std::streampos pos_type; + typedef std::mbstate_t state_type; + + static void assign(char_type& c1, const char_type& c2) { c1 = c2; } + static bool eq(const char_type& c1, const char_type& c2) { return c1 == c2; } + static bool lt(const char_type& c1, const char_type& c2) { return c1 < c2; } + static int compare(const char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + { + if (s1[i] < s2[i]) + return -1; + else if (s1[i] > s2[i]) + return 1; + } + return 0; + } + + static size_t length(const char_type* s) + { + size_t i = 0; + while (s[i] != 0) + ++i; + return i; + } + + static const char_type* find(const char_type* s, size_t n, + const char_type& a) + { + for (size_t i = 0; i < n; ++i) + { + if (s[i] == a) + { + return s+i; + } + } + return 0; + } + + static char_type* move(char_type* s1, const char_type* s2, size_t n) + { + return static_cast(std::memmove(s1, s2, sizeof(char_type)*n)); + } + + static char_type* copy(char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + s1[i] = s2[i]; + + return s1; + } + + static char_type* assign(char_type* s, size_t n, char_type a) + { + for (size_t i = 0; i < n; ++i) + s[i] = a; + + return s; + } + + + static int_type not_eof(const int_type& c) + { + if (!eq_int_type(c,eof())) + return to_int_type(c); + else + return 0; + } + + static char_type to_char_type(const int_type& c) { return static_cast(c); } + static int_type to_int_type(const char_type& c) { return zero_extend_cast(c); } + + static bool eq_int_type(const int_type& c1, const int_type& c2) { return c1 == c2; } + + static int_type eof() { return static_cast(EOF); } + }; + + typedef std::basic_string ustring; +#else + typedef std::basic_string ustring; +#endif + +// ---------------------------------------------------------------------------------------- + + namespace unicode_helpers + { + + template < + typename charT + > + int u8_to_u32( + charT& result, + std::istream& in + ) + /*! + ensures + - if (there just wasn't any more data and we hit EOF) then + - returns 0 + - else if (we decoded another character without error) then + - #result == the decoded character + - returns the number of bytes consumed to make this character + - else + - some error occurred + - returns -1 + !*/ + { + int val = in.get(); + if (val == EOF) + return 0; + + unichar ch[4]; + ch[0] = zero_extend_cast(val); + if ( ch[0] < 0x80 ) + { + result = static_cast(ch[0]); + return 1; + } + if ( ( ch[0] & ~0x3F ) == 0x80 ) + { + // invalid leading byte + return -1; + } + if ( ( ch[0] & ~0x1F ) == 0xC0 ) + { + val = in.get(); + if ( val == EOF ) + return -1; + + ch[1] = zero_extend_cast(val); + if ( ( ch[1] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + if ( ( ch[0] & ~0x01 ) == 0xC0 ) + return -1; // overlong form + ch[0] &= 0x1F; + ch[1] &= 0x3F; + result = static_cast(( ch[0] << 6 ) | ch[1]); + return 2; + } + if ( ( ch[0] & ~0x0F ) == 0xE0 ) + { + for ( unsigned n = 1;n < 3;n++ ) + { + val = in.get(); + if ( val == EOF ) + return -1; + ch[n] = zero_extend_cast(val); + if ( ( ch[n] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + ch[n] &= 0x3F; + } + ch[0] &= 0x0F; + result = static_cast(( ch[0] << 12 ) | ( ch[1] << 6 ) | ch[2]); + if ( result < 0x0800 ) + return -1; // overlong form + if ( result >= 0xD800 && result < 0xE000 ) + return -1; // invalid character (UTF-16 surrogate pairs) + if ( result >= 0xFDD0 && result <= 0xFDEF ) + return -1; // noncharacter + if ( result >= 0xFFFE ) + return -1; // noncharacter + return 3; + } + if ( ( ch[0] & ~0x07 ) == 0xF0 ) + { + for ( unsigned n = 1;n < 4;n++ ) + { + val = in.get(); + if ( val == EOF ) + return -1; + ch[n] = zero_extend_cast(val); + if ( ( ch[n] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + ch[n] &= 0x3F; + } + if ( ( ch[0] ^ 0xF6 ) < 4 ) + return -1; + ch[0] &= 0x07; + result = static_cast(( ch[0] << 18 ) | ( ch[1] << 12 ) | ( ch[2] << 6 ) | ch[3]); + if ( result < 0x10000 ) + return -1; // overlong form + if ( (result & 0xFFFF) >= 0xFFFE ) + return -1; // noncharacter + return 4; + } + return -1; + } + + // ------------------------------------------------------------------------------------ + + template + class basic_utf8_streambuf : public std::basic_streambuf + { + public: + basic_utf8_streambuf ( + std::ifstream& fin_ + ) : + fin(fin_) + { + setg(in_buffer+max_putback, + in_buffer+max_putback, + in_buffer+max_putback); + } + + protected: + + typedef typename std::basic_streambuf::int_type int_type; + + // input functions + int_type underflow( + ) + { + if (this->gptr() < this->egptr()) + { + return zero_extend_cast(*this->gptr()); + } + + int num_put_back = static_cast(this->gptr() - this->eback()); + if (num_put_back > max_putback) + { + num_put_back = max_putback; + } + + // copy the putback characters into the putback end of the in_buffer + std::memmove(in_buffer+(max_putback-num_put_back), this->gptr()-num_put_back, num_put_back); + + + // fill the buffer with characters + int n = in_buffer_size-max_putback; + int i; + for (i = 0; i < n; ++i) + { + charT ch; + if (unicode_helpers::u8_to_u32(ch,fin) > 0) + { + (in_buffer+max_putback)[i] = ch; + } + else + { + break; + } + } + + if (i == 0) + { + // an error occurred or we hit EOF + return EOF; + } + + // reset in_buffer pointers + setg (in_buffer+(max_putback-num_put_back), + in_buffer+max_putback, + in_buffer+max_putback+i); + + return zero_extend_cast(*this->gptr()); + } + + private: + std::ifstream& fin; + static const int max_putback = 4; + static const int in_buffer_size = 10; + charT in_buffer[in_buffer_size]; + }; + } + +// ---------------------------------------------------------------------------------------- + + template + bool is_combining_char( + const T ch_ + ) + { + const unichar ch = zero_extend_cast(ch_); + if ( ch < 0x300 ) return false; + if ( ch < 0x370 ) return true; + + if ( ch < 0x800 ) + { + if ( ch < 0x483 )return false;if ( ch < 0x48A )return true; + + if ( ch < 0x591 )return false;if ( ch < 0x5D0 ) + { + if ( ch == 0x5C0 )return false; + if ( ch == 0x5C3 )return false; + if ( ch == 0x5C6 )return false; + return true; + } + if ( ch < 0x610 )return false;if ( ch < 0x616 )return true; + if ( ch < 0x64B )return false;if ( ch < 0x660 )return true; + + if ( ch == 0x670 )return true; + + if ( ch < 0x6D6 )return false;if ( ch < 0x6EE ) + { + if ( ch == 0x6DD )return false; + if ( ch == 0x6E5 )return false; + if ( ch == 0x6E6 )return false; + if ( ch == 0x6E9 )return false; + return true; + } + if ( ch == 0x711 )return true; + + if ( ch < 0x730 )return false;if ( ch < 0x74B )return true; + if ( ch < 0x7A6 )return false;if ( ch < 0x7B1 )return true; + if ( ch < 0x7EB )return false;if ( ch < 0x7F4 )return true; + return false; + } + if ( ch < 0xA00 ) + { + if ( ch < 0x901 )return false;if ( ch < 0x904 )return true; + if ( ch < 0x93C )return false;if ( ch < 0x955 ) + { + if ( ch == 0x93D )return false; + if ( ch == 0x950 )return false; + return true; + } + if ( ch < 0x962 )return false;if ( ch < 0x964 )return true; + if ( ch < 0x981 )return false;if ( ch < 0x984 )return true; + if ( ch < 0x9BC )return false;if ( ch < 0x9D8 ) + { + if ( ch == 0x9BD )return false; + if ( ch == 0x9CE )return false; + return true; + } + if ( ch < 0x9E2 )return false;if ( ch < 0x9E4 )return true; + return false; + } + if ( ch < 0xC00 ) + { + if ( ch < 0xA01 )return false;if ( ch < 0xA04 )return true; + if ( ch < 0xA3C )return false;if ( ch < 0xA4E )return true; + if ( ch < 0xA70 )return false;if ( ch < 0xA72 )return true; + if ( ch < 0xA81 )return false;if ( ch < 0xA84 )return true; + if ( ch < 0xABC )return false;if ( ch < 0xACE ) + { + if ( ch == 0xABD )return false; + return true; + } + if ( ch < 0xAE2 )return false;if ( ch < 0xAE4 )return true; + if ( ch < 0xB01 )return false;if ( ch < 0xB04 )return true; + if ( ch < 0xB3C )return false;if ( ch < 0xB58 ) + { + if ( ch == 0xB3D )return false; + return true; + } + if ( ch == 0xB82 )return true; + + if ( ch < 0xBBE )return false;if ( ch < 0xBD8 )return true; + + if ( ch == 0xBF4 )return true; + if ( ch == 0xBF8 )return true; + return false; + } + if(ch < 0xE00) + { + if ( ch < 0xC01 )return false;if ( ch < 0xC04 )return true; + if ( ch < 0xC3E )return false;if ( ch < 0xC57 )return true; + if ( ch < 0xC82 )return false;if ( ch < 0xC84 )return true; + if ( ch < 0xCBC )return false;if ( ch < 0xCD7 ) + { + if ( ch == 0xCBD )return false; + return true; + } + if ( ch < 0xCE2 )return false;if ( ch < 0xCE4 )return true; + if ( ch < 0xD02 )return false;if ( ch < 0xD04 )return true; + if ( ch < 0xD3E )return false;if ( ch < 0xD58 )return true; + if ( ch < 0xD82 )return false;if ( ch < 0xD84 )return true; + if ( ch < 0xDCA )return false;if ( ch < 0xDF4 )return true; + return false; + } + if(ch < 0x1000) + { + if ( ch == 0xE31 )return true; + + if ( ch < 0xE34 )return false;if ( ch < 0xE3B )return true; + if ( ch < 0xE47 )return false;if ( ch < 0xE4F )return true; + + if ( ch == 0xEB1 )return true; + + if ( ch < 0xEB4 )return false;if ( ch < 0xEBD )return true; + if ( ch < 0xEC8 )return false;if ( ch < 0xECE )return true; + if ( ch < 0xF18 )return false;if ( ch < 0xF1A )return true; + + if ( ch == 0xF35 )return true; + if ( ch == 0xF37 )return true; + if ( ch == 0xF39 )return true; + + if ( ch < 0xF3E )return false;if ( ch < 0xF40 )return true; + if ( ch < 0xF71 )return false;if ( ch < 0xF88 ) + { + if ( ch == 0xF85 )return false; + return true; + } + if ( ch < 0xF90 )return false;if ( ch < 0xFBD )return true; + + if ( ch == 0xFC6 )return true; + return false; + } + if ( ch < 0x1800 ) + { + if ( ch < 0x102C )return false;if ( ch < 0x1040 )return true; + if ( ch < 0x1056 )return false;if ( ch < 0x105A )return true; + + if ( ch == 0x135F )return true; + + if ( ch < 0x1712 )return false;if ( ch < 0x1715 )return true; + if ( ch < 0x1732 )return false;if ( ch < 0x1735 )return true; + if ( ch < 0x1752 )return false;if ( ch < 0x1754 )return true; + if ( ch < 0x1772 )return false;if ( ch < 0x1774 )return true; + if ( ch < 0x17B6 )return false;if ( ch < 0x17D4 )return true; + + if ( ch == 0x17DD )return true; + return false; + } + if(ch < 0x2000) + { + if ( ch < 0x180B )return false;if ( ch < 0x180E )return true; + + if ( ch == 0x18A9 )return true; + + if ( ch < 0x1920 )return false;if ( ch < 0x193C )return true; + if ( ch < 0x19B0 )return false;if ( ch < 0x19C1 )return true; + if ( ch < 0x19C8 )return false;if ( ch < 0x19CA )return true; + if ( ch < 0x1A17 )return false;if ( ch < 0x1A1C )return true; + if ( ch < 0x1B00 )return false;if ( ch < 0x1B05 )return true; + if ( ch < 0x1B34 )return false;if ( ch < 0x1B45 )return true; + if ( ch < 0x1B6B )return false;if ( ch < 0x1B74 )return true; + if ( ch < 0x1DC0 )return false;if ( ch < 0x1E00 )return true; + return false; + } + if ( ch < 0x20D0 )return false;if ( ch < 0x2100 )return true; + if ( ch < 0x302A )return false;if ( ch < 0x3030 )return true; + if ( ch < 0x3099 )return false;if ( ch < 0x309B )return true; + + if ( ch == 0xA802 )return true; + if ( ch == 0xA806 )return true; + if ( ch == 0xA80B )return true; + + if ( ch < 0xA823 )return false;if ( ch < 0xA828 )return true; + + if ( ch == 0xFB1E )return true; + + if ( ch < 0xFE00 )return false;if ( ch < 0xFE10 )return true; + if ( ch < 0xFE20 )return false;if ( ch < 0xFE30 )return true; + if ( ch < 0x10A01 )return false;if ( ch < 0x10A10 )return true; + if ( ch < 0x10A38 )return false;if ( ch < 0x10A40 )return true; + if ( ch < 0x1D165 )return false;if ( ch < 0x1D16A )return true; + if ( ch < 0x1D16D )return false;if ( ch < 0x1D173 )return true; + if ( ch < 0x1D17B )return false;if ( ch < 0x1D183 )return true; + if ( ch < 0x1D185 )return false;if ( ch < 0x1D18C )return true; + if ( ch < 0x1D1AA )return false;if ( ch < 0x1D1AE )return true; + if ( ch < 0x1D242 )return false;if ( ch < 0x1D245 )return true; + if ( ch < 0xE0100 )return false;if ( ch < 0xE01F0 )return true; + return false; + } + +// ---------------------------------------------------------------------------------------- + + class invalid_utf8_error : public error + { + public: + invalid_utf8_error():error(EUTF8_TO_UTF32) {} + }; + + inline const ustring convert_utf8_to_utf32 ( + const std::string& str + ) + { + using namespace unicode_helpers; + ustring temp; + std::istringstream sin(str); + + temp.reserve(str.size()); + + int status; + unichar ch; + while ( (status = u8_to_u32(ch,sin)) > 0) + temp.push_back(ch); + + if (status < 0) + throw invalid_utf8_error(); + + return temp; + } + +// ---------------------------------------------------------------------------------------- + + bool is_surrogate(unichar ch); + + unichar surrogate_pair_to_unichar(unichar first, unichar second); + + void unichar_to_surrogate_pair(unichar unicode, unichar &first, unichar &second); + + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + + const std::wstring convert_utf32_to_wstring ( + const ustring &src + ); + + const std::wstring convert_mbstring_to_wstring ( + const std::string &src + ); + + const std::string convert_wstring_to_mbstring( + const std::wstring &src + ); + +// ---------------------------------------------------------------------------------------- + + template + class basic_utf8_ifstream : public std::basic_istream + { + public: + + basic_utf8_ifstream ( + ) : std::basic_istream(&buf), buf(fin) {} + + basic_utf8_ifstream ( + const char* file_name + ) : + std::basic_istream(&buf), + buf(fin) + { + fin.open(file_name); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + basic_utf8_ifstream ( + const std::string& file_name + ) : + std::basic_istream(&buf), + buf(fin) + { + fin.open(file_name.c_str()); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + void open( + const std::string& file_name + ) + { + open(file_name.c_str()); + } + + void open ( + const char* file_name + ) + { + fin.close(); + fin.clear(); + fin.open(file_name); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + void close ( + ) + { + fin.close(); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + private: + + std::ifstream fin; + unicode_helpers::basic_utf8_streambuf buf; + }; + + typedef basic_utf8_ifstream utf8_uifstream; + typedef basic_utf8_ifstream utf8_wifstream; + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "unicode.cpp" +#endif + +#endif // DLIB_UNICODe_H_ + diff --git a/libs/dlib/unicode/unicode_abstract.h b/libs/dlib/unicode/unicode_abstract.h new file mode 100644 index 0000000..04261c1 --- /dev/null +++ b/libs/dlib/unicode/unicode_abstract.h @@ -0,0 +1,221 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net), and Nils Labugt +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_UNICODe_ABSTRACT_H_ +#ifdef DLIB_UNICODe_ABSTRACT_H_ + +#include "../uintn.h" +#include "../error.h" +#include +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // a typedef for an unsigned 32bit integer to hold our UNICODE characters + typedef uint32 unichar; + + // a typedef for a string object to hold our UNICODE strings + typedef std::basic_string ustring; + +// ---------------------------------------------------------------------------------------- + + template + bool is_combining_char( + const T ch_ + ); + /*! + ensures + - if (ch_ is a unicode combining character) then + - returns true + - else + - returns false + !*/ + + bool is_surrogate( + unichar ch + ); + /*! + ensures + - if (ch is a unicode surrogate character) then + - returns true + - else + - returns false + !*/ + + unichar surrogate_pair_to_unichar( + unichar first, + unichar second + ); + /*! + requires + - 0xD800 <= first < 0xDC00 + - 0xDC00 <= second < 0xE000 + - is_surrogate(first) == true + - is_surrogate(second) == true + ensures + - converts two surrogates into one unicode character + !*/ + + void unichar_to_surrogate_pair( + unichar ch, + unichar& first, + unichar& second + ); + /*! + requires + - ch >= 0x10000 (i.e. is not in Basic Multilingual Plane) + ensures + - surrogate_pair_to_unichar(#first,#second) == ch + (i.e. converts ch into two surrogate characters) + !*/ + +// ---------------------------------------------------------------------------------------- + + class invalid_utf8_error : public error + { + public: + invalid_utf8_error():error(EUTF8_TO_UTF32) {} + }; + + const ustring convert_utf8_to_utf32 ( + const std::string& str + ); + /*! + ensures + - if (str is a valid UTF-8 encoded string) then + - returns a copy of str that has been converted into a + unichar string + - else + - throws invalid_utf8_error + !*/ + +// ---------------------------------------------------------------------------------------- + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + /*! + requires + - wstr is a valid UTF-16 string when sizeof(wchar_t) == 2 + - wstr is a valid UTF-32 string when sizeof(wchar_t) == 4 + ensures + - converts wstr into UTF-32 string + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_utf32_to_wstring ( + const ustring &str + ); + /*! + requires + - str is a valid UTF-32 encoded string + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_mbstring_to_wstring ( + const std::string &str + ); + /*! + requires + - str is a valid multibyte string whose encoding is same as current locale setting + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::string convert_wstring_to_mbstring ( + const std::wstring &src + ); + /*! + requires + - str is a valid wide character string string whose encoding is same as current + locale setting + ensures + - returns a multibyte encoded version of the given string + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT + > + class basic_utf8_ifstream : public std::basic_istream + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents an input file stream much like the + normal std::ifstream except that it knows how to read UTF-8 + data. So when you read characters out of this stream it will + automatically convert them from the UTF-8 multibyte encoding + into a fixed width wide character encoding. + !*/ + + public: + + basic_utf8_ifstream ( + ); + /*! + ensures + - constructs an input stream that isn't yet associated with + a file. + !*/ + + basic_utf8_ifstream ( + const char* file_name + ); + /*! + ensures + - tries to open the given file for reading by this stream + !*/ + + basic_utf8_ifstream ( + const std::string& file_name + ); + /*! + ensures + - tries to open the given file for reading by this stream + !*/ + + void open( + const std::string& file_name + ); + /*! + ensures + - tries to open the given file for reading by this stream + !*/ + + void open ( + const char* file_name + ); + /*! + ensures + - tries to open the given file for reading by this stream + !*/ + + void close ( + ); + /*! + ensures + - any file opened by this stream has been closed + !*/ + }; + + typedef basic_utf8_ifstream utf8_uifstream; + typedef basic_utf8_ifstream utf8_wifstream; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_UNICODe_ABSTRACT_H_ + + diff --git a/libs/dlib/windows_magic.h b/libs/dlib/windows_magic.h new file mode 100644 index 0000000..348bf96 --- /dev/null +++ b/libs/dlib/windows_magic.h @@ -0,0 +1,45 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_WINDOWS_MAGIc_ +#define DLIB_WINDOWS_MAGIc_ + +#include "platform.h" + +#ifdef WIN32 + +// This file contains all the magical #defines you have to setup before you +// include the windows header files. + +#ifndef NOMINMAX +#define NOMINMAX // prevent windows from messing with std::min and std::max +#endif + +// now just for good measure undefine min and max if they are defined +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +#ifdef NO_MAKEFILE +// only define this if all the cpp files are going to be sucked into the headers +// because otherwise we don't need it since everything is isolated in the sockets +// cpp file and this declaration for _WINSOCKAPI_ appears there also. +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */ +#endif +#endif + +// This is something stupid you have to do to make visual studio include the right +// stuff. I don't really know what the deal is with this. +#if _WIN32_WINNT < 0x0500 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#endif // WIN32 + +#endif // DLIB_WINDOWS_MAGIc_ + diff --git a/src/ofxKinectProjectorToolkit.cpp b/src/ofxKinectProjectorToolkit.cpp new file mode 100644 index 0000000..398deab --- /dev/null +++ b/src/ofxKinectProjectorToolkit.cpp @@ -0,0 +1,67 @@ +#include "ofxKinectProjectorToolkit.h" + + +void ofxKinectProjectorToolkit::calibrate(vector pairsKinect, + vector pairsProjector) { + int nPairs = pairsKinect.size(); + A.set_size(nPairs*2, 11); + y.set_size(nPairs*2, 1); + + for (int i=0; i > qrd(A); + x = qrd.solve(y); +} + +ofVec2f ofxKinectProjectorToolkit::getProjectedPoint(ofVec3f worldPoint) { + float a = x(0, 0)*worldPoint.x + x(1, 0)*worldPoint.y + x(2, 0)*worldPoint.z + x(3,0); + float b = x(4, 0)*worldPoint.x + x(5, 0)*worldPoint.y + x(6, 0)*worldPoint.z + x(7,0); + float c = x(8, 0)*worldPoint.x + x(9, 0)*worldPoint.y + x(10, 0)*worldPoint.z + 1; + ofVec2f projectedPoint(a/c, b/c); + return projectedPoint; +} + +void ofxKinectProjectorToolkit::loadCalibration(string path){ + xml.loadFile(path); + for (int i=0; i<11; i++) { + x(i, 0) = xml.getValue("CALIBRATION:COEFF"+ofToString(i), -1.0); + } +} + +void ofxKinectProjectorToolkit::saveCalibration(string path){ + int tagNum = xml.addTag("CALIBRATION"); + for (int i=0; i<11; i++) { + x(i, 0) = xml.setValue("CALIBRATION:COEFF"+ofToString(i), x(i, 0), tagNum); + } + xml.popTag(); + xml.saveFile(path); +} + + diff --git a/src/ofxKinectProjectorToolkit.h b/src/ofxKinectProjectorToolkit.h new file mode 100644 index 0000000..c736b23 --- /dev/null +++ b/src/ofxKinectProjectorToolkit.h @@ -0,0 +1,24 @@ +#pragma once + +#include "ofMain.h" +#include "ofxXmlSettings.h" +#include "matrix.h" +#include "matrix_qr.h" + + +class ofxKinectProjectorToolkit +{ +public: + void calibrate(vector pairsKinect, + vector pairsProjector); + ofVec2f getProjectedPoint(ofVec3f worldPoint); + vector getProjectedContour(vector *worldPoints); + void loadCalibration(string path); + void saveCalibration(string path); + +private: + dlib::matrix A; + dlib::matrix y; + dlib::matrix x; + ofxXmlSettings xml; +}; \ No newline at end of file