test_math.cpp 128 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //////////////////////////////////////////////////////////////////////////////////////////
  5. /////////////////// tests for matrix operations and math functions ///////////////////////
  6. //////////////////////////////////////////////////////////////////////////////////////////
  7. #include "test_precomp.hpp"
  8. #include <float.h>
  9. #include <math.h>
  10. #include "opencv2/core/softfloat.hpp"
  11. namespace opencv_test { namespace {
  12. /// !!! NOTE !!! These tests happily avoid overflow cases & out-of-range arguments
  13. /// so that output arrays contain neigher Inf's nor Nan's.
  14. /// Handling such cases would require special modification of check function
  15. /// (validate_test_results) => TBD.
  16. /// Also, need some logarithmic-scale generation of input data. Right now it is done (in some tests)
  17. /// by generating min/max boundaries for random data in logarimithic scale, but
  18. /// within the same test case all the input array elements are of the same order.
  19. class Core_MathTest : public cvtest::ArrayTest
  20. {
  21. public:
  22. typedef cvtest::ArrayTest Base;
  23. Core_MathTest();
  24. protected:
  25. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes,
  26. vector<vector<int> >& types);
  27. double get_success_error_level( int /*test_case_idx*/, int i, int j );
  28. bool test_nd;
  29. };
  30. Core_MathTest::Core_MathTest()
  31. {
  32. optional_mask = false;
  33. test_array[INPUT].push_back(NULL);
  34. test_array[OUTPUT].push_back(NULL);
  35. test_array[REF_OUTPUT].push_back(NULL);
  36. test_nd = false;
  37. }
  38. double Core_MathTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
  39. {
  40. return test_mat[i][j].depth() == CV_32F ? FLT_EPSILON*128 : DBL_EPSILON*1024;
  41. }
  42. void Core_MathTest::get_test_array_types_and_sizes( int test_case_idx,
  43. vector<vector<Size> >& sizes,
  44. vector<vector<int> >& types)
  45. {
  46. RNG& rng = ts->get_rng();
  47. int depth = cvtest::randInt(rng)%2 + CV_32F;
  48. int cn = cvtest::randInt(rng) % 4 + 1, type = CV_MAKETYPE(depth, cn);
  49. size_t i, j;
  50. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  51. for( i = 0; i < test_array.size(); i++ )
  52. {
  53. size_t count = test_array[i].size();
  54. for( j = 0; j < count; j++ )
  55. types[i][j] = type;
  56. }
  57. test_nd = cvtest::randInt(rng)%3 == 0;
  58. }
  59. ////////// pow /////////////
  60. class Core_PowTest : public Core_MathTest
  61. {
  62. public:
  63. typedef Core_MathTest Base;
  64. Core_PowTest();
  65. protected:
  66. void get_test_array_types_and_sizes( int test_case_idx,
  67. vector<vector<Size> >& sizes,
  68. vector<vector<int> >& types );
  69. void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
  70. void run_func();
  71. void prepare_to_validation( int test_case_idx );
  72. double get_success_error_level( int test_case_idx, int i, int j );
  73. double power;
  74. };
  75. Core_PowTest::Core_PowTest()
  76. {
  77. power = 0;
  78. }
  79. void Core_PowTest::get_test_array_types_and_sizes( int test_case_idx,
  80. vector<vector<Size> >& sizes,
  81. vector<vector<int> >& types )
  82. {
  83. RNG& rng = ts->get_rng();
  84. int depth = cvtest::randInt(rng) % (CV_64F+1);
  85. int cn = cvtest::randInt(rng) % 4 + 1;
  86. size_t i, j;
  87. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  88. depth += depth == CV_8S;
  89. if( depth < CV_32F || cvtest::randInt(rng)%8 == 0 )
  90. // integer power
  91. power = (int)(cvtest::randInt(rng)%21 - 10);
  92. else
  93. {
  94. i = cvtest::randInt(rng)%17;
  95. power = i == 16 ? 1./3 : i == 15 ? 0.5 : i == 14 ? -0.5 : cvtest::randReal(rng)*10 - 5;
  96. }
  97. for( i = 0; i < test_array.size(); i++ )
  98. {
  99. size_t count = test_array[i].size();
  100. int type = CV_MAKETYPE(depth, cn);
  101. for( j = 0; j < count; j++ )
  102. types[i][j] = type;
  103. }
  104. test_nd = cvtest::randInt(rng)%3 == 0;
  105. }
  106. double Core_PowTest::get_success_error_level( int test_case_idx, int i, int j )
  107. {
  108. int depth = test_mat[i][j].depth();
  109. if( depth < CV_32F )
  110. return power == cvRound(power) && power >= 0 ? 0 : 1;
  111. else
  112. {
  113. return depth != CV_64F ? Base::get_success_error_level( test_case_idx, i, j ) : DBL_EPSILON*1024*1.1;
  114. }
  115. }
  116. void Core_PowTest::get_minmax_bounds( int /*i*/, int /*j*/, int type, Scalar& low, Scalar& high )
  117. {
  118. double l, u = cvtest::randInt(ts->get_rng())%1000 + 1;
  119. if( power > 0 )
  120. {
  121. double mval = cvtest::getMaxVal(type);
  122. double u1 = pow(mval,1./power)*2;
  123. u = MIN(u,u1);
  124. }
  125. l = power == cvRound(power) ? -u : FLT_EPSILON;
  126. low = Scalar::all(l);
  127. high = Scalar::all(u);
  128. }
  129. void Core_PowTest::run_func()
  130. {
  131. if(!test_nd)
  132. {
  133. if( fabs(power-1./3) <= DBL_EPSILON && test_mat[INPUT][0].depth() == CV_32F )
  134. {
  135. Mat a = test_mat[INPUT][0], b = test_mat[OUTPUT][0];
  136. a = a.reshape(1);
  137. b = b.reshape(1);
  138. for( int i = 0; i < a.rows; i++ )
  139. {
  140. b.at<float>(i,0) = (float)fabs(cvCbrt(a.at<float>(i,0)));
  141. for( int j = 1; j < a.cols; j++ )
  142. b.at<float>(i,j) = (float)fabs(cv::cubeRoot(a.at<float>(i,j)));
  143. }
  144. }
  145. else
  146. cvPow( test_array[INPUT][0], test_array[OUTPUT][0], power );
  147. }
  148. else
  149. {
  150. Mat& a = test_mat[INPUT][0];
  151. Mat& b = test_mat[OUTPUT][0];
  152. if(power == 0.5)
  153. cv::sqrt(a, b);
  154. else
  155. cv::pow(a, power, b);
  156. }
  157. }
  158. inline static int ipow( int a, int power )
  159. {
  160. int b = 1;
  161. while( power > 0 )
  162. {
  163. if( power&1 )
  164. b *= a, power--;
  165. else
  166. a *= a, power >>= 1;
  167. }
  168. return b;
  169. }
  170. inline static double ipow( double a, int power )
  171. {
  172. double b = 1.;
  173. while( power > 0 )
  174. {
  175. if( power&1 )
  176. b *= a, power--;
  177. else
  178. a *= a, power >>= 1;
  179. }
  180. return b;
  181. }
  182. void Core_PowTest::prepare_to_validation( int /*test_case_idx*/ )
  183. {
  184. const Mat& a = test_mat[INPUT][0];
  185. Mat& b = test_mat[REF_OUTPUT][0];
  186. int depth = a.depth();
  187. int ncols = a.cols*a.channels();
  188. int ipower = cvRound(power), apower = abs(ipower);
  189. int i, j;
  190. for( i = 0; i < a.rows; i++ )
  191. {
  192. const uchar* a_data = a.ptr(i);
  193. uchar* b_data = b.ptr(i);
  194. switch( depth )
  195. {
  196. case CV_8U:
  197. if( ipower < 0 )
  198. for( j = 0; j < ncols; j++ )
  199. {
  200. int val = ((uchar*)a_data)[j];
  201. ((uchar*)b_data)[j] = (uchar)(val == 0 ? 255 : val == 1 ? 1 :
  202. val == 2 && ipower == -1 ? 1 : 0);
  203. }
  204. else
  205. for( j = 0; j < ncols; j++ )
  206. {
  207. int val = ((uchar*)a_data)[j];
  208. val = ipow( val, ipower );
  209. ((uchar*)b_data)[j] = saturate_cast<uchar>(val);
  210. }
  211. break;
  212. case CV_8S:
  213. if( ipower < 0 )
  214. for( j = 0; j < ncols; j++ )
  215. {
  216. int val = ((schar*)a_data)[j];
  217. ((schar*)b_data)[j] = (schar)(val == 0 ? 127 : val == 1 ? 1 :
  218. val ==-1 ? 1-2*(ipower&1) :
  219. val == 2 && ipower == -1 ? 1 : 0);
  220. }
  221. else
  222. for( j = 0; j < ncols; j++ )
  223. {
  224. int val = ((schar*)a_data)[j];
  225. val = ipow( val, ipower );
  226. ((schar*)b_data)[j] = saturate_cast<schar>(val);
  227. }
  228. break;
  229. case CV_16U:
  230. if( ipower < 0 )
  231. for( j = 0; j < ncols; j++ )
  232. {
  233. int val = ((ushort*)a_data)[j];
  234. ((ushort*)b_data)[j] = (ushort)(val == 0 ? 65535 : val == 1 ? 1 :
  235. val ==-1 ? 1-2*(ipower&1) :
  236. val == 2 && ipower == -1 ? 1 : 0);
  237. }
  238. else
  239. for( j = 0; j < ncols; j++ )
  240. {
  241. int val = ((ushort*)a_data)[j];
  242. val = ipow( val, ipower );
  243. ((ushort*)b_data)[j] = saturate_cast<ushort>(val);
  244. }
  245. break;
  246. case CV_16S:
  247. if( ipower < 0 )
  248. for( j = 0; j < ncols; j++ )
  249. {
  250. int val = ((short*)a_data)[j];
  251. ((short*)b_data)[j] = (short)(val == 0 ? 32767 : val == 1 ? 1 :
  252. val ==-1 ? 1-2*(ipower&1) :
  253. val == 2 && ipower == -1 ? 1 : 0);
  254. }
  255. else
  256. for( j = 0; j < ncols; j++ )
  257. {
  258. int val = ((short*)a_data)[j];
  259. val = ipow( val, ipower );
  260. ((short*)b_data)[j] = saturate_cast<short>(val);
  261. }
  262. break;
  263. case CV_32S:
  264. if( ipower < 0 )
  265. for( j = 0; j < ncols; j++ )
  266. {
  267. int val = ((int*)a_data)[j];
  268. ((int*)b_data)[j] = val == 0 ? INT_MAX : val == 1 ? 1 :
  269. val ==-1 ? 1-2*(ipower&1) :
  270. val == 2 && ipower == -1 ? 1 : 0;
  271. }
  272. else
  273. for( j = 0; j < ncols; j++ )
  274. {
  275. int val = ((int*)a_data)[j];
  276. val = ipow( val, ipower );
  277. ((int*)b_data)[j] = val;
  278. }
  279. break;
  280. case CV_32F:
  281. if( power != ipower )
  282. for( j = 0; j < ncols; j++ )
  283. {
  284. double val = ((float*)a_data)[j];
  285. val = pow( fabs(val), power );
  286. ((float*)b_data)[j] = (float)val;
  287. }
  288. else
  289. for( j = 0; j < ncols; j++ )
  290. {
  291. double val = ((float*)a_data)[j];
  292. if( ipower < 0 )
  293. val = 1./val;
  294. val = ipow( val, apower );
  295. ((float*)b_data)[j] = (float)val;
  296. }
  297. break;
  298. case CV_64F:
  299. if( power != ipower )
  300. for( j = 0; j < ncols; j++ )
  301. {
  302. double val = ((double*)a_data)[j];
  303. val = pow( fabs(val), power );
  304. ((double*)b_data)[j] = (double)val;
  305. }
  306. else
  307. for( j = 0; j < ncols; j++ )
  308. {
  309. double val = ((double*)a_data)[j];
  310. if( ipower < 0 )
  311. val = 1./val;
  312. val = ipow( val, apower );
  313. ((double*)b_data)[j] = (double)val;
  314. }
  315. break;
  316. }
  317. }
  318. }
  319. ///////////////////////////////////////// matrix tests ////////////////////////////////////////////
  320. class Core_MatrixTest : public cvtest::ArrayTest
  321. {
  322. public:
  323. typedef cvtest::ArrayTest Base;
  324. Core_MatrixTest( int in_count, int out_count,
  325. bool allow_int, bool scalar_output, int max_cn );
  326. protected:
  327. void get_test_array_types_and_sizes( int test_case_idx,
  328. vector<vector<Size> >& sizes,
  329. vector<vector<int> >& types );
  330. double get_success_error_level( int test_case_idx, int i, int j );
  331. bool allow_int;
  332. bool scalar_output;
  333. int max_cn;
  334. };
  335. Core_MatrixTest::Core_MatrixTest( int in_count, int out_count,
  336. bool _allow_int, bool _scalar_output, int _max_cn )
  337. : allow_int(_allow_int), scalar_output(_scalar_output), max_cn(_max_cn)
  338. {
  339. int i;
  340. for( i = 0; i < in_count; i++ )
  341. test_array[INPUT].push_back(NULL);
  342. for( i = 0; i < out_count; i++ )
  343. {
  344. test_array[OUTPUT].push_back(NULL);
  345. test_array[REF_OUTPUT].push_back(NULL);
  346. }
  347. element_wise_relative_error = false;
  348. }
  349. void Core_MatrixTest::get_test_array_types_and_sizes( int test_case_idx,
  350. vector<vector<Size> >& sizes,
  351. vector<vector<int> >& types )
  352. {
  353. RNG& rng = ts->get_rng();
  354. int depth = cvtest::randInt(rng) % (allow_int ? CV_64F+1 : 2);
  355. int cn = cvtest::randInt(rng) % max_cn + 1;
  356. size_t i, j;
  357. if( allow_int )
  358. depth += depth == CV_8S;
  359. else
  360. depth += CV_32F;
  361. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  362. for( i = 0; i < test_array.size(); i++ )
  363. {
  364. size_t count = test_array[i].size();
  365. int flag = (i == OUTPUT || i == REF_OUTPUT) && scalar_output;
  366. int type = !flag ? CV_MAKETYPE(depth, cn) : CV_64FC1;
  367. for( j = 0; j < count; j++ )
  368. {
  369. types[i][j] = type;
  370. if( flag )
  371. sizes[i][j] = Size( 4, 1 );
  372. }
  373. }
  374. }
  375. double Core_MatrixTest::get_success_error_level( int test_case_idx, int i, int j )
  376. {
  377. int input_depth = test_mat[INPUT][0].depth();
  378. double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 5e-5 : 5e-10;
  379. double output_precision = Base::get_success_error_level( test_case_idx, i, j );
  380. return MAX(input_precision, output_precision);
  381. }
  382. ///////////////// Trace /////////////////////
  383. class Core_TraceTest : public Core_MatrixTest
  384. {
  385. public:
  386. Core_TraceTest();
  387. protected:
  388. void run_func();
  389. void prepare_to_validation( int test_case_idx );
  390. };
  391. Core_TraceTest::Core_TraceTest() : Core_MatrixTest( 1, 1, true, true, 4 )
  392. {
  393. }
  394. void Core_TraceTest::run_func()
  395. {
  396. test_mat[OUTPUT][0].at<Scalar>(0,0) = cvTrace(test_array[INPUT][0]);
  397. }
  398. void Core_TraceTest::prepare_to_validation( int )
  399. {
  400. Mat& mat = test_mat[INPUT][0];
  401. int count = MIN( mat.rows, mat.cols );
  402. Mat diag(count, 1, mat.type(), mat.ptr(), mat.step + mat.elemSize());
  403. Scalar r = cvtest::mean(diag);
  404. r *= (double)count;
  405. test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = r;
  406. }
  407. ///////// dotproduct //////////
  408. class Core_DotProductTest : public Core_MatrixTest
  409. {
  410. public:
  411. Core_DotProductTest();
  412. protected:
  413. void run_func();
  414. void prepare_to_validation( int test_case_idx );
  415. };
  416. Core_DotProductTest::Core_DotProductTest() : Core_MatrixTest( 2, 1, true, true, 4 )
  417. {
  418. }
  419. void Core_DotProductTest::run_func()
  420. {
  421. test_mat[OUTPUT][0].at<Scalar>(0,0) = Scalar(cvDotProduct( test_array[INPUT][0], test_array[INPUT][1] ));
  422. }
  423. void Core_DotProductTest::prepare_to_validation( int )
  424. {
  425. test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = Scalar(cvtest::crossCorr( test_mat[INPUT][0], test_mat[INPUT][1] ));
  426. }
  427. ///////// crossproduct //////////
  428. class Core_CrossProductTest : public Core_MatrixTest
  429. {
  430. public:
  431. Core_CrossProductTest();
  432. protected:
  433. void get_test_array_types_and_sizes( int test_case_idx,
  434. vector<vector<Size> >& sizes,
  435. vector<vector<int> >& types );
  436. void run_func();
  437. void prepare_to_validation( int test_case_idx );
  438. };
  439. Core_CrossProductTest::Core_CrossProductTest() : Core_MatrixTest( 2, 1, false, false, 1 )
  440. {
  441. }
  442. void Core_CrossProductTest::get_test_array_types_and_sizes( int,
  443. vector<vector<Size> >& sizes,
  444. vector<vector<int> >& types )
  445. {
  446. RNG& rng = ts->get_rng();
  447. int depth = cvtest::randInt(rng) % 2 + CV_32F;
  448. int cn = cvtest::randInt(rng) & 1 ? 3 : 1, type = CV_MAKETYPE(depth, cn);
  449. Size sz;
  450. types[INPUT][0] = types[INPUT][1] = types[OUTPUT][0] = types[REF_OUTPUT][0] = type;
  451. if( cn == 3 )
  452. sz = Size(1,1);
  453. else if( cvtest::randInt(rng) & 1 )
  454. sz = Size(3,1);
  455. else
  456. sz = Size(1,3);
  457. sizes[INPUT][0] = sizes[INPUT][1] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sz;
  458. }
  459. void Core_CrossProductTest::run_func()
  460. {
  461. cvCrossProduct( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0] );
  462. }
  463. void Core_CrossProductTest::prepare_to_validation( int )
  464. {
  465. cv::Scalar a, b, c;
  466. if( test_mat[INPUT][0].rows > 1 )
  467. {
  468. a.val[0] = cvGetReal2D( test_array[INPUT][0], 0, 0 );
  469. a.val[1] = cvGetReal2D( test_array[INPUT][0], 1, 0 );
  470. a.val[2] = cvGetReal2D( test_array[INPUT][0], 2, 0 );
  471. b.val[0] = cvGetReal2D( test_array[INPUT][1], 0, 0 );
  472. b.val[1] = cvGetReal2D( test_array[INPUT][1], 1, 0 );
  473. b.val[2] = cvGetReal2D( test_array[INPUT][1], 2, 0 );
  474. }
  475. else if( test_mat[INPUT][0].cols > 1 )
  476. {
  477. a.val[0] = cvGetReal1D( test_array[INPUT][0], 0 );
  478. a.val[1] = cvGetReal1D( test_array[INPUT][0], 1 );
  479. a.val[2] = cvGetReal1D( test_array[INPUT][0], 2 );
  480. b.val[0] = cvGetReal1D( test_array[INPUT][1], 0 );
  481. b.val[1] = cvGetReal1D( test_array[INPUT][1], 1 );
  482. b.val[2] = cvGetReal1D( test_array[INPUT][1], 2 );
  483. }
  484. else
  485. {
  486. a = cvGet1D( test_array[INPUT][0], 0 );
  487. b = cvGet1D( test_array[INPUT][1], 0 );
  488. }
  489. c.val[2] = a.val[0]*b.val[1] - a.val[1]*b.val[0];
  490. c.val[1] = -a.val[0]*b.val[2] + a.val[2]*b.val[0];
  491. c.val[0] = a.val[1]*b.val[2] - a.val[2]*b.val[1];
  492. if( test_mat[REF_OUTPUT][0].rows > 1 )
  493. {
  494. cvSetReal2D( test_array[REF_OUTPUT][0], 0, 0, c.val[0] );
  495. cvSetReal2D( test_array[REF_OUTPUT][0], 1, 0, c.val[1] );
  496. cvSetReal2D( test_array[REF_OUTPUT][0], 2, 0, c.val[2] );
  497. }
  498. else if( test_mat[REF_OUTPUT][0].cols > 1 )
  499. {
  500. cvSetReal1D( test_array[REF_OUTPUT][0], 0, c.val[0] );
  501. cvSetReal1D( test_array[REF_OUTPUT][0], 1, c.val[1] );
  502. cvSetReal1D( test_array[REF_OUTPUT][0], 2, c.val[2] );
  503. }
  504. else
  505. {
  506. cvSet1D( test_array[REF_OUTPUT][0], 0, cvScalar(c) );
  507. }
  508. }
  509. ///////////////// gemm /////////////////////
  510. class Core_GEMMTest : public Core_MatrixTest
  511. {
  512. public:
  513. typedef Core_MatrixTest Base;
  514. Core_GEMMTest();
  515. protected:
  516. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  517. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  518. int prepare_test_case( int test_case_idx );
  519. void run_func();
  520. void prepare_to_validation( int test_case_idx );
  521. int tabc_flag;
  522. double alpha, beta;
  523. };
  524. Core_GEMMTest::Core_GEMMTest() : Core_MatrixTest( 5, 1, false, false, 2 )
  525. {
  526. test_case_count = 100;
  527. max_log_array_size = 10;
  528. tabc_flag = 0;
  529. alpha = beta = 0;
  530. }
  531. void Core_GEMMTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  532. {
  533. RNG& rng = ts->get_rng();
  534. Size sizeA;
  535. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  536. sizeA = sizes[INPUT][0];
  537. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  538. sizes[INPUT][0] = sizeA;
  539. sizes[INPUT][2] = sizes[INPUT][3] = Size(1,1);
  540. types[INPUT][2] = types[INPUT][3] &= ~CV_MAT_CN_MASK;
  541. tabc_flag = cvtest::randInt(rng) & 7;
  542. switch( tabc_flag & (CV_GEMM_A_T|CV_GEMM_B_T) )
  543. {
  544. case 0:
  545. sizes[INPUT][1].height = sizes[INPUT][0].width;
  546. sizes[OUTPUT][0].height = sizes[INPUT][0].height;
  547. sizes[OUTPUT][0].width = sizes[INPUT][1].width;
  548. break;
  549. case CV_GEMM_B_T:
  550. sizes[INPUT][1].width = sizes[INPUT][0].width;
  551. sizes[OUTPUT][0].height = sizes[INPUT][0].height;
  552. sizes[OUTPUT][0].width = sizes[INPUT][1].height;
  553. break;
  554. case CV_GEMM_A_T:
  555. sizes[INPUT][1].height = sizes[INPUT][0].height;
  556. sizes[OUTPUT][0].height = sizes[INPUT][0].width;
  557. sizes[OUTPUT][0].width = sizes[INPUT][1].width;
  558. break;
  559. case CV_GEMM_A_T | CV_GEMM_B_T:
  560. sizes[INPUT][1].width = sizes[INPUT][0].height;
  561. sizes[OUTPUT][0].height = sizes[INPUT][0].width;
  562. sizes[OUTPUT][0].width = sizes[INPUT][1].height;
  563. break;
  564. }
  565. sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
  566. if( cvtest::randInt(rng) & 1 )
  567. sizes[INPUT][4] = Size(0,0);
  568. else if( !(tabc_flag & CV_GEMM_C_T) )
  569. sizes[INPUT][4] = sizes[OUTPUT][0];
  570. else
  571. {
  572. sizes[INPUT][4].width = sizes[OUTPUT][0].height;
  573. sizes[INPUT][4].height = sizes[OUTPUT][0].width;
  574. }
  575. }
  576. int Core_GEMMTest::prepare_test_case( int test_case_idx )
  577. {
  578. int code = Base::prepare_test_case( test_case_idx );
  579. if( code > 0 )
  580. {
  581. alpha = cvGetReal2D( test_array[INPUT][2], 0, 0 );
  582. beta = cvGetReal2D( test_array[INPUT][3], 0, 0 );
  583. }
  584. return code;
  585. }
  586. void Core_GEMMTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  587. {
  588. low = Scalar::all(-10.);
  589. high = Scalar::all(10.);
  590. }
  591. void Core_GEMMTest::run_func()
  592. {
  593. cvGEMM( test_array[INPUT][0], test_array[INPUT][1], alpha,
  594. test_array[INPUT][4], beta, test_array[OUTPUT][0], tabc_flag );
  595. }
  596. void Core_GEMMTest::prepare_to_validation( int )
  597. {
  598. cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][1], alpha,
  599. test_array[INPUT][4] ? test_mat[INPUT][4] : Mat(),
  600. beta, test_mat[REF_OUTPUT][0], tabc_flag );
  601. }
  602. ///////////////// multransposed /////////////////////
  603. class Core_MulTransposedTest : public Core_MatrixTest
  604. {
  605. public:
  606. Core_MulTransposedTest();
  607. protected:
  608. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  609. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  610. void run_func();
  611. void prepare_to_validation( int test_case_idx );
  612. int order;
  613. };
  614. Core_MulTransposedTest::Core_MulTransposedTest() : Core_MatrixTest( 2, 1, false, false, 1 )
  615. {
  616. test_case_count = 100;
  617. order = 0;
  618. test_array[TEMP].push_back(NULL);
  619. }
  620. void Core_MulTransposedTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  621. {
  622. RNG& rng = ts->get_rng();
  623. int bits = cvtest::randInt(rng);
  624. int src_type = cvtest::randInt(rng) % 5;
  625. int dst_type = cvtest::randInt(rng) % 2;
  626. src_type = src_type == 0 ? CV_8U : src_type == 1 ? CV_16U : src_type == 2 ? CV_16S :
  627. src_type == 3 ? CV_32F : CV_64F;
  628. dst_type = dst_type == 0 ? CV_32F : CV_64F;
  629. dst_type = MAX( dst_type, src_type );
  630. Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  631. if( bits & 1 )
  632. sizes[INPUT][1] = Size(0,0);
  633. else
  634. {
  635. sizes[INPUT][1] = sizes[INPUT][0];
  636. if( bits & 2 )
  637. sizes[INPUT][1].height = 1;
  638. if( bits & 4 )
  639. sizes[INPUT][1].width = 1;
  640. }
  641. sizes[TEMP][0] = sizes[INPUT][0];
  642. types[INPUT][0] = src_type;
  643. types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][1] = types[TEMP][0] = dst_type;
  644. order = (bits & 8) != 0;
  645. sizes[OUTPUT][0].width = sizes[OUTPUT][0].height = order == 0 ?
  646. sizes[INPUT][0].height : sizes[INPUT][0].width;
  647. sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
  648. }
  649. void Core_MulTransposedTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  650. {
  651. low = cvScalarAll(-10.);
  652. high = cvScalarAll(10.);
  653. }
  654. void Core_MulTransposedTest::run_func()
  655. {
  656. cvMulTransposed( test_array[INPUT][0], test_array[OUTPUT][0],
  657. order, test_array[INPUT][1] );
  658. }
  659. void Core_MulTransposedTest::prepare_to_validation( int )
  660. {
  661. const Mat& src = test_mat[INPUT][0];
  662. Mat delta = test_mat[INPUT][1];
  663. Mat& temp = test_mat[TEMP][0];
  664. if( !delta.empty() )
  665. {
  666. if( delta.rows < src.rows || delta.cols < src.cols )
  667. {
  668. cv::repeat( delta, src.rows/delta.rows, src.cols/delta.cols, temp);
  669. delta = temp;
  670. }
  671. cvtest::add( src, 1, delta, -1, Scalar::all(0), temp, temp.type());
  672. }
  673. else
  674. src.convertTo(temp, temp.type());
  675. cvtest::gemm( temp, temp, 1., Mat(), 0, test_mat[REF_OUTPUT][0], order == 0 ? GEMM_2_T : GEMM_1_T );
  676. }
  677. ///////////////// Transform /////////////////////
  678. class Core_TransformTest : public Core_MatrixTest
  679. {
  680. public:
  681. typedef Core_MatrixTest Base;
  682. Core_TransformTest();
  683. protected:
  684. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  685. double get_success_error_level( int test_case_idx, int i, int j );
  686. int prepare_test_case( int test_case_idx );
  687. void run_func();
  688. void prepare_to_validation( int test_case_idx );
  689. double scale;
  690. bool diagMtx;
  691. };
  692. Core_TransformTest::Core_TransformTest() : Core_MatrixTest( 3, 1, true, false, 4 )
  693. {
  694. scale = 1;
  695. diagMtx = false;
  696. }
  697. void Core_TransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  698. {
  699. RNG& rng = ts->get_rng();
  700. int bits = cvtest::randInt(rng);
  701. int depth, dst_cn, mat_cols, mattype;
  702. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  703. mat_cols = CV_MAT_CN(types[INPUT][0]);
  704. depth = CV_MAT_DEPTH(types[INPUT][0]);
  705. dst_cn = cvtest::randInt(rng) % 4 + 1;
  706. types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
  707. mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
  708. types[INPUT][1] = mattype;
  709. types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
  710. scale = 1./((cvtest::randInt(rng)%4)*50+1);
  711. if( bits & 2 )
  712. {
  713. sizes[INPUT][2] = Size(0,0);
  714. mat_cols += (bits & 4) != 0;
  715. }
  716. else if( bits & 4 )
  717. sizes[INPUT][2] = Size(1,1);
  718. else
  719. {
  720. if( bits & 8 )
  721. sizes[INPUT][2] = Size(dst_cn,1);
  722. else
  723. sizes[INPUT][2] = Size(1,dst_cn);
  724. types[INPUT][2] &= ~CV_MAT_CN_MASK;
  725. }
  726. diagMtx = (bits & 16) != 0;
  727. sizes[INPUT][1] = Size(mat_cols,dst_cn);
  728. }
  729. int Core_TransformTest::prepare_test_case( int test_case_idx )
  730. {
  731. int code = Base::prepare_test_case( test_case_idx );
  732. if( code > 0 )
  733. {
  734. Mat& m = test_mat[INPUT][1];
  735. cvtest::add(m, scale, m, 0, Scalar::all(0), m, m.type() );
  736. if(diagMtx)
  737. {
  738. Mat mask = Mat::eye(m.rows, m.cols, CV_8U)*255;
  739. mask = ~mask;
  740. m.setTo(Scalar::all(0), mask);
  741. }
  742. }
  743. return code;
  744. }
  745. double Core_TransformTest::get_success_error_level( int test_case_idx, int i, int j )
  746. {
  747. int depth = test_mat[INPUT][0].depth();
  748. return depth <= CV_8S ? 1 : depth <= CV_32S ? 9 : Base::get_success_error_level( test_case_idx, i, j );
  749. }
  750. void Core_TransformTest::run_func()
  751. {
  752. CvMat _m = cvMat(test_mat[INPUT][1]), _shift = cvMat(test_mat[INPUT][2]);
  753. cvTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m, _shift.data.ptr ? &_shift : 0);
  754. }
  755. void Core_TransformTest::prepare_to_validation( int )
  756. {
  757. Mat transmat = test_mat[INPUT][1];
  758. Mat shift = test_mat[INPUT][2];
  759. cvtest::transform( test_mat[INPUT][0], test_mat[REF_OUTPUT][0], transmat, shift );
  760. }
  761. class Core_TransformLargeTest : public Core_TransformTest
  762. {
  763. public:
  764. typedef Core_MatrixTest Base;
  765. protected:
  766. void get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types);
  767. };
  768. void Core_TransformLargeTest::get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types)
  769. {
  770. RNG& rng = ts->get_rng();
  771. int bits = cvtest::randInt(rng);
  772. int depth, dst_cn, mat_cols, mattype;
  773. Base::get_test_array_types_and_sizes(test_case_idx, sizes, types);
  774. for (unsigned int j = 0; j < sizes.size(); j++)
  775. {
  776. for (unsigned int i = 0; i < sizes[j].size(); i++)
  777. {
  778. sizes[j][i].width *= 4;
  779. }
  780. }
  781. mat_cols = CV_MAT_CN(types[INPUT][0]);
  782. depth = CV_MAT_DEPTH(types[INPUT][0]);
  783. dst_cn = cvtest::randInt(rng) % 4 + 1;
  784. types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, dst_cn);
  785. mattype = depth < CV_32S ? CV_32F : depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
  786. types[INPUT][1] = mattype;
  787. types[INPUT][2] = CV_MAKETYPE(mattype, dst_cn);
  788. scale = 1. / ((cvtest::randInt(rng) % 4) * 50 + 1);
  789. if (bits & 2)
  790. {
  791. sizes[INPUT][2] = Size(0, 0);
  792. mat_cols += (bits & 4) != 0;
  793. }
  794. else if (bits & 4)
  795. sizes[INPUT][2] = Size(1, 1);
  796. else
  797. {
  798. if (bits & 8)
  799. sizes[INPUT][2] = Size(dst_cn, 1);
  800. else
  801. sizes[INPUT][2] = Size(1, dst_cn);
  802. types[INPUT][2] &= ~CV_MAT_CN_MASK;
  803. }
  804. diagMtx = (bits & 16) != 0;
  805. sizes[INPUT][1] = Size(mat_cols, dst_cn);
  806. }
  807. ///////////////// PerspectiveTransform /////////////////////
  808. class Core_PerspectiveTransformTest : public Core_MatrixTest
  809. {
  810. public:
  811. Core_PerspectiveTransformTest();
  812. protected:
  813. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  814. double get_success_error_level( int test_case_idx, int i, int j );
  815. void run_func();
  816. void prepare_to_validation( int test_case_idx );
  817. };
  818. Core_PerspectiveTransformTest::Core_PerspectiveTransformTest() : Core_MatrixTest( 2, 1, false, false, 2 )
  819. {
  820. }
  821. void Core_PerspectiveTransformTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  822. {
  823. RNG& rng = ts->get_rng();
  824. int bits = cvtest::randInt(rng);
  825. int depth, cn, mattype;
  826. Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  827. cn = CV_MAT_CN(types[INPUT][0]) + 1;
  828. depth = CV_MAT_DEPTH(types[INPUT][0]);
  829. types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth, cn);
  830. mattype = depth == CV_64F ? CV_64F : bits & 1 ? CV_32F : CV_64F;
  831. types[INPUT][1] = mattype;
  832. sizes[INPUT][1] = Size(cn + 1, cn + 1);
  833. }
  834. double Core_PerspectiveTransformTest::get_success_error_level( int test_case_idx, int i, int j )
  835. {
  836. int depth = test_mat[INPUT][0].depth();
  837. return depth == CV_32F ? 1e-4 : depth == CV_64F ? 1e-8 :
  838. Core_MatrixTest::get_success_error_level(test_case_idx, i, j);
  839. }
  840. void Core_PerspectiveTransformTest::run_func()
  841. {
  842. CvMat _m = cvMat(test_mat[INPUT][1]);
  843. cvPerspectiveTransform( test_array[INPUT][0], test_array[OUTPUT][0], &_m );
  844. }
  845. static void cvTsPerspectiveTransform( const CvArr* _src, CvArr* _dst, const CvMat* transmat )
  846. {
  847. int i, j, cols;
  848. int cn, depth, mat_depth;
  849. CvMat astub, bstub, *a, *b;
  850. double mat[16] = {0.0};
  851. a = cvGetMat( _src, &astub, 0, 0 );
  852. b = cvGetMat( _dst, &bstub, 0, 0 );
  853. cn = CV_MAT_CN(a->type);
  854. depth = CV_MAT_DEPTH(a->type);
  855. mat_depth = CV_MAT_DEPTH(transmat->type);
  856. cols = transmat->cols;
  857. // prepare cn x (cn + 1) transform matrix
  858. if( mat_depth == CV_32F )
  859. {
  860. for( i = 0; i < transmat->rows; i++ )
  861. for( j = 0; j < cols; j++ )
  862. mat[i*cols + j] = ((float*)(transmat->data.ptr + transmat->step*i))[j];
  863. }
  864. else
  865. {
  866. CV_Assert( mat_depth == CV_64F );
  867. for( i = 0; i < transmat->rows; i++ )
  868. for( j = 0; j < cols; j++ )
  869. mat[i*cols + j] = ((double*)(transmat->data.ptr + transmat->step*i))[j];
  870. }
  871. // transform data
  872. cols = a->cols * cn;
  873. vector<double> buf(cols);
  874. for( i = 0; i < a->rows; i++ )
  875. {
  876. uchar* src = a->data.ptr + i*a->step;
  877. uchar* dst = b->data.ptr + i*b->step;
  878. switch( depth )
  879. {
  880. case CV_32F:
  881. for( j = 0; j < cols; j++ )
  882. buf[j] = ((float*)src)[j];
  883. break;
  884. case CV_64F:
  885. for( j = 0; j < cols; j++ )
  886. buf[j] = ((double*)src)[j];
  887. break;
  888. default:
  889. CV_Assert(0);
  890. }
  891. switch( cn )
  892. {
  893. case 2:
  894. for( j = 0; j < cols; j += 2 )
  895. {
  896. double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + mat[2];
  897. double t1 = buf[j]*mat[3] + buf[j+1]*mat[4] + mat[5];
  898. double w = buf[j]*mat[6] + buf[j+1]*mat[7] + mat[8];
  899. w = w ? 1./w : 0;
  900. buf[j] = t0*w;
  901. buf[j+1] = t1*w;
  902. }
  903. break;
  904. case 3:
  905. for( j = 0; j < cols; j += 3 )
  906. {
  907. double t0 = buf[j]*mat[0] + buf[j+1]*mat[1] + buf[j+2]*mat[2] + mat[3];
  908. double t1 = buf[j]*mat[4] + buf[j+1]*mat[5] + buf[j+2]*mat[6] + mat[7];
  909. double t2 = buf[j]*mat[8] + buf[j+1]*mat[9] + buf[j+2]*mat[10] + mat[11];
  910. double w = buf[j]*mat[12] + buf[j+1]*mat[13] + buf[j+2]*mat[14] + mat[15];
  911. w = w ? 1./w : 0;
  912. buf[j] = t0*w;
  913. buf[j+1] = t1*w;
  914. buf[j+2] = t2*w;
  915. }
  916. break;
  917. default:
  918. CV_Assert(0);
  919. }
  920. switch( depth )
  921. {
  922. case CV_32F:
  923. for( j = 0; j < cols; j++ )
  924. ((float*)dst)[j] = (float)buf[j];
  925. break;
  926. case CV_64F:
  927. for( j = 0; j < cols; j++ )
  928. ((double*)dst)[j] = buf[j];
  929. break;
  930. default:
  931. CV_Assert(0);
  932. }
  933. }
  934. }
  935. void Core_PerspectiveTransformTest::prepare_to_validation( int )
  936. {
  937. CvMat transmat = cvMat(test_mat[INPUT][1]);
  938. cvTsPerspectiveTransform( test_array[INPUT][0], test_array[REF_OUTPUT][0], &transmat );
  939. }
  940. ///////////////// Mahalanobis /////////////////////
  941. class Core_MahalanobisTest : public Core_MatrixTest
  942. {
  943. public:
  944. typedef Core_MatrixTest Base;
  945. Core_MahalanobisTest();
  946. protected:
  947. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  948. int prepare_test_case( int test_case_idx );
  949. void run_func();
  950. void prepare_to_validation( int test_case_idx );
  951. };
  952. Core_MahalanobisTest::Core_MahalanobisTest() : Core_MatrixTest( 3, 1, false, true, 1 )
  953. {
  954. test_case_count = 100;
  955. test_array[TEMP].push_back(NULL);
  956. test_array[TEMP].push_back(NULL);
  957. test_array[TEMP].push_back(NULL);
  958. }
  959. void Core_MahalanobisTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  960. {
  961. RNG& rng = ts->get_rng();
  962. Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  963. if( cvtest::randInt(rng) & 1 )
  964. sizes[INPUT][0].width = sizes[INPUT][1].width = 1;
  965. else
  966. sizes[INPUT][0].height = sizes[INPUT][1].height = 1;
  967. sizes[TEMP][0] = sizes[TEMP][1] = sizes[INPUT][0];
  968. sizes[INPUT][2].width = sizes[INPUT][2].height = sizes[INPUT][0].width + sizes[INPUT][0].height - 1;
  969. sizes[TEMP][2] = sizes[INPUT][2];
  970. types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
  971. }
  972. int Core_MahalanobisTest::prepare_test_case( int test_case_idx )
  973. {
  974. int code = Base::prepare_test_case( test_case_idx );
  975. if( code > 0 )
  976. {
  977. // make sure that the inverted "covariation" matrix is symmetrix and positively defined.
  978. cvtest::gemm( test_mat[INPUT][2], test_mat[INPUT][2], 1., Mat(), 0., test_mat[TEMP][2], GEMM_2_T );
  979. cvtest::copy( test_mat[TEMP][2], test_mat[INPUT][2] );
  980. }
  981. return code;
  982. }
  983. void Core_MahalanobisTest::run_func()
  984. {
  985. test_mat[OUTPUT][0].at<Scalar>(0,0) =
  986. cvRealScalar(cvMahalanobis(test_array[INPUT][0], test_array[INPUT][1], test_array[INPUT][2]));
  987. }
  988. void Core_MahalanobisTest::prepare_to_validation( int )
  989. {
  990. cvtest::add( test_mat[INPUT][0], 1., test_mat[INPUT][1], -1.,
  991. Scalar::all(0), test_mat[TEMP][0], test_mat[TEMP][0].type() );
  992. if( test_mat[INPUT][0].rows == 1 )
  993. cvtest::gemm( test_mat[TEMP][0], test_mat[INPUT][2], 1.,
  994. Mat(), 0., test_mat[TEMP][1], 0 );
  995. else
  996. cvtest::gemm( test_mat[INPUT][2], test_mat[TEMP][0], 1.,
  997. Mat(), 0., test_mat[TEMP][1], 0 );
  998. test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(sqrt(cvtest::crossCorr(test_mat[TEMP][0], test_mat[TEMP][1])));
  999. }
  1000. ///////////////// covarmatrix /////////////////////
  1001. class Core_CovarMatrixTest : public Core_MatrixTest
  1002. {
  1003. public:
  1004. Core_CovarMatrixTest();
  1005. protected:
  1006. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1007. int prepare_test_case( int test_case_idx );
  1008. void run_func();
  1009. void prepare_to_validation( int test_case_idx );
  1010. vector<void*> temp_hdrs;
  1011. vector<uchar> hdr_data;
  1012. int flags, t_flag, len, count;
  1013. bool are_images;
  1014. };
  1015. Core_CovarMatrixTest::Core_CovarMatrixTest() : Core_MatrixTest( 1, 1, true, false, 1 ),
  1016. flags(0), t_flag(0), len(0), count(0), are_images(false)
  1017. {
  1018. test_case_count = 100;
  1019. test_array[INPUT_OUTPUT].push_back(NULL);
  1020. test_array[REF_INPUT_OUTPUT].push_back(NULL);
  1021. test_array[TEMP].push_back(NULL);
  1022. test_array[TEMP].push_back(NULL);
  1023. }
  1024. void Core_CovarMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  1025. {
  1026. RNG& rng = ts->get_rng();
  1027. int bits = cvtest::randInt(rng);
  1028. int i, single_matrix;
  1029. Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1030. flags = bits & (CV_COVAR_NORMAL | CV_COVAR_USE_AVG | CV_COVAR_SCALE | CV_COVAR_ROWS );
  1031. single_matrix = flags & CV_COVAR_ROWS;
  1032. t_flag = (bits & 256) != 0;
  1033. const int min_count = 2;
  1034. if( !t_flag )
  1035. {
  1036. len = sizes[INPUT][0].width;
  1037. count = sizes[INPUT][0].height;
  1038. count = MAX(count, min_count);
  1039. sizes[INPUT][0] = Size(len, count);
  1040. }
  1041. else
  1042. {
  1043. len = sizes[INPUT][0].height;
  1044. count = sizes[INPUT][0].width;
  1045. count = MAX(count, min_count);
  1046. sizes[INPUT][0] = Size(count, len);
  1047. }
  1048. if( single_matrix && t_flag )
  1049. flags = (flags & ~CV_COVAR_ROWS) | CV_COVAR_COLS;
  1050. if( CV_MAT_DEPTH(types[INPUT][0]) == CV_32S )
  1051. types[INPUT][0] = (types[INPUT][0] & ~CV_MAT_DEPTH_MASK) | CV_32F;
  1052. sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = flags & CV_COVAR_NORMAL ? Size(len,len) : Size(count,count);
  1053. sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = !t_flag ? Size(len,1) : Size(1,len);
  1054. sizes[TEMP][0] = sizes[INPUT][0];
  1055. types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] =
  1056. types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0] =
  1057. CV_MAT_DEPTH(types[INPUT][0]) == CV_64F || (bits & 512) ? CV_64F : CV_32F;
  1058. are_images = (bits & 1024) != 0;
  1059. for( i = 0; i < (single_matrix ? 1 : count); i++ )
  1060. temp_hdrs.push_back(NULL);
  1061. }
  1062. int Core_CovarMatrixTest::prepare_test_case( int test_case_idx )
  1063. {
  1064. int code = Core_MatrixTest::prepare_test_case( test_case_idx );
  1065. if( code > 0 )
  1066. {
  1067. int i;
  1068. int single_matrix = flags & (CV_COVAR_ROWS|CV_COVAR_COLS);
  1069. int hdr_size = are_images ? sizeof(IplImage) : sizeof(CvMat);
  1070. hdr_data.resize(count*hdr_size);
  1071. uchar* _hdr_data = &hdr_data[0];
  1072. if( single_matrix )
  1073. {
  1074. if( !are_images )
  1075. *((CvMat*)_hdr_data) = cvMat(test_mat[INPUT][0]);
  1076. else
  1077. *((IplImage*)_hdr_data) = cvIplImage(test_mat[INPUT][0]);
  1078. temp_hdrs[0] = _hdr_data;
  1079. }
  1080. else
  1081. for( i = 0; i < count; i++ )
  1082. {
  1083. Mat part;
  1084. void* ptr = _hdr_data + i*hdr_size;
  1085. if( !t_flag )
  1086. part = test_mat[INPUT][0].row(i);
  1087. else
  1088. part = test_mat[INPUT][0].col(i);
  1089. if( !are_images )
  1090. *((CvMat*)ptr) = cvMat(part);
  1091. else
  1092. *((IplImage*)ptr) = cvIplImage(part);
  1093. temp_hdrs[i] = ptr;
  1094. }
  1095. }
  1096. return code;
  1097. }
  1098. void Core_CovarMatrixTest::run_func()
  1099. {
  1100. cvCalcCovarMatrix( (const void**)&temp_hdrs[0], count,
  1101. test_array[OUTPUT][0], test_array[INPUT_OUTPUT][0], flags );
  1102. }
  1103. void Core_CovarMatrixTest::prepare_to_validation( int )
  1104. {
  1105. Mat& avg = test_mat[REF_INPUT_OUTPUT][0];
  1106. double scale = 1.;
  1107. if( !(flags & CV_COVAR_USE_AVG) )
  1108. {
  1109. Mat hdrs0 = cvarrToMat(temp_hdrs[0]);
  1110. int i;
  1111. avg = Scalar::all(0);
  1112. for( i = 0; i < count; i++ )
  1113. {
  1114. Mat vec;
  1115. if( flags & CV_COVAR_ROWS )
  1116. vec = hdrs0.row(i);
  1117. else if( flags & CV_COVAR_COLS )
  1118. vec = hdrs0.col(i);
  1119. else
  1120. vec = cvarrToMat(temp_hdrs[i]);
  1121. cvtest::add(avg, 1, vec, 1, Scalar::all(0), avg, avg.type());
  1122. }
  1123. cvtest::add(avg, 1./count, avg, 0., Scalar::all(0), avg, avg.type());
  1124. }
  1125. if( flags & CV_COVAR_SCALE )
  1126. {
  1127. scale = 1./count;
  1128. }
  1129. Mat& temp0 = test_mat[TEMP][0];
  1130. cv::repeat( avg, temp0.rows/avg.rows, temp0.cols/avg.cols, temp0 );
  1131. cvtest::add( test_mat[INPUT][0], 1, temp0, -1, Scalar::all(0), temp0, temp0.type());
  1132. cvtest::gemm( temp0, temp0, scale, Mat(), 0., test_mat[REF_OUTPUT][0],
  1133. t_flag ^ ((flags & CV_COVAR_NORMAL) != 0) ? CV_GEMM_A_T : CV_GEMM_B_T );
  1134. temp_hdrs.clear();
  1135. }
  1136. static void cvTsFloodWithZeros( Mat& mat, RNG& rng )
  1137. {
  1138. int k, total = mat.rows*mat.cols, type = mat.type();
  1139. int zero_total = cvtest::randInt(rng) % total;
  1140. CV_Assert( type == CV_32FC1 || type == CV_64FC1 );
  1141. for( k = 0; k < zero_total; k++ )
  1142. {
  1143. int i = cvtest::randInt(rng) % mat.rows;
  1144. int j = cvtest::randInt(rng) % mat.cols;
  1145. if( type == CV_32FC1 )
  1146. mat.at<float>(i,j) = 0.f;
  1147. else
  1148. mat.at<double>(i,j) = 0.;
  1149. }
  1150. }
  1151. ///////////////// determinant /////////////////////
  1152. class Core_DetTest : public Core_MatrixTest
  1153. {
  1154. public:
  1155. typedef Core_MatrixTest Base;
  1156. Core_DetTest();
  1157. protected:
  1158. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1159. double get_success_error_level( int test_case_idx, int i, int j );
  1160. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  1161. int prepare_test_case( int test_case_idx );
  1162. void run_func();
  1163. void prepare_to_validation( int test_case_idx );
  1164. };
  1165. Core_DetTest::Core_DetTest() : Core_MatrixTest( 1, 1, false, true, 1 )
  1166. {
  1167. test_case_count = 100;
  1168. max_log_array_size = 7;
  1169. test_array[TEMP].push_back(NULL);
  1170. }
  1171. void Core_DetTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  1172. {
  1173. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1174. sizes[INPUT][0].width = sizes[INPUT][0].height;
  1175. sizes[TEMP][0] = sizes[INPUT][0];
  1176. types[TEMP][0] = CV_64FC1;
  1177. }
  1178. void Core_DetTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  1179. {
  1180. low = cvScalarAll(-2.);
  1181. high = cvScalarAll(2.);
  1182. }
  1183. double Core_DetTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
  1184. {
  1185. return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-2 : 1e-5;
  1186. }
  1187. int Core_DetTest::prepare_test_case( int test_case_idx )
  1188. {
  1189. int code = Core_MatrixTest::prepare_test_case( test_case_idx );
  1190. if( code > 0 )
  1191. cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
  1192. return code;
  1193. }
  1194. void Core_DetTest::run_func()
  1195. {
  1196. test_mat[OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvDet(test_array[INPUT][0]));
  1197. }
  1198. // LU method that chooses the optimal in a column pivot element
  1199. static double cvTsLU( CvMat* a, CvMat* b=NULL, CvMat* x=NULL, int* rank=0 )
  1200. {
  1201. int i, j, k, N = a->rows, N1 = a->cols, Nm = MIN(N, N1), step = a->step/sizeof(double);
  1202. int M = b ? b->cols : 0, b_step = b ? b->step/sizeof(double) : 0;
  1203. int x_step = x ? x->step/sizeof(double) : 0;
  1204. double *a0 = a->data.db, *b0 = b ? b->data.db : 0;
  1205. double *x0 = x ? x->data.db : 0;
  1206. double t, det = 1.;
  1207. CV_Assert( CV_MAT_TYPE(a->type) == CV_64FC1 &&
  1208. (!b || CV_ARE_TYPES_EQ(a,b)) && (!x || CV_ARE_TYPES_EQ(a,x)));
  1209. for( i = 0; i < Nm; i++ )
  1210. {
  1211. double max_val = fabs(a0[i*step + i]);
  1212. double *a1, *a2, *b1 = 0, *b2 = 0;
  1213. k = i;
  1214. for( j = i+1; j < N; j++ )
  1215. {
  1216. t = fabs(a0[j*step + i]);
  1217. if( max_val < t )
  1218. {
  1219. max_val = t;
  1220. k = j;
  1221. }
  1222. }
  1223. if( k != i )
  1224. {
  1225. for( j = i; j < N1; j++ )
  1226. CV_SWAP( a0[i*step + j], a0[k*step + j], t );
  1227. for( j = 0; j < M; j++ )
  1228. CV_SWAP( b0[i*b_step + j], b0[k*b_step + j], t );
  1229. det = -det;
  1230. }
  1231. if( max_val == 0 )
  1232. {
  1233. if( rank )
  1234. *rank = i;
  1235. return 0.;
  1236. }
  1237. a1 = a0 + i*step;
  1238. a2 = a1 + step;
  1239. b1 = b0 + i*b_step;
  1240. b2 = b1 + b_step;
  1241. for( j = i+1; j < N; j++, a2 += step, b2 += b_step )
  1242. {
  1243. t = a2[i]/a1[i];
  1244. for( k = i+1; k < N1; k++ )
  1245. a2[k] -= t*a1[k];
  1246. for( k = 0; k < M; k++ )
  1247. b2[k] -= t*b1[k];
  1248. }
  1249. det *= a1[i];
  1250. }
  1251. if( x )
  1252. {
  1253. CV_Assert( b );
  1254. for( i = N-1; i >= 0; i-- )
  1255. {
  1256. double* a1 = a0 + i*step;
  1257. double* b1 = b0 + i*b_step;
  1258. for( j = 0; j < M; j++ )
  1259. {
  1260. t = b1[j];
  1261. for( k = i+1; k < N1; k++ )
  1262. t -= a1[k]*x0[k*x_step + j];
  1263. x0[i*x_step + j] = t/a1[i];
  1264. }
  1265. }
  1266. }
  1267. if( rank )
  1268. *rank = i;
  1269. return det;
  1270. }
  1271. void Core_DetTest::prepare_to_validation( int )
  1272. {
  1273. test_mat[INPUT][0].convertTo(test_mat[TEMP][0], test_mat[TEMP][0].type());
  1274. CvMat temp0 = cvMat(test_mat[TEMP][0]);
  1275. test_mat[REF_OUTPUT][0].at<Scalar>(0,0) = cvRealScalar(cvTsLU(&temp0, 0, 0));
  1276. }
  1277. ///////////////// invert /////////////////////
  1278. class Core_InvertTest : public Core_MatrixTest
  1279. {
  1280. public:
  1281. typedef Core_MatrixTest Base;
  1282. Core_InvertTest();
  1283. protected:
  1284. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1285. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  1286. double get_success_error_level( int test_case_idx, int i, int j );
  1287. int prepare_test_case( int test_case_idx );
  1288. void run_func();
  1289. void prepare_to_validation( int test_case_idx );
  1290. int method, rank;
  1291. double result;
  1292. };
  1293. Core_InvertTest::Core_InvertTest()
  1294. : Core_MatrixTest( 1, 1, false, false, 1 ), method(0), rank(0), result(0.)
  1295. {
  1296. test_case_count = 100;
  1297. max_log_array_size = 7;
  1298. test_array[TEMP].push_back(NULL);
  1299. test_array[TEMP].push_back(NULL);
  1300. }
  1301. void Core_InvertTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  1302. {
  1303. RNG& rng = ts->get_rng();
  1304. int bits = cvtest::randInt(rng);
  1305. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1306. int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
  1307. if( (bits & 3) == 0 )
  1308. {
  1309. method = CV_SVD;
  1310. if( bits & 4 )
  1311. {
  1312. sizes[INPUT][0] = Size(min_size, min_size);
  1313. if( bits & 16 )
  1314. method = CV_CHOLESKY;
  1315. }
  1316. }
  1317. else
  1318. {
  1319. method = CV_LU;
  1320. sizes[INPUT][0] = Size(min_size, min_size);
  1321. }
  1322. sizes[TEMP][0].width = sizes[INPUT][0].height;
  1323. sizes[TEMP][0].height = sizes[INPUT][0].width;
  1324. sizes[TEMP][1] = sizes[INPUT][0];
  1325. types[TEMP][0] = types[INPUT][0];
  1326. types[TEMP][1] = CV_64FC1;
  1327. sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(min_size, min_size);
  1328. }
  1329. double Core_InvertTest::get_success_error_level( int /*test_case_idx*/, int, int )
  1330. {
  1331. return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 1e-2 : 1e-6;
  1332. }
  1333. int Core_InvertTest::prepare_test_case( int test_case_idx )
  1334. {
  1335. int code = Core_MatrixTest::prepare_test_case( test_case_idx );
  1336. if( code > 0 )
  1337. {
  1338. cvTsFloodWithZeros( test_mat[INPUT][0], ts->get_rng() );
  1339. if( method == CV_CHOLESKY )
  1340. {
  1341. cvtest::gemm( test_mat[INPUT][0], test_mat[INPUT][0], 1.,
  1342. Mat(), 0., test_mat[TEMP][0], CV_GEMM_B_T );
  1343. cvtest::copy( test_mat[TEMP][0], test_mat[INPUT][0] );
  1344. }
  1345. }
  1346. return code;
  1347. }
  1348. void Core_InvertTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  1349. {
  1350. low = cvScalarAll(-1.);
  1351. high = cvScalarAll(1.);
  1352. }
  1353. void Core_InvertTest::run_func()
  1354. {
  1355. result = cvInvert(test_array[INPUT][0], test_array[TEMP][0], method);
  1356. }
  1357. static double cvTsSVDet( CvMat* mat, double* ratio )
  1358. {
  1359. int type = CV_MAT_TYPE(mat->type);
  1360. int i, nm = MIN( mat->rows, mat->cols );
  1361. CvMat* w = cvCreateMat( nm, 1, type );
  1362. double det = 1.;
  1363. cvSVD( mat, w, 0, 0, 0 );
  1364. if( type == CV_32FC1 )
  1365. {
  1366. for( i = 0; i < nm; i++ )
  1367. det *= w->data.fl[i];
  1368. *ratio = w->data.fl[nm-1] < FLT_EPSILON ? 0 : w->data.fl[nm-1]/w->data.fl[0];
  1369. }
  1370. else
  1371. {
  1372. for( i = 0; i < nm; i++ )
  1373. det *= w->data.db[i];
  1374. *ratio = w->data.db[nm-1] < FLT_EPSILON ? 0 : w->data.db[nm-1]/w->data.db[0];
  1375. }
  1376. cvReleaseMat( &w );
  1377. return det;
  1378. }
  1379. void Core_InvertTest::prepare_to_validation( int )
  1380. {
  1381. Mat& input = test_mat[INPUT][0];
  1382. Mat& temp0 = test_mat[TEMP][0];
  1383. Mat& temp1 = test_mat[TEMP][1];
  1384. Mat& dst0 = test_mat[REF_OUTPUT][0];
  1385. Mat& dst = test_mat[OUTPUT][0];
  1386. CvMat _input = cvMat(input);
  1387. double ratio = 0, det = cvTsSVDet( &_input, &ratio );
  1388. double threshold = (input.depth() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000;
  1389. cvtest::convert( input, temp1, temp1.type() );
  1390. if( det < threshold ||
  1391. ((method == CV_LU || method == CV_CHOLESKY) && (result == 0 || ratio < threshold)) ||
  1392. ((method == CV_SVD || method == CV_SVD_SYM) && result < threshold) )
  1393. {
  1394. dst = Scalar::all(0);
  1395. dst0 = Scalar::all(0);
  1396. return;
  1397. }
  1398. if( input.rows >= input.cols )
  1399. cvtest::gemm( temp0, input, 1., Mat(), 0., dst, 0 );
  1400. else
  1401. cvtest::gemm( input, temp0, 1., Mat(), 0., dst, 0 );
  1402. cv::setIdentity( dst0, Scalar::all(1) );
  1403. }
  1404. ///////////////// solve /////////////////////
  1405. class Core_SolveTest : public Core_MatrixTest
  1406. {
  1407. public:
  1408. typedef Core_MatrixTest Base;
  1409. Core_SolveTest();
  1410. protected:
  1411. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1412. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  1413. double get_success_error_level( int test_case_idx, int i, int j );
  1414. int prepare_test_case( int test_case_idx );
  1415. void run_func();
  1416. void prepare_to_validation( int test_case_idx );
  1417. int method, rank;
  1418. double result;
  1419. };
  1420. Core_SolveTest::Core_SolveTest() : Core_MatrixTest( 2, 1, false, false, 1 ), method(0), rank(0), result(0.)
  1421. {
  1422. test_case_count = 100;
  1423. max_log_array_size = 7;
  1424. test_array[TEMP].push_back(NULL);
  1425. test_array[TEMP].push_back(NULL);
  1426. }
  1427. void Core_SolveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  1428. {
  1429. RNG& rng = ts->get_rng();
  1430. int bits = cvtest::randInt(rng);
  1431. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1432. CvSize in_sz = cvSize(sizes[INPUT][0]);
  1433. if( in_sz.width > in_sz.height )
  1434. in_sz = cvSize(in_sz.height, in_sz.width);
  1435. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1436. sizes[INPUT][0] = in_sz;
  1437. int min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
  1438. if( (bits & 3) == 0 )
  1439. {
  1440. method = CV_SVD;
  1441. if( bits & 4 )
  1442. {
  1443. sizes[INPUT][0] = Size(min_size, min_size);
  1444. /*if( bits & 8 )
  1445. method = CV_SVD_SYM;*/
  1446. }
  1447. }
  1448. else
  1449. {
  1450. method = CV_LU;
  1451. sizes[INPUT][0] = Size(min_size, min_size);
  1452. }
  1453. sizes[INPUT][1].height = sizes[INPUT][0].height;
  1454. sizes[TEMP][0].width = sizes[INPUT][1].width;
  1455. sizes[TEMP][0].height = sizes[INPUT][0].width;
  1456. sizes[TEMP][1] = sizes[INPUT][0];
  1457. types[TEMP][0] = types[INPUT][0];
  1458. types[TEMP][1] = CV_64FC1;
  1459. sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size(sizes[INPUT][1].width, min_size);
  1460. }
  1461. int Core_SolveTest::prepare_test_case( int test_case_idx )
  1462. {
  1463. int code = Core_MatrixTest::prepare_test_case( test_case_idx );
  1464. /*if( method == CV_SVD_SYM )
  1465. {
  1466. cvTsGEMM( test_array[INPUT][0], test_array[INPUT][0], 1.,
  1467. 0, 0., test_array[TEMP][0], CV_GEMM_B_T );
  1468. cvTsCopy( test_array[TEMP][0], test_array[INPUT][0] );
  1469. }*/
  1470. return code;
  1471. }
  1472. void Core_SolveTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  1473. {
  1474. low = cvScalarAll(-1.);
  1475. high = cvScalarAll(1.);
  1476. }
  1477. double Core_SolveTest::get_success_error_level( int /*test_case_idx*/, int, int )
  1478. {
  1479. return CV_MAT_DEPTH(cvGetElemType(test_array[OUTPUT][0])) == CV_32F ? 5e-2 : 1e-8;
  1480. }
  1481. void Core_SolveTest::run_func()
  1482. {
  1483. result = cvSolve(test_array[INPUT][0], test_array[INPUT][1], test_array[TEMP][0], method);
  1484. }
  1485. void Core_SolveTest::prepare_to_validation( int )
  1486. {
  1487. //int rank = test_mat[REF_OUTPUT][0].rows;
  1488. Mat& input = test_mat[INPUT][0];
  1489. Mat& dst = test_mat[OUTPUT][0];
  1490. Mat& dst0 = test_mat[REF_OUTPUT][0];
  1491. if( method == CV_LU )
  1492. {
  1493. if( result == 0 )
  1494. {
  1495. Mat& temp1 = test_mat[TEMP][1];
  1496. cvtest::convert(input, temp1, temp1.type());
  1497. dst = Scalar::all(0);
  1498. CvMat _temp1 = cvMat(temp1);
  1499. double det = cvTsLU( &_temp1, 0, 0 );
  1500. dst0 = Scalar::all(det != 0);
  1501. return;
  1502. }
  1503. double threshold = (input.type() == CV_32F ? FLT_EPSILON : DBL_EPSILON)*1000;
  1504. CvMat _input = cvMat(input);
  1505. double ratio = 0, det = cvTsSVDet( &_input, &ratio );
  1506. if( det < threshold || ratio < threshold )
  1507. {
  1508. dst = Scalar::all(0);
  1509. dst0 = Scalar::all(0);
  1510. return;
  1511. }
  1512. }
  1513. Mat* pdst = input.rows <= input.cols ? &test_mat[OUTPUT][0] : &test_mat[INPUT][1];
  1514. cvtest::gemm( input, test_mat[TEMP][0], 1., test_mat[INPUT][1], -1., *pdst, 0 );
  1515. if( pdst != &dst )
  1516. cvtest::gemm( input, *pdst, 1., Mat(), 0., dst, CV_GEMM_A_T );
  1517. dst0 = Scalar::all(0);
  1518. }
  1519. ///////////////// SVD /////////////////////
  1520. class Core_SVDTest : public Core_MatrixTest
  1521. {
  1522. public:
  1523. typedef Core_MatrixTest Base;
  1524. Core_SVDTest();
  1525. protected:
  1526. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1527. double get_success_error_level( int test_case_idx, int i, int j );
  1528. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  1529. int prepare_test_case( int test_case_idx );
  1530. void run_func();
  1531. void prepare_to_validation( int test_case_idx );
  1532. int flags;
  1533. bool have_u, have_v, symmetric, compact, vector_w;
  1534. };
  1535. Core_SVDTest::Core_SVDTest() :
  1536. Core_MatrixTest( 1, 4, false, false, 1 ),
  1537. flags(0), have_u(false), have_v(false), symmetric(false), compact(false), vector_w(false)
  1538. {
  1539. test_case_count = 100;
  1540. max_log_array_size = 8;
  1541. test_array[TEMP].push_back(NULL);
  1542. test_array[TEMP].push_back(NULL);
  1543. test_array[TEMP].push_back(NULL);
  1544. test_array[TEMP].push_back(NULL);
  1545. }
  1546. void Core_SVDTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
  1547. {
  1548. RNG& rng = ts->get_rng();
  1549. int bits = cvtest::randInt(rng);
  1550. Core_MatrixTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1551. int min_size, i, m, n;
  1552. min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
  1553. flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
  1554. have_u = (bits & 8) != 0;
  1555. have_v = (bits & 16) != 0;
  1556. symmetric = (bits & 32) != 0;
  1557. compact = (bits & 64) != 0;
  1558. vector_w = (bits & 128) != 0;
  1559. if( symmetric )
  1560. sizes[INPUT][0] = Size(min_size, min_size);
  1561. m = sizes[INPUT][0].height;
  1562. n = sizes[INPUT][0].width;
  1563. if( compact )
  1564. sizes[TEMP][0] = Size(min_size, min_size);
  1565. else
  1566. sizes[TEMP][0] = sizes[INPUT][0];
  1567. sizes[TEMP][3] = Size(0,0);
  1568. if( vector_w )
  1569. {
  1570. sizes[TEMP][3] = sizes[TEMP][0];
  1571. if( bits & 256 )
  1572. sizes[TEMP][0] = Size(1, min_size);
  1573. else
  1574. sizes[TEMP][0] = Size(min_size, 1);
  1575. }
  1576. if( have_u )
  1577. {
  1578. sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
  1579. if( flags & CV_SVD_U_T )
  1580. CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
  1581. }
  1582. else
  1583. sizes[TEMP][1] = Size(0,0);
  1584. if( have_v )
  1585. {
  1586. sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
  1587. if( !(flags & CV_SVD_V_T) )
  1588. CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
  1589. }
  1590. else
  1591. sizes[TEMP][2] = Size(0,0);
  1592. types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[TEMP][3] = types[INPUT][0];
  1593. types[OUTPUT][0] = types[OUTPUT][1] = types[OUTPUT][2] = types[INPUT][0];
  1594. types[OUTPUT][3] = CV_8UC1;
  1595. sizes[OUTPUT][0] = !have_u || !have_v ? Size(0,0) : sizes[INPUT][0];
  1596. sizes[OUTPUT][1] = !have_u ? Size(0,0) : compact ? Size(min_size,min_size) : Size(m,m);
  1597. sizes[OUTPUT][2] = !have_v ? Size(0,0) : compact ? Size(min_size,min_size) : Size(n,n);
  1598. sizes[OUTPUT][3] = Size(min_size,1);
  1599. for( i = 0; i < 4; i++ )
  1600. {
  1601. sizes[REF_OUTPUT][i] = sizes[OUTPUT][i];
  1602. types[REF_OUTPUT][i] = types[OUTPUT][i];
  1603. }
  1604. }
  1605. int Core_SVDTest::prepare_test_case( int test_case_idx )
  1606. {
  1607. int code = Core_MatrixTest::prepare_test_case( test_case_idx );
  1608. if( code > 0 )
  1609. {
  1610. Mat& input = test_mat[INPUT][0];
  1611. cvTsFloodWithZeros( input, ts->get_rng() );
  1612. if( symmetric && (have_u || have_v) )
  1613. {
  1614. Mat& temp = test_mat[TEMP][have_u ? 1 : 2];
  1615. cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T );
  1616. cvtest::copy( temp, input );
  1617. }
  1618. if( (flags & CV_SVD_MODIFY_A) && test_array[OUTPUT][0] )
  1619. cvtest::copy( input, test_mat[OUTPUT][0] );
  1620. }
  1621. return code;
  1622. }
  1623. void Core_SVDTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  1624. {
  1625. low = cvScalarAll(-2.);
  1626. high = cvScalarAll(2.);
  1627. }
  1628. double Core_SVDTest::get_success_error_level( int test_case_idx, int i, int j )
  1629. {
  1630. int input_depth = CV_MAT_DEPTH(cvGetElemType( test_array[INPUT][0] ));
  1631. double input_precision = input_depth < CV_32F ? 0 : input_depth == CV_32F ? 1e-5 : 5e-11;
  1632. double output_precision = Base::get_success_error_level( test_case_idx, i, j );
  1633. return MAX(input_precision, output_precision);
  1634. }
  1635. void Core_SVDTest::run_func()
  1636. {
  1637. CvArr* src = test_array[!(flags & CV_SVD_MODIFY_A) ? INPUT : OUTPUT][0];
  1638. if( !src )
  1639. src = test_array[INPUT][0];
  1640. cvSVD( src, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
  1641. }
  1642. void Core_SVDTest::prepare_to_validation( int /*test_case_idx*/ )
  1643. {
  1644. Mat& input = test_mat[INPUT][0];
  1645. int depth = input.depth();
  1646. int i, m = input.rows, n = input.cols, min_size = MIN(m, n);
  1647. Mat *src, *dst, *w;
  1648. double prev = 0, threshold = depth == CV_32F ? FLT_EPSILON : DBL_EPSILON;
  1649. if( have_u )
  1650. {
  1651. src = &test_mat[TEMP][1];
  1652. dst = &test_mat[OUTPUT][1];
  1653. cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
  1654. cv::setIdentity( test_mat[REF_OUTPUT][1], Scalar::all(1.) );
  1655. }
  1656. if( have_v )
  1657. {
  1658. src = &test_mat[TEMP][2];
  1659. dst = &test_mat[OUTPUT][2];
  1660. cvtest::gemm( *src, *src, 1., Mat(), 0., *dst, src->rows == dst->rows ? CV_GEMM_B_T : CV_GEMM_A_T );
  1661. cv::setIdentity( test_mat[REF_OUTPUT][2], Scalar::all(1.) );
  1662. }
  1663. w = &test_mat[TEMP][0];
  1664. for( i = 0; i < min_size; i++ )
  1665. {
  1666. double normval = 0, aii;
  1667. if( w->rows > 1 && w->cols > 1 )
  1668. {
  1669. normval = cvtest::norm( w->row(i), NORM_L1 );
  1670. aii = depth == CV_32F ? w->at<float>(i,i) : w->at<double>(i,i);
  1671. }
  1672. else
  1673. {
  1674. normval = aii = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
  1675. }
  1676. normval = fabs(normval - aii);
  1677. test_mat[OUTPUT][3].at<uchar>(i) = aii >= 0 && normval < threshold && (i == 0 || aii <= prev);
  1678. prev = aii;
  1679. }
  1680. test_mat[REF_OUTPUT][3] = Scalar::all(1);
  1681. if( have_u && have_v )
  1682. {
  1683. if( vector_w )
  1684. {
  1685. test_mat[TEMP][3] = Scalar::all(0);
  1686. for( i = 0; i < min_size; i++ )
  1687. {
  1688. double val = depth == CV_32F ? w->at<float>(i) : w->at<double>(i);
  1689. cvSetReal2D( test_array[TEMP][3], i, i, val );
  1690. }
  1691. w = &test_mat[TEMP][3];
  1692. }
  1693. if( m >= n )
  1694. {
  1695. cvtest::gemm( test_mat[TEMP][1], *w, 1., Mat(), 0., test_mat[REF_OUTPUT][0],
  1696. flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
  1697. cvtest::gemm( test_mat[REF_OUTPUT][0], test_mat[TEMP][2], 1., Mat(), 0.,
  1698. test_mat[OUTPUT][0], flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
  1699. }
  1700. else
  1701. {
  1702. cvtest::gemm( *w, test_mat[TEMP][2], 1., Mat(), 0., test_mat[REF_OUTPUT][0],
  1703. flags & CV_SVD_V_T ? 0 : CV_GEMM_B_T );
  1704. cvtest::gemm( test_mat[TEMP][1], test_mat[REF_OUTPUT][0], 1., Mat(), 0.,
  1705. test_mat[OUTPUT][0], flags & CV_SVD_U_T ? CV_GEMM_A_T : 0 );
  1706. }
  1707. cvtest::copy( test_mat[INPUT][0], test_mat[REF_OUTPUT][0] );
  1708. }
  1709. }
  1710. ///////////////// SVBkSb /////////////////////
  1711. class Core_SVBkSbTest : public Core_MatrixTest
  1712. {
  1713. public:
  1714. typedef Core_MatrixTest Base;
  1715. Core_SVBkSbTest();
  1716. protected:
  1717. void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
  1718. double get_success_error_level( int test_case_idx, int i, int j );
  1719. void get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high );
  1720. int prepare_test_case( int test_case_idx );
  1721. void run_func();
  1722. void prepare_to_validation( int test_case_idx );
  1723. int flags;
  1724. bool have_b, symmetric, compact, vector_w;
  1725. };
  1726. Core_SVBkSbTest::Core_SVBkSbTest() : Core_MatrixTest( 2, 1, false, false, 1 ),
  1727. flags(0), have_b(false), symmetric(false), compact(false), vector_w(false)
  1728. {
  1729. test_case_count = 100;
  1730. test_array[TEMP].push_back(NULL);
  1731. test_array[TEMP].push_back(NULL);
  1732. test_array[TEMP].push_back(NULL);
  1733. }
  1734. void Core_SVBkSbTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes,
  1735. vector<vector<int> >& types )
  1736. {
  1737. RNG& rng = ts->get_rng();
  1738. int bits = cvtest::randInt(rng);
  1739. Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
  1740. int min_size, i, m, n;
  1741. cv::Size b_size;
  1742. min_size = MIN( sizes[INPUT][0].width, sizes[INPUT][0].height );
  1743. flags = bits & (CV_SVD_MODIFY_A+CV_SVD_U_T+CV_SVD_V_T);
  1744. have_b = (bits & 16) != 0;
  1745. symmetric = (bits & 32) != 0;
  1746. compact = (bits & 64) != 0;
  1747. vector_w = (bits & 128) != 0;
  1748. if( symmetric )
  1749. sizes[INPUT][0] = Size(min_size, min_size);
  1750. m = sizes[INPUT][0].height;
  1751. n = sizes[INPUT][0].width;
  1752. sizes[INPUT][1] = Size(0,0);
  1753. b_size = cvSize(m, m);
  1754. if( have_b )
  1755. {
  1756. sizes[INPUT][1].height = sizes[INPUT][0].height;
  1757. sizes[INPUT][1].width = cvtest::randInt(rng) % 100 + 1;
  1758. b_size = sizes[INPUT][1];
  1759. }
  1760. if( compact )
  1761. sizes[TEMP][0] = Size(min_size, min_size);
  1762. else
  1763. sizes[TEMP][0] = sizes[INPUT][0];
  1764. if( vector_w )
  1765. {
  1766. if( bits & 256 )
  1767. sizes[TEMP][0] = Size(1, min_size);
  1768. else
  1769. sizes[TEMP][0] = Size(min_size, 1);
  1770. }
  1771. sizes[TEMP][1] = compact ? Size(min_size, m) : Size(m, m);
  1772. if( flags & CV_SVD_U_T )
  1773. CV_SWAP( sizes[TEMP][1].width, sizes[TEMP][1].height, i );
  1774. sizes[TEMP][2] = compact ? Size(n, min_size) : Size(n, n);
  1775. if( !(flags & CV_SVD_V_T) )
  1776. CV_SWAP( sizes[TEMP][2].width, sizes[TEMP][2].height, i );
  1777. types[TEMP][0] = types[TEMP][1] = types[TEMP][2] = types[INPUT][0];
  1778. types[OUTPUT][0] = types[REF_OUTPUT][0] = types[INPUT][0];
  1779. sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = Size( b_size.width, n );
  1780. }
  1781. int Core_SVBkSbTest::prepare_test_case( int test_case_idx )
  1782. {
  1783. int code = Base::prepare_test_case( test_case_idx );
  1784. if( code > 0 )
  1785. {
  1786. Mat& input = test_mat[INPUT][0];
  1787. cvTsFloodWithZeros( input, ts->get_rng() );
  1788. if( symmetric )
  1789. {
  1790. Mat& temp = test_mat[TEMP][1];
  1791. cvtest::gemm( input, input, 1., Mat(), 0., temp, CV_GEMM_B_T );
  1792. cvtest::copy( temp, input );
  1793. }
  1794. CvMat _input = cvMat(input);
  1795. cvSVD( &_input, test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2], flags );
  1796. }
  1797. return code;
  1798. }
  1799. void Core_SVBkSbTest::get_minmax_bounds( int /*i*/, int /*j*/, int /*type*/, Scalar& low, Scalar& high )
  1800. {
  1801. low = cvScalarAll(-2.);
  1802. high = cvScalarAll(2.);
  1803. }
  1804. double Core_SVBkSbTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
  1805. {
  1806. return CV_MAT_DEPTH(cvGetElemType(test_array[INPUT][0])) == CV_32F ? 1e-3 : 1e-7;
  1807. }
  1808. void Core_SVBkSbTest::run_func()
  1809. {
  1810. cvSVBkSb( test_array[TEMP][0], test_array[TEMP][1], test_array[TEMP][2],
  1811. test_array[INPUT][1], test_array[OUTPUT][0], flags );
  1812. }
  1813. void Core_SVBkSbTest::prepare_to_validation( int )
  1814. {
  1815. Mat& input = test_mat[INPUT][0];
  1816. int i, m = input.rows, n = input.cols, min_size = MIN(m, n);
  1817. bool is_float = input.type() == CV_32F;
  1818. Size w_size = compact ? Size(min_size,min_size) : Size(m,n);
  1819. Mat& w = test_mat[TEMP][0];
  1820. Mat wdb( w_size.height, w_size.width, CV_64FC1 );
  1821. CvMat _w = cvMat(w), _wdb = cvMat(wdb);
  1822. // use exactly the same threshold as in icvSVD... ,
  1823. // so the changes in the library and here should be synchronized.
  1824. double threshold = cv::sum(w)[0]*(DBL_EPSILON*2);//(is_float ? FLT_EPSILON*10 : DBL_EPSILON*2);
  1825. wdb = Scalar::all(0);
  1826. for( i = 0; i < min_size; i++ )
  1827. {
  1828. double wii = vector_w ? cvGetReal1D(&_w,i) : cvGetReal2D(&_w,i,i);
  1829. cvSetReal2D( &_wdb, i, i, wii > threshold ? 1./wii : 0. );
  1830. }
  1831. Mat u = test_mat[TEMP][1];
  1832. Mat v = test_mat[TEMP][2];
  1833. Mat b = test_mat[INPUT][1];
  1834. if( is_float )
  1835. {
  1836. test_mat[TEMP][1].convertTo(u, CV_64F);
  1837. test_mat[TEMP][2].convertTo(v, CV_64F);
  1838. if( !b.empty() )
  1839. test_mat[INPUT][1].convertTo(b, CV_64F);
  1840. }
  1841. Mat t0, t1;
  1842. if( !b.empty() )
  1843. cvtest::gemm( u, b, 1., Mat(), 0., t0, !(flags & CV_SVD_U_T) ? CV_GEMM_A_T : 0 );
  1844. else if( flags & CV_SVD_U_T )
  1845. cvtest::copy( u, t0 );
  1846. else
  1847. cvtest::transpose( u, t0 );
  1848. cvtest::gemm( wdb, t0, 1, Mat(), 0, t1, 0 );
  1849. cvtest::gemm( v, t1, 1, Mat(), 0, t0, flags & CV_SVD_V_T ? CV_GEMM_A_T : 0 );
  1850. Mat& dst0 = test_mat[REF_OUTPUT][0];
  1851. t0.convertTo(dst0, dst0.type() );
  1852. }
  1853. typedef std::complex<double> complex_type;
  1854. struct pred_complex
  1855. {
  1856. bool operator() (const complex_type& lhs, const complex_type& rhs) const
  1857. {
  1858. return fabs(lhs.real() - rhs.real()) > fabs(rhs.real())*FLT_EPSILON ? lhs.real() < rhs.real() : lhs.imag() < rhs.imag();
  1859. }
  1860. };
  1861. struct pred_double
  1862. {
  1863. bool operator() (const double& lhs, const double& rhs) const
  1864. {
  1865. return lhs < rhs;
  1866. }
  1867. };
  1868. class Core_SolvePolyTest : public cvtest::BaseTest
  1869. {
  1870. public:
  1871. Core_SolvePolyTest();
  1872. ~Core_SolvePolyTest();
  1873. protected:
  1874. virtual void run( int start_from );
  1875. };
  1876. Core_SolvePolyTest::Core_SolvePolyTest() {}
  1877. Core_SolvePolyTest::~Core_SolvePolyTest() {}
  1878. void Core_SolvePolyTest::run( int )
  1879. {
  1880. RNG& rng = ts->get_rng();
  1881. int fig = 100;
  1882. double range = 50;
  1883. double err_eps = 1e-4;
  1884. for (int idx = 0, max_idx = 1000, progress = 0; idx < max_idx; ++idx)
  1885. {
  1886. progress = update_progress(progress, idx-1, max_idx, 0);
  1887. int n = cvtest::randInt(rng) % 13 + 1;
  1888. std::vector<complex_type> r(n), ar(n), c(n + 1, 0);
  1889. std::vector<double> a(n + 1), u(n * 2), ar1(n), ar2(n);
  1890. int rr_odds = 3; // odds that we get a real root
  1891. for (int j = 0; j < n;)
  1892. {
  1893. if (cvtest::randInt(rng) % rr_odds == 0 || j == n - 1)
  1894. r[j++] = cvtest::randReal(rng) * range;
  1895. else
  1896. {
  1897. r[j] = complex_type(cvtest::randReal(rng) * range,
  1898. cvtest::randReal(rng) * range + 1);
  1899. r[j + 1] = std::conj(r[j]);
  1900. j += 2;
  1901. }
  1902. }
  1903. for (int j = 0, k = 1 << n, jj, kk; j < k; ++j)
  1904. {
  1905. int p = 0;
  1906. complex_type v(1);
  1907. for (jj = 0, kk = 1; jj < n && !(j & kk); ++jj, ++p, kk <<= 1)
  1908. ;
  1909. for (; jj < n; ++jj, kk <<= 1)
  1910. {
  1911. if (j & kk)
  1912. v *= -r[jj];
  1913. else
  1914. ++p;
  1915. }
  1916. c[p] += v;
  1917. }
  1918. bool pass = false;
  1919. double div = 0, s = 0;
  1920. int cubic_case = idx & 1;
  1921. for (int maxiter = 100; !pass && maxiter < 10000; maxiter *= 2, cubic_case = (cubic_case + 1) % 2)
  1922. {
  1923. for (int j = 0; j < n + 1; ++j)
  1924. a[j] = c[j].real();
  1925. CvMat amat, umat;
  1926. cvInitMatHeader(&amat, n + 1, 1, CV_64FC1, &a[0]);
  1927. cvInitMatHeader(&umat, n, 1, CV_64FC2, &u[0]);
  1928. cvSolvePoly(&amat, &umat, maxiter, fig);
  1929. for (int j = 0; j < n; ++j)
  1930. ar[j] = complex_type(u[j * 2], u[j * 2 + 1]);
  1931. std::sort(r.begin(), r.end(), pred_complex());
  1932. std::sort(ar.begin(), ar.end(), pred_complex());
  1933. pass = true;
  1934. if( n == 3 )
  1935. {
  1936. ar2.resize(n);
  1937. cv::Mat _umat2(3, 1, CV_64F, &ar2[0]), umat2 = _umat2;
  1938. cvFlip(&amat, &amat, 0);
  1939. int nr2;
  1940. if( cubic_case == 0 )
  1941. nr2 = cv::solveCubic(cv::cvarrToMat(&amat),umat2);
  1942. else
  1943. nr2 = cv::solveCubic(cv::Mat_<float>(cv::cvarrToMat(&amat)), umat2);
  1944. cvFlip(&amat, &amat, 0);
  1945. if(nr2 > 0)
  1946. std::sort(ar2.begin(), ar2.begin()+nr2, pred_double());
  1947. ar2.resize(nr2);
  1948. int nr1 = 0;
  1949. for(int j = 0; j < n; j++)
  1950. if( fabs(r[j].imag()) < DBL_EPSILON )
  1951. ar1[nr1++] = r[j].real();
  1952. pass = pass && nr1 == nr2;
  1953. if( nr2 > 0 )
  1954. {
  1955. div = s = 0;
  1956. for(int j = 0; j < nr1; j++)
  1957. {
  1958. s += fabs(ar1[j]);
  1959. div += fabs(ar1[j] - ar2[j]);
  1960. }
  1961. div /= s;
  1962. pass = pass && div < err_eps;
  1963. }
  1964. }
  1965. div = s = 0;
  1966. for (int j = 0; j < n; ++j)
  1967. {
  1968. s += fabs(r[j].real()) + fabs(r[j].imag());
  1969. div += sqrt(pow(r[j].real() - ar[j].real(), 2) + pow(r[j].imag() - ar[j].imag(), 2));
  1970. }
  1971. div /= s;
  1972. pass = pass && div < err_eps;
  1973. }
  1974. //test x^3 = 0
  1975. cv::Mat coeffs_5623(4, 1, CV_64FC1);
  1976. cv::Mat r_5623(3, 1, CV_64FC2);
  1977. coeffs_5623.at<double>(0) = 1;
  1978. coeffs_5623.at<double>(1) = 0;
  1979. coeffs_5623.at<double>(2) = 0;
  1980. coeffs_5623.at<double>(3) = 0;
  1981. double prec_5623 = cv::solveCubic(coeffs_5623, r_5623);
  1982. pass = pass && r_5623.at<double>(0) == 0 && r_5623.at<double>(1) == 0 && r_5623.at<double>(2) == 0;
  1983. pass = pass && prec_5623 == 1;
  1984. if (!pass)
  1985. {
  1986. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  1987. ts->printf( cvtest::TS::LOG, "too big diff = %g\n", div );
  1988. for (size_t j=0;j<ar2.size();++j)
  1989. ts->printf( cvtest::TS::LOG, "ar2[%d]=%g\n", j, ar2[j]);
  1990. ts->printf(cvtest::TS::LOG, "\n");
  1991. for (size_t j=0;j<r.size();++j)
  1992. ts->printf( cvtest::TS::LOG, "r[%d]=(%g, %g)\n", j, r[j].real(), r[j].imag());
  1993. ts->printf( cvtest::TS::LOG, "\n" );
  1994. for (size_t j=0;j<ar.size();++j)
  1995. ts->printf( cvtest::TS::LOG, "ar[%d]=(%g, %g)\n", j, ar[j].real(), ar[j].imag());
  1996. break;
  1997. }
  1998. }
  1999. }
  2000. template<typename T>
  2001. static void checkRoot(Mat& r, T re, T im)
  2002. {
  2003. for (int i = 0; i < r.cols*r.rows; i++)
  2004. {
  2005. Vec<T, 2> v = *(Vec<T, 2>*)r.ptr(i);
  2006. if (fabs(re - v[0]) < 1e-6 && fabs(im - v[1]) < 1e-6)
  2007. {
  2008. v[0] = std::numeric_limits<T>::quiet_NaN();
  2009. v[1] = std::numeric_limits<T>::quiet_NaN();
  2010. return;
  2011. }
  2012. }
  2013. GTEST_NONFATAL_FAILURE_("Can't find root") << "(" << re << ", " << im << ")";
  2014. }
  2015. TEST(Core_SolvePoly, regression_5599)
  2016. {
  2017. // x^4 - x^2 = 0, roots: 1, -1, 0, 0
  2018. cv::Mat coefs = (cv::Mat_<float>(1,5) << 0, 0, -1, 0, 1 );
  2019. {
  2020. cv::Mat r;
  2021. double prec;
  2022. prec = cv::solvePoly(coefs, r);
  2023. EXPECT_LE(prec, 1e-6);
  2024. EXPECT_EQ(4u, r.total());
  2025. //std::cout << "Preciseness = " << prec << std::endl;
  2026. //std::cout << "roots:\n" << r << "\n" << std::endl;
  2027. ASSERT_EQ(CV_32FC2, r.type());
  2028. checkRoot<float>(r, 1, 0);
  2029. checkRoot<float>(r, -1, 0);
  2030. checkRoot<float>(r, 0, 0);
  2031. checkRoot<float>(r, 0, 0);
  2032. }
  2033. // x^2 - 2x + 1 = 0, roots: 1, 1
  2034. coefs = (cv::Mat_<float>(1,3) << 1, -2, 1 );
  2035. {
  2036. cv::Mat r;
  2037. double prec;
  2038. prec = cv::solvePoly(coefs, r);
  2039. EXPECT_LE(prec, 1e-6);
  2040. EXPECT_EQ(2u, r.total());
  2041. //std::cout << "Preciseness = " << prec << std::endl;
  2042. //std::cout << "roots:\n" << r << "\n" << std::endl;
  2043. ASSERT_EQ(CV_32FC2, r.type());
  2044. checkRoot<float>(r, 1, 0);
  2045. checkRoot<float>(r, 1, 0);
  2046. }
  2047. }
  2048. class Core_PhaseTest : public cvtest::BaseTest
  2049. {
  2050. int t;
  2051. public:
  2052. Core_PhaseTest(int t_) : t(t_) {}
  2053. ~Core_PhaseTest() {}
  2054. protected:
  2055. virtual void run(int)
  2056. {
  2057. const float maxAngleDiff = 0.5; //in degrees
  2058. const int axisCount = 8;
  2059. const int dim = theRNG().uniform(1,10);
  2060. const float scale = theRNG().uniform(1.f, 100.f);
  2061. Mat x(axisCount + 1, dim, t),
  2062. y(axisCount + 1, dim, t);
  2063. Mat anglesInDegrees(axisCount + 1, dim, t);
  2064. // fill the data
  2065. x.row(0).setTo(Scalar(0));
  2066. y.row(0).setTo(Scalar(0));
  2067. anglesInDegrees.row(0).setTo(Scalar(0));
  2068. x.row(1).setTo(Scalar(scale));
  2069. y.row(1).setTo(Scalar(0));
  2070. anglesInDegrees.row(1).setTo(Scalar(0));
  2071. x.row(2).setTo(Scalar(scale));
  2072. y.row(2).setTo(Scalar(scale));
  2073. anglesInDegrees.row(2).setTo(Scalar(45));
  2074. x.row(3).setTo(Scalar(0));
  2075. y.row(3).setTo(Scalar(scale));
  2076. anglesInDegrees.row(3).setTo(Scalar(90));
  2077. x.row(4).setTo(Scalar(-scale));
  2078. y.row(4).setTo(Scalar(scale));
  2079. anglesInDegrees.row(4).setTo(Scalar(135));
  2080. x.row(5).setTo(Scalar(-scale));
  2081. y.row(5).setTo(Scalar(0));
  2082. anglesInDegrees.row(5).setTo(Scalar(180));
  2083. x.row(6).setTo(Scalar(-scale));
  2084. y.row(6).setTo(Scalar(-scale));
  2085. anglesInDegrees.row(6).setTo(Scalar(225));
  2086. x.row(7).setTo(Scalar(0));
  2087. y.row(7).setTo(Scalar(-scale));
  2088. anglesInDegrees.row(7).setTo(Scalar(270));
  2089. x.row(8).setTo(Scalar(scale));
  2090. y.row(8).setTo(Scalar(-scale));
  2091. anglesInDegrees.row(8).setTo(Scalar(315));
  2092. Mat resInRad, resInDeg;
  2093. phase(x, y, resInRad, false);
  2094. phase(x, y, resInDeg, true);
  2095. CV_Assert(resInRad.size() == x.size());
  2096. CV_Assert(resInRad.type() == x.type());
  2097. CV_Assert(resInDeg.size() == x.size());
  2098. CV_Assert(resInDeg.type() == x.type());
  2099. // check the result
  2100. int outOfRangeCount = countNonZero((resInDeg > 360) | (resInDeg < 0));
  2101. if(outOfRangeCount > 0)
  2102. {
  2103. ts->printf(cvtest::TS::LOG, "There are result angles that are out of range [0, 360] (part of them is %f)\n",
  2104. static_cast<float>(outOfRangeCount)/resInDeg.total());
  2105. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  2106. }
  2107. Mat diff = abs(anglesInDegrees - resInDeg);
  2108. size_t errDegCount = diff.total() - countNonZero((diff < maxAngleDiff) | ((360 - diff) < maxAngleDiff));
  2109. if(errDegCount > 0)
  2110. {
  2111. ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in degrees) (part of them is %f)\n",
  2112. static_cast<float>(errDegCount)/resInDeg.total());
  2113. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  2114. }
  2115. Mat convertedRes = resInRad * 180. / CV_PI;
  2116. double normDiff = cvtest::norm(convertedRes - resInDeg, NORM_INF);
  2117. if(normDiff > FLT_EPSILON * 180.)
  2118. {
  2119. ts->printf(cvtest::TS::LOG, "There are incorrect result angles (in radians)\n");
  2120. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  2121. }
  2122. ts->set_failed_test_info(cvtest::TS::OK);
  2123. }
  2124. };
  2125. TEST(Core_CheckRange_Empty, accuracy)
  2126. {
  2127. cv::Mat m;
  2128. ASSERT_TRUE( cv::checkRange(m) );
  2129. }
  2130. TEST(Core_CheckRange_INT_MAX, accuracy)
  2131. {
  2132. cv::Mat m(3, 3, CV_32SC1, cv::Scalar(INT_MAX));
  2133. ASSERT_FALSE( cv::checkRange(m, true, 0, 0, INT_MAX) );
  2134. ASSERT_TRUE( cv::checkRange(m) );
  2135. }
  2136. TEST(Core_CheckRange_INT_MAX1, accuracy)
  2137. {
  2138. cv::Mat m(3, 3, CV_32SC1, cv::Scalar(INT_MAX));
  2139. ASSERT_TRUE( cv::checkRange(m, true, 0, 0, (float)((double)INT_MAX+1.0f)) );
  2140. ASSERT_TRUE( cv::checkRange(m) );
  2141. }
  2142. template <typename T> class Core_CheckRange : public testing::Test {};
  2143. TYPED_TEST_CASE_P(Core_CheckRange);
  2144. TYPED_TEST_P(Core_CheckRange, Negative)
  2145. {
  2146. double min_bound = 4.5;
  2147. double max_bound = 16.0;
  2148. TypeParam data[] = {5, 10, 15, 10, 10, 2, 8, 12, 14};
  2149. cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
  2150. cv::Point bad_pt(0, 0);
  2151. ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound));
  2152. ASSERT_EQ(bad_pt.x, 2);
  2153. ASSERT_EQ(bad_pt.y, 1);
  2154. }
  2155. TYPED_TEST_P(Core_CheckRange, Negative3CN)
  2156. {
  2157. double min_bound = 4.5;
  2158. double max_bound = 16.0;
  2159. TypeParam data[] = { 5, 6, 7, 10, 11, 12, 13, 14, 15,
  2160. 10, 11, 12, 10, 11, 12, 2, 5, 6,
  2161. 8, 8, 8, 12, 12, 12, 14, 14, 14};
  2162. cv::Mat src = cv::Mat(3,3, CV_MAKETYPE(cv::DataDepth<TypeParam>::value, 3), data);
  2163. cv::Point bad_pt(0, 0);
  2164. ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound));
  2165. ASSERT_EQ(bad_pt.x, 2);
  2166. ASSERT_EQ(bad_pt.y, 1);
  2167. }
  2168. TYPED_TEST_P(Core_CheckRange, Positive)
  2169. {
  2170. double min_bound = -1;
  2171. double max_bound = 16.0;
  2172. TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14};
  2173. cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
  2174. cv::Point bad_pt(0, 0);
  2175. ASSERT_TRUE(checkRange(src, true, &bad_pt, min_bound, max_bound));
  2176. ASSERT_EQ(bad_pt.x, 0);
  2177. ASSERT_EQ(bad_pt.y, 0);
  2178. }
  2179. TYPED_TEST_P(Core_CheckRange, Bounds)
  2180. {
  2181. double min_bound = 24.5;
  2182. double max_bound = 1.0;
  2183. TypeParam data[] = {5, 10, 15, 4, 10, 2, 8, 12, 14};
  2184. cv::Mat src = cv::Mat(3,3, cv::DataDepth<TypeParam>::value, data);
  2185. cv::Point bad_pt(0, 0);
  2186. ASSERT_FALSE(checkRange(src, true, &bad_pt, min_bound, max_bound));
  2187. ASSERT_EQ(bad_pt.x, 0);
  2188. ASSERT_EQ(bad_pt.y, 0);
  2189. }
  2190. TYPED_TEST_P(Core_CheckRange, Zero)
  2191. {
  2192. double min_bound = 0.0;
  2193. double max_bound = 0.1;
  2194. cv::Mat src1 = cv::Mat::zeros(3, 3, cv::DataDepth<TypeParam>::value);
  2195. int sizes[] = {5, 6, 7};
  2196. cv::Mat src2 = cv::Mat::zeros(3, sizes, cv::DataDepth<TypeParam>::value);
  2197. ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
  2198. ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
  2199. }
  2200. TYPED_TEST_P(Core_CheckRange, One)
  2201. {
  2202. double min_bound = 1.0;
  2203. double max_bound = 1.1;
  2204. cv::Mat src1 = cv::Mat::ones(3, 3, cv::DataDepth<TypeParam>::value);
  2205. int sizes[] = {5, 6, 7};
  2206. cv::Mat src2 = cv::Mat::ones(3, sizes, cv::DataDepth<TypeParam>::value);
  2207. ASSERT_TRUE( checkRange(src1, true, NULL, min_bound, max_bound) );
  2208. ASSERT_TRUE( checkRange(src2, true, NULL, min_bound, max_bound) );
  2209. }
  2210. TEST(Core_CheckRange, NaN)
  2211. {
  2212. float data[] = { 5, 6, 7, 10, 11, 12, 13, 14, 15,
  2213. 10, 11, 12, 10, 11, 12, 5, 5, std::numeric_limits<float>::quiet_NaN(),
  2214. 8, 8, 8, 12, 12, 12, 14, 14, 14};
  2215. cv::Mat src = cv::Mat(3,3, CV_32FC3, data);
  2216. cv::Point bad_pt(0, 0);
  2217. ASSERT_FALSE(checkRange(src, true, &bad_pt));
  2218. ASSERT_EQ(bad_pt.x, 2);
  2219. ASSERT_EQ(bad_pt.y, 1);
  2220. }
  2221. TEST(Core_CheckRange, Inf)
  2222. {
  2223. float data[] = { 5, 6, 7, 10, 11, 12, 13, 14, 15,
  2224. 10, 11, 12, 10, 11, 12, 5, 5, std::numeric_limits<float>::infinity(),
  2225. 8, 8, 8, 12, 12, 12, 14, 14, 14};
  2226. cv::Mat src = cv::Mat(3,3, CV_32FC3, data);
  2227. cv::Point bad_pt(0, 0);
  2228. ASSERT_FALSE(checkRange(src, true, &bad_pt));
  2229. ASSERT_EQ(bad_pt.x, 2);
  2230. ASSERT_EQ(bad_pt.y, 1);
  2231. }
  2232. TEST(Core_CheckRange, Inf_Minus)
  2233. {
  2234. float data[] = { 5, 6, 7, 10, 11, 12, 13, 14, 15,
  2235. 10, 11, 12, 10, 11, 12, 5, 5, -std::numeric_limits<float>::infinity(),
  2236. 8, 8, 8, 12, 12, 12, 14, 14, 14};
  2237. cv::Mat src = cv::Mat(3,3, CV_32FC3, data);
  2238. cv::Point bad_pt(0, 0);
  2239. ASSERT_FALSE(checkRange(src, true, &bad_pt));
  2240. ASSERT_EQ(bad_pt.x, 2);
  2241. ASSERT_EQ(bad_pt.y, 1);
  2242. }
  2243. REGISTER_TYPED_TEST_CASE_P(Core_CheckRange, Negative, Negative3CN, Positive, Bounds, Zero, One);
  2244. typedef ::testing::Types<signed char,unsigned char, signed short, unsigned short, signed int> mat_data_types;
  2245. INSTANTIATE_TYPED_TEST_CASE_P(Negative_Test, Core_CheckRange, mat_data_types);
  2246. TEST(Core_Invert, small)
  2247. {
  2248. cv::Mat a = (cv::Mat_<float>(3,3) << 2.42104644730331, 1.81444796521479, -3.98072565304758, 0, 7.08389214348967e-3, 5.55326770986007e-3, 0,0, 7.44556154284261e-3);
  2249. //cv::randu(a, -1, 1);
  2250. cv::Mat b = a.t()*a;
  2251. cv::Mat c, i = Mat_<float>::eye(3, 3);
  2252. cv::invert(b, c, cv::DECOMP_LU); //std::cout << b*c << std::endl;
  2253. ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
  2254. cv::invert(b, c, cv::DECOMP_SVD); //std::cout << b*c << std::endl;
  2255. ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
  2256. cv::invert(b, c, cv::DECOMP_CHOLESKY); //std::cout << b*c << std::endl;
  2257. ASSERT_LT( cvtest::norm(b*c, i, CV_C), 0.1 );
  2258. }
  2259. /////////////////////////////////////////////////////////////////////////////////////////////////////
  2260. TEST(Core_CovarMatrix, accuracy) { Core_CovarMatrixTest test; test.safe_run(); }
  2261. TEST(Core_CrossProduct, accuracy) { Core_CrossProductTest test; test.safe_run(); }
  2262. TEST(Core_Determinant, accuracy) { Core_DetTest test; test.safe_run(); }
  2263. TEST(Core_DotProduct, accuracy) { Core_DotProductTest test; test.safe_run(); }
  2264. TEST(Core_GEMM, accuracy) { Core_GEMMTest test; test.safe_run(); }
  2265. TEST(Core_Invert, accuracy) { Core_InvertTest test; test.safe_run(); }
  2266. TEST(Core_Mahalanobis, accuracy) { Core_MahalanobisTest test; test.safe_run(); }
  2267. TEST(Core_MulTransposed, accuracy) { Core_MulTransposedTest test; test.safe_run(); }
  2268. TEST(Core_Transform, accuracy) { Core_TransformTest test; test.safe_run(); }
  2269. TEST(Core_TransformLarge, accuracy) { Core_TransformLargeTest test; test.safe_run(); }
  2270. TEST(Core_PerspectiveTransform, accuracy) { Core_PerspectiveTransformTest test; test.safe_run(); }
  2271. TEST(Core_Pow, accuracy) { Core_PowTest test; test.safe_run(); }
  2272. TEST(Core_SolveLinearSystem, accuracy) { Core_SolveTest test; test.safe_run(); }
  2273. TEST(Core_SVD, accuracy) { Core_SVDTest test; test.safe_run(); }
  2274. TEST(Core_SVBkSb, accuracy) { Core_SVBkSbTest test; test.safe_run(); }
  2275. TEST(Core_Trace, accuracy) { Core_TraceTest test; test.safe_run(); }
  2276. TEST(Core_SolvePoly, accuracy) { Core_SolvePolyTest test; test.safe_run(); }
  2277. TEST(Core_Phase, accuracy32f) { Core_PhaseTest test(CV_32FC1); test.safe_run(); }
  2278. TEST(Core_Phase, accuracy64f) { Core_PhaseTest test(CV_64FC1); test.safe_run(); }
  2279. TEST(Core_SVD, flt)
  2280. {
  2281. float a[] = {
  2282. 1.23377746e+011f, -7.05490125e+010f, -4.18380882e+010f, -11693456.f,
  2283. -39091328.f, 77492224.f, -7.05490125e+010f, 2.36211143e+011f,
  2284. -3.51093473e+010f, 70773408.f, -4.83386156e+005f, -129560368.f,
  2285. -4.18380882e+010f, -3.51093473e+010f, 9.25311222e+010f, -49052424.f,
  2286. 43922752.f, 12176842.f, -11693456.f, 70773408.f, -49052424.f, 8.40836094e+004f,
  2287. 5.17475293e+003f, -1.16122949e+004f, -39091328.f, -4.83386156e+005f,
  2288. 43922752.f, 5.17475293e+003f, 5.16047969e+004f, 5.68887842e+003f, 77492224.f,
  2289. -129560368.f, 12176842.f, -1.16122949e+004f, 5.68887842e+003f,
  2290. 1.28060578e+005f
  2291. };
  2292. float b[] = {
  2293. 283751232.f, 2.61604198e+009f, -745033216.f, 2.31125625e+005f,
  2294. -4.52429188e+005f, -1.37596525e+006f
  2295. };
  2296. Mat A(6, 6, CV_32F, a);
  2297. Mat B(6, 1, CV_32F, b);
  2298. Mat X, B1;
  2299. solve(A, B, X, DECOMP_SVD);
  2300. B1 = A*X;
  2301. EXPECT_LE(cvtest::norm(B1, B, NORM_L2 + NORM_RELATIVE), FLT_EPSILON*10);
  2302. }
  2303. // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)),
  2304. enum
  2305. {
  2306. MAT_N_DIM_C1,
  2307. MAT_N_1_CDIM,
  2308. MAT_1_N_CDIM,
  2309. MAT_N_DIM_C1_NONCONT,
  2310. MAT_N_1_CDIM_NONCONT,
  2311. VECTOR
  2312. };
  2313. class CV_KMeansSingularTest : public cvtest::BaseTest
  2314. {
  2315. public:
  2316. CV_KMeansSingularTest() {}
  2317. ~CV_KMeansSingularTest() {}
  2318. protected:
  2319. void run(int inVariant)
  2320. {
  2321. RNG& rng = ts->get_rng();
  2322. int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0;
  2323. Mat labels;
  2324. {
  2325. const int MAX_DIM=5;
  2326. int MAX_POINTS = 100, maxIter = 100;
  2327. for( iter = 0; iter < maxIter; iter++ )
  2328. {
  2329. ts->update_context(this, iter, true);
  2330. dims = rng.uniform(inVariant == MAT_1_N_CDIM ? 2 : 1, MAX_DIM+1);
  2331. N = rng.uniform(2, MAX_POINTS+1);
  2332. N0 = rng.uniform(1, MAX(N/10, 2));
  2333. K = rng.uniform(1, N+1);
  2334. Mat centers;
  2335. if (inVariant == VECTOR)
  2336. {
  2337. dims = 2;
  2338. std::vector<cv::Point2f> data0(N0);
  2339. rng.fill(data0, RNG::UNIFORM, -1, 1);
  2340. std::vector<cv::Point2f> data(N);
  2341. for( i = 0; i < N; i++ )
  2342. data[i] = data0[rng.uniform(0, N0)];
  2343. kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
  2344. 5, KMEANS_PP_CENTERS, centers);
  2345. }
  2346. else
  2347. {
  2348. Mat data0(N0, dims, CV_32F);
  2349. rng.fill(data0, RNG::UNIFORM, -1, 1);
  2350. Mat data;
  2351. switch (inVariant)
  2352. {
  2353. case MAT_N_DIM_C1:
  2354. data.create(N, dims, CV_32F);
  2355. for( i = 0; i < N; i++ )
  2356. data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
  2357. break;
  2358. case MAT_N_1_CDIM:
  2359. data.create(N, 1, CV_32FC(dims));
  2360. for( i = 0; i < N; i++ )
  2361. memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
  2362. break;
  2363. case MAT_1_N_CDIM:
  2364. data.create(1, N, CV_32FC(dims));
  2365. for( i = 0; i < N; i++ )
  2366. memcpy(data.ptr() + i * dims * sizeof(float), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
  2367. break;
  2368. case MAT_N_DIM_C1_NONCONT:
  2369. data.create(N, dims + 5, CV_32F);
  2370. data = data(Range(0, N), Range(0, dims));
  2371. for( i = 0; i < N; i++ )
  2372. data0.row(rng.uniform(0, N0)).copyTo(data.row(i));
  2373. break;
  2374. case MAT_N_1_CDIM_NONCONT:
  2375. data.create(N, 3, CV_32FC(dims));
  2376. data = data.colRange(0, 1);
  2377. for( i = 0; i < N; i++ )
  2378. memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float));
  2379. break;
  2380. }
  2381. kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0),
  2382. 5, KMEANS_PP_CENTERS, centers);
  2383. }
  2384. ASSERT_EQ(centers.rows, K);
  2385. ASSERT_EQ(labels.rows, N);
  2386. Mat hist(K, 1, CV_32S, Scalar(0));
  2387. for( i = 0; i < N; i++ )
  2388. {
  2389. int l = labels.at<int>(i);
  2390. ASSERT_GE(l, 0);
  2391. ASSERT_LT(l, K);
  2392. hist.at<int>(l)++;
  2393. }
  2394. for( i = 0; i < K; i++ )
  2395. ASSERT_GT(hist.at<int>(i), 0);
  2396. }
  2397. }
  2398. }
  2399. };
  2400. TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); }
  2401. CV_ENUM(KMeansInputVariant, MAT_N_DIM_C1, MAT_N_1_CDIM, MAT_1_N_CDIM, MAT_N_DIM_C1_NONCONT, MAT_N_1_CDIM_NONCONT, VECTOR)
  2402. typedef testing::TestWithParam<KMeansInputVariant> Core_KMeans_InputVariants;
  2403. TEST_P(Core_KMeans_InputVariants, singular)
  2404. {
  2405. CV_KMeansSingularTest test;
  2406. test.safe_run(GetParam());
  2407. }
  2408. INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all());
  2409. TEST(Core_KMeans, compactness)
  2410. {
  2411. const int N = 1024;
  2412. const int attempts = 4;
  2413. const TermCriteria crit = TermCriteria(TermCriteria::COUNT, 5, 0); // low number of iterations
  2414. cvtest::TS& ts = *cvtest::TS::ptr();
  2415. for (int K = 1; K <= N; K *= 2)
  2416. {
  2417. Mat data(N, 1, CV_32FC2);
  2418. cvtest::randUni(ts.get_rng(), data, Scalar(-200, -200), Scalar(200, 200));
  2419. Mat labels, centers;
  2420. double compactness = kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers);
  2421. centers = centers.reshape(2);
  2422. EXPECT_EQ(labels.rows, N);
  2423. EXPECT_EQ(centers.rows, K);
  2424. EXPECT_GE(compactness, 0.0);
  2425. double expected = 0.0;
  2426. for (int i = 0; i < N; ++i)
  2427. {
  2428. int l = labels.at<int>(i);
  2429. Point2f d = data.at<Point2f>(i) - centers.at<Point2f>(l);
  2430. expected += d.x * d.x + d.y * d.y;
  2431. }
  2432. EXPECT_NEAR(expected, compactness, expected * 1e-8);
  2433. if (K == N)
  2434. {
  2435. EXPECT_DOUBLE_EQ(compactness, 0.0);
  2436. }
  2437. }
  2438. }
  2439. TEST(Core_KMeans, bad_input)
  2440. {
  2441. const int N = 100;
  2442. const int attempts = 4;
  2443. const TermCriteria crit = TermCriteria(TermCriteria::COUNT, 5, 0); // low number of iterations
  2444. const int K = 3;
  2445. Mat data(N, 1, CV_32FC2);
  2446. cv::randu(data, Scalar(-200, -200), Scalar(200, 200));
  2447. {
  2448. SCOPED_TRACE("Huge value");
  2449. data.at<Vec2f>(10, 0) = Vec2f(1e20f, 0);
  2450. Mat labels, centers;
  2451. EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers));
  2452. }
  2453. {
  2454. SCOPED_TRACE("Negative value");
  2455. data.at<Vec2f>(10, 0) = Vec2f(0, -1e20f);
  2456. Mat labels, centers;
  2457. EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers));
  2458. }
  2459. {
  2460. SCOPED_TRACE("NaN");
  2461. data.at<Vec2f>(10, 0) = Vec2f(0, std::numeric_limits<float>::quiet_NaN());
  2462. Mat labels, centers;
  2463. EXPECT_ANY_THROW(kmeans(data, K, labels, crit, attempts, KMEANS_PP_CENTERS, centers));
  2464. }
  2465. }
  2466. TEST(CovariationMatrixVectorOfMat, accuracy)
  2467. {
  2468. unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16;
  2469. cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F);
  2470. int singleMatFlags = CV_COVAR_ROWS;
  2471. cv::Mat gold;
  2472. cv::Mat goldMean;
  2473. cv::randu(src,cv::Scalar(-128), cv::Scalar(128));
  2474. cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F);
  2475. std::vector<cv::Mat> srcVec;
  2476. for(size_t i = 0; i < vector_size; i++)
  2477. {
  2478. srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
  2479. }
  2480. cv::Mat actual;
  2481. cv::Mat actualMean;
  2482. cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
  2483. cv::Mat diff;
  2484. cv::absdiff(gold, actual, diff);
  2485. cv::Scalar s = cv::sum(diff);
  2486. ASSERT_EQ(s.dot(s), 0.0);
  2487. cv::Mat meanDiff;
  2488. cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
  2489. cv::Scalar sDiff = cv::sum(meanDiff);
  2490. ASSERT_EQ(sDiff.dot(sDiff), 0.0);
  2491. }
  2492. TEST(CovariationMatrixVectorOfMatWithMean, accuracy)
  2493. {
  2494. unsigned int col_problem_size = 8, row_problem_size = 8, vector_size = 16;
  2495. cv::Mat src(vector_size, col_problem_size * row_problem_size, CV_32F);
  2496. int singleMatFlags = CV_COVAR_ROWS | CV_COVAR_USE_AVG;
  2497. cv::Mat gold;
  2498. cv::randu(src,cv::Scalar(-128), cv::Scalar(128));
  2499. cv::Mat goldMean;
  2500. cv::reduce(src,goldMean,0 ,REDUCE_AVG, CV_32F);
  2501. cv::calcCovarMatrix(src,gold,goldMean,singleMatFlags,CV_32F);
  2502. std::vector<cv::Mat> srcVec;
  2503. for(size_t i = 0; i < vector_size; i++)
  2504. {
  2505. srcVec.push_back(src.row(static_cast<int>(i)).reshape(0,col_problem_size));
  2506. }
  2507. cv::Mat actual;
  2508. cv::Mat actualMean = goldMean.reshape(0, row_problem_size);
  2509. cv::calcCovarMatrix(srcVec, actual, actualMean,singleMatFlags,CV_32F);
  2510. cv::Mat diff;
  2511. cv::absdiff(gold, actual, diff);
  2512. cv::Scalar s = cv::sum(diff);
  2513. ASSERT_EQ(s.dot(s), 0.0);
  2514. cv::Mat meanDiff;
  2515. cv::absdiff(goldMean, actualMean.reshape(0,1), meanDiff);
  2516. cv::Scalar sDiff = cv::sum(meanDiff);
  2517. ASSERT_EQ(sDiff.dot(sDiff), 0.0);
  2518. }
  2519. TEST(Core_Pow, special)
  2520. {
  2521. for( int i = 0; i < 100; i++ )
  2522. {
  2523. int n = theRNG().uniform(1, 30);
  2524. Mat mtx0(1, n, CV_8S), mtx, result;
  2525. randu(mtx0, -5, 5);
  2526. int type = theRNG().uniform(0, 2) ? CV_64F : CV_32F;
  2527. double eps = type == CV_32F ? 1e-3 : 1e-10;
  2528. mtx0.convertTo(mtx, type);
  2529. // generate power from [-n, n] interval with 1/8 step - enough to check various cases.
  2530. const int max_pf = 3;
  2531. int pf = theRNG().uniform(0, max_pf*2+1);
  2532. double power = ((1 << pf) - (1 << (max_pf*2-1)))/16.;
  2533. int ipower = cvRound(power);
  2534. bool is_ipower = ipower == power;
  2535. cv::pow(mtx, power, result);
  2536. for( int j = 0; j < n; j++ )
  2537. {
  2538. double val = type == CV_32F ? (double)mtx.at<float>(j) : mtx.at<double>(j);
  2539. double r = type == CV_32F ? (double)result.at<float>(j) : result.at<double>(j);
  2540. double r0;
  2541. if( power == 0. )
  2542. r0 = 1;
  2543. else if( is_ipower )
  2544. {
  2545. r0 = 1;
  2546. for( int k = 0; k < std::abs(ipower); k++ )
  2547. r0 *= val;
  2548. if( ipower < 0 )
  2549. r0 = 1./r0;
  2550. }
  2551. else
  2552. r0 = std::pow(val, power);
  2553. if( cvIsInf(r0) )
  2554. {
  2555. ASSERT_TRUE(cvIsInf(r) != 0);
  2556. }
  2557. else if( cvIsNaN(r0) )
  2558. {
  2559. ASSERT_TRUE(cvIsNaN(r) != 0);
  2560. }
  2561. else
  2562. {
  2563. ASSERT_TRUE(cvIsInf(r) == 0 && cvIsNaN(r) == 0);
  2564. ASSERT_LT(fabs(r - r0), eps);
  2565. }
  2566. }
  2567. }
  2568. }
  2569. TEST(Core_Cholesky, accuracy64f)
  2570. {
  2571. const int n = 5;
  2572. Mat A(n, n, CV_64F), refA;
  2573. Mat mean(1, 1, CV_64F);
  2574. *mean.ptr<double>() = 10.0;
  2575. Mat dev(1, 1, CV_64F);
  2576. *dev.ptr<double>() = 10.0;
  2577. RNG rng(10);
  2578. rng.fill(A, RNG::NORMAL, mean, dev);
  2579. A = A*A.t();
  2580. A.copyTo(refA);
  2581. Cholesky(A.ptr<double>(), A.step, n, NULL, 0, 0);
  2582. for (int i = 0; i < A.rows; i++)
  2583. for (int j = i + 1; j < A.cols; j++)
  2584. A.at<double>(i, j) = 0.0;
  2585. EXPECT_LE(cvtest::norm(refA, A*A.t(), CV_RELATIVE_L2), FLT_EPSILON);
  2586. }
  2587. TEST(Core_QR_Solver, accuracy64f)
  2588. {
  2589. int m = 20, n = 18;
  2590. Mat A(m, m, CV_64F);
  2591. Mat B(m, n, CV_64F);
  2592. Mat mean(1, 1, CV_64F);
  2593. *mean.ptr<double>() = 10.0;
  2594. Mat dev(1, 1, CV_64F);
  2595. *dev.ptr<double>() = 10.0;
  2596. RNG rng(10);
  2597. rng.fill(A, RNG::NORMAL, mean, dev);
  2598. rng.fill(B, RNG::NORMAL, mean, dev);
  2599. A = A*A.t();
  2600. Mat solutionQR;
  2601. //solve system with square matrix
  2602. solve(A, B, solutionQR, DECOMP_QR);
  2603. EXPECT_LE(cvtest::norm(A*solutionQR, B, CV_RELATIVE_L2), FLT_EPSILON);
  2604. A = Mat(m, n, CV_64F);
  2605. B = Mat(m, n, CV_64F);
  2606. rng.fill(A, RNG::NORMAL, mean, dev);
  2607. rng.fill(B, RNG::NORMAL, mean, dev);
  2608. //solve normal system
  2609. solve(A, B, solutionQR, DECOMP_QR | DECOMP_NORMAL);
  2610. EXPECT_LE(cvtest::norm(A.t()*(A*solutionQR), A.t()*B, CV_RELATIVE_L2), FLT_EPSILON);
  2611. //solve overdeterminated system as a least squares problem
  2612. Mat solutionSVD;
  2613. solve(A, B, solutionQR, DECOMP_QR);
  2614. solve(A, B, solutionSVD, DECOMP_SVD);
  2615. EXPECT_LE(cvtest::norm(solutionQR, solutionSVD, CV_RELATIVE_L2), FLT_EPSILON);
  2616. //solve system with singular matrix
  2617. A = Mat(10, 10, CV_64F);
  2618. B = Mat(10, 1, CV_64F);
  2619. rng.fill(A, RNG::NORMAL, mean, dev);
  2620. rng.fill(B, RNG::NORMAL, mean, dev);
  2621. for (int i = 0; i < A.cols; i++)
  2622. A.at<double>(0, i) = A.at<double>(1, i);
  2623. ASSERT_FALSE(solve(A, B, solutionQR, DECOMP_QR));
  2624. }
  2625. TEST(Core_Solve, regression_11888)
  2626. {
  2627. cv::Matx<float, 3, 2> A(
  2628. 2, 1,
  2629. 3, 1,
  2630. 6, 1
  2631. );
  2632. cv::Vec<float, 3> b(4, 5, 7);
  2633. cv::Matx<float, 2, 1> xQR = A.solve(b, DECOMP_QR);
  2634. cv::Matx<float, 2, 1> xSVD = A.solve(b, DECOMP_SVD);
  2635. EXPECT_LE(cvtest::norm(xQR, xSVD, NORM_L2 | NORM_RELATIVE), 0.001);
  2636. cv::Matx<float, 2, 3> iA = A.inv(DECOMP_SVD);
  2637. EXPECT_LE(cvtest::norm(iA*A, Matx<float, 2, 2>::eye(), NORM_L2), 1e-3);
  2638. EXPECT_ANY_THROW({
  2639. /*cv::Matx<float, 2, 1> xLU =*/ A.solve(b, DECOMP_LU);
  2640. std::cout << "FATAL ERROR" << std::endl;
  2641. });
  2642. }
  2643. TEST(Core_Solve, Matx_2_2)
  2644. {
  2645. cv::Matx<float, 2, 2> A(
  2646. 2, 1,
  2647. 1, 1
  2648. );
  2649. cv::Vec<float, 2> b(4, 5);
  2650. cv::Matx<float, 2, 1> xLU = A.solve(b, DECOMP_LU);
  2651. cv::Matx<float, 2, 1> xQR = A.solve(b, DECOMP_QR);
  2652. cv::Matx<float, 2, 1> xSVD = A.solve(b, DECOMP_SVD);
  2653. EXPECT_LE(cvtest::norm(xQR, xSVD, NORM_L2 | NORM_RELATIVE), 1e-3);
  2654. EXPECT_LE(cvtest::norm(xQR, xLU, NORM_L2 | NORM_RELATIVE), 1e-3);
  2655. cv::Matx<float, 2, 2> iA = A.inv(DECOMP_SVD);
  2656. EXPECT_LE(cvtest::norm(iA*A, Matx<float, 2, 2>::eye(), NORM_L2), 1e-3);
  2657. }
  2658. TEST(Core_Solve, Matx_3_3)
  2659. {
  2660. cv::Matx<float, 3, 3> A(
  2661. 2, 1, 0,
  2662. 0, 1, 1,
  2663. 1, 0, 1
  2664. );
  2665. cv::Vec<float, 3> b(4, 5, 6);
  2666. cv::Matx<float, 3, 1> xLU = A.solve(b, DECOMP_LU);
  2667. cv::Matx<float, 3, 1> xQR = A.solve(b, DECOMP_QR);
  2668. cv::Matx<float, 3, 1> xSVD = A.solve(b, DECOMP_SVD);
  2669. EXPECT_LE(cvtest::norm(xQR, xSVD, NORM_L2 | NORM_RELATIVE), 1e-3);
  2670. EXPECT_LE(cvtest::norm(xQR, xLU, NORM_L2 | NORM_RELATIVE), 1e-3);
  2671. cv::Matx<float, 3, 3> iA = A.inv(DECOMP_SVD);
  2672. EXPECT_LE(cvtest::norm(iA*A, Matx<float, 3, 3>::eye(), NORM_L2), 1e-3);
  2673. }
  2674. TEST(Core_Solve, Matx_4_4)
  2675. {
  2676. cv::Matx<float, 4, 4> A(
  2677. 2, 1, 0, 4,
  2678. 0, 1, 1, 3,
  2679. 1, 0, 1, 2,
  2680. 2, 2, 0, 1
  2681. );
  2682. cv::Vec<float, 4> b(4, 5, 6, 7);
  2683. cv::Matx<float, 4, 1> xLU = A.solve(b, DECOMP_LU);
  2684. cv::Matx<float, 4, 1> xQR = A.solve(b, DECOMP_QR);
  2685. cv::Matx<float, 4, 1> xSVD = A.solve(b, DECOMP_SVD);
  2686. EXPECT_LE(cvtest::norm(xQR, xSVD, NORM_L2 | NORM_RELATIVE), 1e-3);
  2687. EXPECT_LE(cvtest::norm(xQR, xLU, NORM_L2 | NORM_RELATIVE), 1e-3);
  2688. cv::Matx<float, 4, 4> iA = A.inv(DECOMP_SVD);
  2689. EXPECT_LE(cvtest::norm(iA*A, Matx<float, 4, 4>::eye(), NORM_L2), 1e-3);
  2690. }
  2691. softdouble naiveExp(softdouble x)
  2692. {
  2693. int exponent = x.getExp();
  2694. int sign = x.getSign() ? -1 : 1;
  2695. if(sign < 0 && exponent >= 10) return softdouble::inf();
  2696. softdouble mantissa = x.getFrac();
  2697. //Taylor series for mantissa
  2698. uint64 fac[20] = {1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
  2699. 39916800, 479001600, 6227020800, 87178291200, 1307674368000,
  2700. 20922789888000, 355687428096000, 6402373705728000, 121645100408832000,
  2701. 2432902008176640000};
  2702. softdouble sum = softdouble::one();
  2703. // 21! > (2 ** 64)
  2704. for(int i = 20; i > 0; i--)
  2705. sum += pow(mantissa, softdouble(i))/softdouble(fac[i-1]);
  2706. if(exponent >= 0)
  2707. {
  2708. exponent = (1 << exponent);
  2709. return pow(sum, softdouble(exponent*sign));
  2710. }
  2711. else
  2712. {
  2713. if(sign < 0) sum = softdouble::one()/sum;
  2714. exponent = -exponent;
  2715. for(int j = 0; j < exponent; j++)
  2716. sum = sqrt(sum);
  2717. return sum;
  2718. }
  2719. }
  2720. static float makeFP32(int sign, int exponent, int significand)
  2721. {
  2722. Cv32suf x;
  2723. x.u = (unsigned)(((sign & 1) << 31) | ((exponent&255) << 23) | (significand & 0x7fffff));
  2724. return x.f;
  2725. }
  2726. static float makeRandomFP32(RNG& rng, int sign, int exprange)
  2727. {
  2728. if( sign == -1 )
  2729. sign = rng() % 2;
  2730. int exponent = rng() % exprange;
  2731. int significand = rng() % (1 << 23);
  2732. return makeFP32(sign, exponent, significand);
  2733. }
  2734. TEST(Core_SoftFloat, exp32)
  2735. {
  2736. //special cases
  2737. EXPECT_TRUE(exp( softfloat::nan()).isNaN());
  2738. EXPECT_TRUE(exp( softfloat::inf()).isInf());
  2739. EXPECT_EQ (exp(-softfloat::inf()), softfloat::zero());
  2740. //ln(FLT_MAX) ~ 88.722
  2741. const softfloat ln_max(88.722f);
  2742. vector<softfloat> inputs;
  2743. RNG rng(0);
  2744. inputs.push_back(softfloat::zero());
  2745. inputs.push_back(softfloat::one());
  2746. inputs.push_back(softfloat::min());
  2747. for(int i = 0; i < 50000; i++)
  2748. {
  2749. float x = makeRandomFP32(rng, -1, 10+127 //bigger exponent will produce inf
  2750. );
  2751. if(softfloat(x) > ln_max)
  2752. x = rng.uniform(0.0f, (float)ln_max);
  2753. inputs.push_back(softfloat(x));
  2754. }
  2755. for(size_t i = 0; i < inputs.size(); i++)
  2756. {
  2757. softfloat x(inputs[i]);
  2758. softfloat y = exp(x);
  2759. ASSERT_TRUE(!y.isNaN());
  2760. ASSERT_TRUE(!y.isInf());
  2761. ASSERT_GE(y, softfloat::zero());
  2762. softfloat ygood = naiveExp(x);
  2763. softfloat diff = abs(ygood - y);
  2764. const softfloat eps = softfloat::eps();
  2765. if(diff > eps)
  2766. {
  2767. ASSERT_LE(diff/max(abs(y), abs(ygood)), eps);
  2768. }
  2769. }
  2770. }
  2771. TEST(Core_SoftFloat, exp64)
  2772. {
  2773. //special cases
  2774. EXPECT_TRUE(exp( softdouble::nan()).isNaN());
  2775. EXPECT_TRUE(exp( softdouble::inf()).isInf());
  2776. EXPECT_EQ (exp(-softdouble::inf()), softdouble::zero());
  2777. //ln(DBL_MAX) ~ 709.7827
  2778. const softdouble ln_max(709.7827);
  2779. vector<softdouble> inputs;
  2780. RNG rng(0);
  2781. inputs.push_back(softdouble::zero());
  2782. inputs.push_back(softdouble::one());
  2783. inputs.push_back(softdouble::min());
  2784. for(int i = 0; i < 50000; i++)
  2785. {
  2786. Cv64suf x;
  2787. uint64 sign = rng() % 2;
  2788. uint64 exponent = rng() % (10 + 1023); //bigger exponent will produce inf
  2789. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  2790. x.u = (sign << 63) | (exponent << 52) | mantissa;
  2791. if(softdouble(x.f) > ln_max)
  2792. x.f = rng.uniform(0.0, (double)ln_max);
  2793. inputs.push_back(softdouble(x.f));
  2794. }
  2795. for(size_t i = 0; i < inputs.size(); i++)
  2796. {
  2797. softdouble x(inputs[i]);
  2798. softdouble y = exp(x);
  2799. ASSERT_TRUE(!y.isNaN());
  2800. ASSERT_TRUE(!y.isInf());
  2801. ASSERT_GE(y, softdouble::zero());
  2802. softdouble ygood = naiveExp(x);
  2803. softdouble diff = abs(ygood - y);
  2804. const softdouble eps = softdouble::eps();
  2805. if(diff > eps)
  2806. {
  2807. ASSERT_LE(diff/max(abs(y), abs(ygood)), softdouble(8192)*eps);
  2808. }
  2809. }
  2810. }
  2811. TEST(Core_SoftFloat, log32)
  2812. {
  2813. const int nValues = 50000;
  2814. RNG rng(0);
  2815. //special cases
  2816. EXPECT_TRUE(log(softfloat::nan()).isNaN());
  2817. for(int i = 0; i < nValues; i++)
  2818. {
  2819. softfloat x32(makeRandomFP32(rng, 1, 255));
  2820. ASSERT_TRUE(log(x32).isNaN());
  2821. }
  2822. EXPECT_TRUE(log(softfloat::zero()).isInf());
  2823. vector<softfloat> inputs;
  2824. inputs.push_back(softfloat::one());
  2825. inputs.push_back(softfloat(exp(softfloat::one())));
  2826. inputs.push_back(softfloat::min());
  2827. inputs.push_back(softfloat::max());
  2828. for(int i = 0; i < nValues; i++)
  2829. {
  2830. inputs.push_back(softfloat(makeRandomFP32(rng, 0, 255)));
  2831. }
  2832. for(size_t i = 0; i < inputs.size(); i++)
  2833. {
  2834. softfloat x(inputs[i]);
  2835. softfloat y = log(x);
  2836. ASSERT_TRUE(!y.isNaN());
  2837. ASSERT_TRUE(!y.isInf());
  2838. softfloat ex = exp(y);
  2839. softfloat diff = abs(ex - x);
  2840. // 88 is approx estimate of max exp() argument
  2841. ASSERT_TRUE(!ex.isInf() || (y > softfloat(88)));
  2842. const softfloat eps2 = softfloat().setExp(-17);
  2843. if(!ex.isInf() && diff > softfloat::eps())
  2844. {
  2845. ASSERT_LT(diff/max(abs(ex), x), eps2);
  2846. }
  2847. }
  2848. }
  2849. TEST(Core_SoftFloat, log64)
  2850. {
  2851. const int nValues = 50000;
  2852. RNG rng(0);
  2853. //special cases
  2854. EXPECT_TRUE(log(softdouble::nan()).isNaN());
  2855. for(int i = 0; i < nValues; i++)
  2856. {
  2857. Cv64suf x;
  2858. uint64 sign = 1;
  2859. uint64 exponent = rng() % 2047;
  2860. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  2861. x.u = (sign << 63) | (exponent << 52) | mantissa;
  2862. softdouble x64(x.f);
  2863. ASSERT_TRUE(log(x64).isNaN());
  2864. }
  2865. EXPECT_TRUE(log(softdouble::zero()).isInf());
  2866. vector<softdouble> inputs;
  2867. inputs.push_back(softdouble::one());
  2868. inputs.push_back(exp(softdouble::one()));
  2869. inputs.push_back(softdouble::min());
  2870. inputs.push_back(softdouble::max());
  2871. for(int i = 0; i < nValues; i++)
  2872. {
  2873. Cv64suf x;
  2874. uint64 sign = 0;
  2875. uint64 exponent = rng() % 2047;
  2876. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  2877. x.u = (sign << 63) | (exponent << 52) | mantissa;
  2878. inputs.push_back(softdouble(x.f));
  2879. }
  2880. for(size_t i = 0; i < inputs.size(); i++)
  2881. {
  2882. softdouble x(inputs[i]);
  2883. softdouble y = log(x);
  2884. ASSERT_TRUE(!y.isNaN());
  2885. ASSERT_TRUE(!y.isInf());
  2886. softdouble ex = exp(y);
  2887. softdouble diff = abs(ex - x);
  2888. // 700 is approx estimate of max exp() argument
  2889. ASSERT_TRUE(!ex.isInf() || (y > softdouble(700)));
  2890. const softdouble eps2 = softdouble().setExp(-41);
  2891. if(!ex.isInf() && diff > softdouble::eps())
  2892. {
  2893. ASSERT_LT(diff/max(abs(ex), x), eps2);
  2894. }
  2895. }
  2896. }
  2897. TEST(Core_SoftFloat, cbrt32)
  2898. {
  2899. vector<softfloat> inputs;
  2900. RNG rng(0);
  2901. inputs.push_back(softfloat::zero());
  2902. inputs.push_back(softfloat::one());
  2903. inputs.push_back(softfloat::max());
  2904. inputs.push_back(softfloat::min());
  2905. for(int i = 0; i < 50000; i++)
  2906. {
  2907. inputs.push_back(softfloat(makeRandomFP32(rng, -1, 255)));
  2908. }
  2909. for(size_t i = 0; i < inputs.size(); i++)
  2910. {
  2911. softfloat x(inputs[i]);
  2912. softfloat y = cbrt(x);
  2913. ASSERT_TRUE(!y.isNaN());
  2914. ASSERT_TRUE(!y.isInf());
  2915. softfloat cube = y*y*y;
  2916. softfloat diff = abs(x - cube);
  2917. const softfloat eps = softfloat::eps();
  2918. if(diff > eps)
  2919. {
  2920. ASSERT_LT(diff/max(abs(x), abs(cube)), softfloat(4)*eps);
  2921. }
  2922. }
  2923. }
  2924. TEST(Core_SoftFloat, pow32)
  2925. {
  2926. const softfloat zero = softfloat::zero(), one = softfloat::one();
  2927. const softfloat inf = softfloat::inf(), nan = softfloat::nan();
  2928. const size_t nValues = 5000;
  2929. RNG rng(0);
  2930. //x ** nan == nan
  2931. for(size_t i = 0; i < nValues; i++)
  2932. {
  2933. Cv32suf x;
  2934. x.u = rng();
  2935. ASSERT_TRUE(pow(softfloat(x.f), nan).isNaN());
  2936. }
  2937. //x ** inf check
  2938. for(size_t i = 0; i < nValues; i++)
  2939. {
  2940. Cv32suf x;
  2941. x.u = rng();
  2942. softfloat x32(x.f);
  2943. softfloat ax = abs(x32);
  2944. if(x32.isNaN())
  2945. {
  2946. ASSERT_TRUE(pow(x32, inf).isNaN());
  2947. }
  2948. if(ax > one)
  2949. {
  2950. ASSERT_TRUE(pow(x32, inf).isInf());
  2951. ASSERT_EQ (pow(x32, -inf), zero);
  2952. }
  2953. if(ax < one && ax > zero)
  2954. {
  2955. ASSERT_TRUE(pow(x32, -inf).isInf());
  2956. ASSERT_EQ (pow(x32, inf), zero);
  2957. }
  2958. }
  2959. //+-1 ** inf
  2960. EXPECT_TRUE(pow( one, inf).isNaN());
  2961. EXPECT_TRUE(pow(-one, inf).isNaN());
  2962. // x ** 0 == 1
  2963. for(size_t i = 0; i < nValues; i++)
  2964. {
  2965. Cv32suf x;
  2966. x.u = rng();
  2967. ASSERT_EQ(pow(softfloat(x.f), zero), one);
  2968. }
  2969. // x ** 1 == x
  2970. for(size_t i = 0; i < nValues; i++)
  2971. {
  2972. Cv32suf x;
  2973. x.u = rng();
  2974. softfloat x32(x.f);
  2975. softfloat val = pow(x32, one);
  2976. // don't compare val and x32 directly because x != x if x is nan
  2977. ASSERT_EQ(val.v, x32.v);
  2978. }
  2979. // nan ** y == nan, if y != 0
  2980. for(size_t i = 0; i < nValues; i++)
  2981. {
  2982. unsigned u = rng();
  2983. softfloat x32 = softfloat::fromRaw(u);
  2984. x32 = (x32 != softfloat::zero()) ? x32 : softfloat::min();
  2985. ASSERT_TRUE(pow(nan, x32).isNaN());
  2986. }
  2987. // nan ** 0 == 1
  2988. EXPECT_EQ(pow(nan, zero), one);
  2989. // inf ** y == 0, if y < 0
  2990. // inf ** y == inf, if y > 0
  2991. for(size_t i = 0; i < nValues; i++)
  2992. {
  2993. float x = makeRandomFP32(rng, 0, 255);
  2994. softfloat x32 = softfloat(x);
  2995. ASSERT_TRUE(pow( inf, x32).isInf());
  2996. ASSERT_TRUE(pow(-inf, x32).isInf());
  2997. ASSERT_EQ(pow( inf, -x32), zero);
  2998. ASSERT_EQ(pow(-inf, -x32), zero);
  2999. }
  3000. // x ** y == (-x) ** y, if y % 2 == 0
  3001. // x ** y == - (-x) ** y, if y % 2 == 1
  3002. // x ** y == nan, if x < 0 and y is not integer
  3003. for(size_t i = 0; i < nValues; i++)
  3004. {
  3005. softfloat x32(makeRandomFP32(rng, 1, 255));
  3006. softfloat y32(makeRandomFP32(rng, -1, 23+127 //bigger exponent produces integer numbers only
  3007. ));
  3008. int yi = cvRound(y32);
  3009. if(y32 != softfloat(yi))
  3010. ASSERT_TRUE(pow(x32, y32).isNaN());
  3011. else if(yi % 2)
  3012. ASSERT_EQ(pow(-x32, y32), -pow(x32, y32));
  3013. else
  3014. ASSERT_EQ(pow(-x32, y32), pow(x32, y32));
  3015. }
  3016. // (0 ** 0) == 1
  3017. EXPECT_EQ(pow(zero, zero), one);
  3018. // 0 ** y == inf, if y < 0
  3019. // 0 ** y == 0, if y > 0
  3020. for(size_t i = 0; i < nValues; i++)
  3021. {
  3022. softfloat x32(makeRandomFP32(rng, 0, 255));
  3023. ASSERT_TRUE(pow(zero, -x32).isInf());
  3024. if(x32 != one)
  3025. {
  3026. ASSERT_EQ(pow(zero, x32), zero);
  3027. }
  3028. }
  3029. }
  3030. TEST(Core_SoftFloat, pow64)
  3031. {
  3032. const softdouble zero = softdouble::zero(), one = softdouble::one();
  3033. const softdouble inf = softdouble::inf(), nan = softdouble::nan();
  3034. const size_t nValues = 5000;
  3035. RNG rng(0);
  3036. //x ** nan == nan
  3037. for(size_t i = 0; i < nValues; i++)
  3038. {
  3039. Cv64suf x;
  3040. x.u = ((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng);
  3041. ASSERT_TRUE(pow(softdouble(x.f), nan).isNaN());
  3042. }
  3043. //x ** inf check
  3044. for(size_t i = 0; i < nValues; i++)
  3045. {
  3046. Cv64suf x;
  3047. x.u = ((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng);
  3048. softdouble x64(x.f);
  3049. softdouble ax = abs(x64);
  3050. if(x64.isNaN())
  3051. {
  3052. ASSERT_TRUE(pow(x64, inf).isNaN());
  3053. }
  3054. if(ax > one)
  3055. {
  3056. ASSERT_TRUE(pow(x64, inf).isInf());
  3057. ASSERT_EQ(pow(x64, -inf), zero);
  3058. }
  3059. if(ax < one && ax > zero)
  3060. {
  3061. ASSERT_TRUE(pow(x64, -inf).isInf());
  3062. ASSERT_EQ(pow(x64, inf), zero);
  3063. }
  3064. }
  3065. //+-1 ** inf
  3066. EXPECT_TRUE(pow( one, inf).isNaN());
  3067. EXPECT_TRUE(pow(-one, inf).isNaN());
  3068. // x ** 0 == 1
  3069. for(size_t i = 0; i < nValues; i++)
  3070. {
  3071. Cv64suf x;
  3072. x.u = ((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng);
  3073. ASSERT_EQ(pow(softdouble(x.f), zero), one);
  3074. }
  3075. // x ** 1 == x
  3076. for(size_t i = 0; i < nValues; i++)
  3077. {
  3078. Cv64suf x;
  3079. x.u = ((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng);
  3080. softdouble x64(x.f);
  3081. softdouble val = pow(x64, one);
  3082. // don't compare val and x64 directly because x != x if x is nan
  3083. ASSERT_EQ(val.v, x64.v);
  3084. }
  3085. // nan ** y == nan, if y != 0
  3086. for(size_t i = 0; i < nValues; i++)
  3087. {
  3088. uint64 u = ((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng);
  3089. softdouble x64 = softdouble::fromRaw(u);
  3090. x64 = (x64 != softdouble::zero()) ? x64 : softdouble::min();
  3091. ASSERT_TRUE(pow(nan, x64).isNaN());
  3092. }
  3093. // nan ** 0 == 1
  3094. EXPECT_EQ(pow(nan, zero), one);
  3095. // inf ** y == 0, if y < 0
  3096. // inf ** y == inf, if y > 0
  3097. for(size_t i = 0; i < nValues; i++)
  3098. {
  3099. Cv64suf x;
  3100. uint64 sign = 0;
  3101. uint64 exponent = rng() % 2047;
  3102. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  3103. x.u = (sign << 63) | (exponent << 52) | mantissa;
  3104. softdouble x64(x.f);
  3105. ASSERT_TRUE(pow( inf, x64).isInf());
  3106. ASSERT_TRUE(pow(-inf, x64).isInf());
  3107. ASSERT_EQ(pow( inf, -x64), zero);
  3108. ASSERT_EQ(pow(-inf, -x64), zero);
  3109. }
  3110. // x ** y == (-x) ** y, if y % 2 == 0
  3111. // x ** y == - (-x) ** y, if y % 2 == 1
  3112. // x ** y == nan, if x < 0 and y is not integer
  3113. for(size_t i = 0; i < nValues; i++)
  3114. {
  3115. Cv64suf x;
  3116. uint64 sign = 1;
  3117. uint64 exponent = rng() % 2047;
  3118. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  3119. x.u = (sign << 63) | (exponent << 52) | mantissa;
  3120. softdouble x64(x.f);
  3121. Cv64suf y;
  3122. sign = rng() % 2;
  3123. //bigger exponent produces integer numbers only
  3124. //exponent = rng() % (52 + 1023);
  3125. //bigger exponent is too big
  3126. exponent = rng() % (23 + 1023);
  3127. mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  3128. y.u = (sign << 63) | (exponent << 52) | mantissa;
  3129. softdouble y64(y.f);
  3130. uint64 yi = cvRound(y64);
  3131. if(y64 != softdouble(yi))
  3132. ASSERT_TRUE(pow(x64, y64).isNaN());
  3133. else if(yi % 2)
  3134. ASSERT_EQ(pow(-x64, y64), -pow(x64, y64));
  3135. else
  3136. ASSERT_EQ(pow(-x64, y64), pow(x64, y64));
  3137. }
  3138. // (0 ** 0) == 1
  3139. EXPECT_EQ(pow(zero, zero), one);
  3140. // 0 ** y == inf, if y < 0
  3141. // 0 ** y == 0, if y > 0
  3142. for(size_t i = 0; i < nValues; i++)
  3143. {
  3144. Cv64suf x;
  3145. uint64 sign = 0;
  3146. uint64 exponent = rng() % 2047;
  3147. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  3148. x.u = (sign << 63) | (exponent << 52) | mantissa;
  3149. softdouble x64(x.f);
  3150. ASSERT_TRUE(pow(zero, -x64).isInf());
  3151. if(x64 != one)
  3152. {
  3153. ASSERT_EQ(pow(zero, x64), zero);
  3154. }
  3155. }
  3156. }
  3157. TEST(Core_SoftFloat, sincos64)
  3158. {
  3159. static const softdouble
  3160. two = softdouble(2), three = softdouble(3),
  3161. half = softdouble::one()/two,
  3162. zero = softdouble::zero(), one = softdouble::one(),
  3163. pi = softdouble::pi(), piby2 = pi/two, eps = softdouble::eps(),
  3164. sin45 = sqrt(two)/two, sin60 = sqrt(three)/two;
  3165. softdouble vstdAngles[] =
  3166. //x, sin(x), cos(x)
  3167. {
  3168. zero, zero, one,
  3169. pi/softdouble(6), half, sin60,
  3170. pi/softdouble(4), sin45, sin45,
  3171. pi/three, sin60, half,
  3172. };
  3173. vector<softdouble> stdAngles;
  3174. stdAngles.assign(vstdAngles, vstdAngles + 3*4);
  3175. static const softdouble stdEps = eps.setExp(-39);
  3176. const size_t nStdValues = 5000;
  3177. for(size_t i = 0; i < nStdValues; i++)
  3178. {
  3179. for(size_t k = 0; k < stdAngles.size()/3; k++)
  3180. {
  3181. softdouble x = stdAngles[k*3] + pi*softdouble(2*((int)i-(int)nStdValues/2));
  3182. softdouble s = stdAngles[k*3+1];
  3183. softdouble c = stdAngles[k*3+2];
  3184. ASSERT_LE(abs(sin(x) - s), stdEps);
  3185. ASSERT_LE(abs(cos(x) - c), stdEps);
  3186. //sin(x+pi/2) = cos(x)
  3187. ASSERT_LE(abs(sin(x + piby2) - c), stdEps);
  3188. //sin(x+pi) = -sin(x)
  3189. ASSERT_LE(abs(sin(x + pi) + s), stdEps);
  3190. //cos(x+pi/2) = -sin(x)
  3191. ASSERT_LE(abs(cos(x+piby2) + s), stdEps);
  3192. //cos(x+pi) = -cos(x)
  3193. ASSERT_LE(abs(cos(x+pi) + c), stdEps);
  3194. }
  3195. }
  3196. // sin(x) is NaN iff x ix NaN or Inf
  3197. EXPECT_TRUE(sin(softdouble::inf()).isNaN());
  3198. EXPECT_TRUE(sin(softdouble::nan()).isNaN());
  3199. vector<int> exponents;
  3200. exponents.push_back(0);
  3201. for(int i = 1; i < 52; i++)
  3202. {
  3203. exponents.push_back( i);
  3204. exponents.push_back(-i);
  3205. }
  3206. exponents.push_back(256); exponents.push_back(-256);
  3207. exponents.push_back(512); exponents.push_back(-512);
  3208. exponents.push_back(1022); exponents.push_back(-1022);
  3209. vector<softdouble> inputs;
  3210. RNG rng(0);
  3211. static const size_t nValues = 1 << 18;
  3212. for(size_t i = 0; i < nValues; i++)
  3213. {
  3214. softdouble x;
  3215. uint64 mantissa = (((long long int)((unsigned int)(rng)) << 32 ) | (unsigned int)(rng)) & ((1LL << 52) - 1);
  3216. x.v = mantissa;
  3217. x = x.setSign((rng() % 2) != 0);
  3218. x = x.setExp(exponents[rng() % exponents.size()]);
  3219. inputs.push_back(x);
  3220. }
  3221. for(size_t i = 0; i < inputs.size(); i++)
  3222. {
  3223. softdouble x = inputs[i];
  3224. int xexp = x.getExp();
  3225. softdouble randEps = eps.setExp(std::max(xexp-52, -46));
  3226. softdouble sx = sin(x);
  3227. softdouble cx = cos(x);
  3228. ASSERT_FALSE(sx.isInf()); ASSERT_FALSE(cx.isInf());
  3229. ASSERT_FALSE(sx.isNaN()); ASSERT_FALSE(cx.isNaN());
  3230. ASSERT_LE(abs(sx), one); ASSERT_LE(abs(cx), one);
  3231. ASSERT_LE(abs((sx*sx + cx*cx) - one), eps);
  3232. ASSERT_LE(abs(sin(x*two) - two*sx*cx), randEps);
  3233. ASSERT_LE(abs(cos(x*two) - (cx*cx - sx*sx)), randEps);
  3234. ASSERT_LE(abs(sin(-x) + sx), eps);
  3235. ASSERT_LE(abs(cos(-x) - cx), eps);
  3236. ASSERT_LE(abs(sin(x + piby2) - cx), randEps);
  3237. ASSERT_LE(abs(sin(x + pi) + sx), randEps);
  3238. ASSERT_LE(abs(cos(x+piby2) + sx), randEps);
  3239. ASSERT_LE(abs(cos(x+pi) + cx), randEps);
  3240. }
  3241. }
  3242. TEST(Core_SoftFloat, CvRound)
  3243. {
  3244. struct
  3245. {
  3246. uint64_t inVal;
  3247. int64_t out64;
  3248. int32_t out32;
  3249. } _values[] =
  3250. {
  3251. { 0x0123456789abcdefU, 0, 0 }, // 3.51270056408850369812238561681E-303
  3252. { 0x0000000000000000U, 0, 0 }, // 0
  3253. { 0x8000000000000000U, 0, 0 }, // -0
  3254. { 0x000123456789abcdU, 0, 0 }, // 1.5822747438273385725152200433E-309
  3255. { 0x800123456789abcdU, 0, 0 }, // -1.5822747438273385725152200433E-309
  3256. { 0x7ff0000000000000U, INT64_MAX, INT32_MAX }, // +inf
  3257. { 0xfff0000000000000U, INT64_MIN, INT32_MIN }, // -inf
  3258. { 0x7ff0000000000001U, INT64_MAX, INT32_MAX }, // nan(casts to maximum value)
  3259. { 0xfff0000000000001U, INT64_MAX, INT32_MAX }, // nan(casts to maximum value)
  3260. { 0x7ffa5a5a5a5a5a5aU, INT64_MAX, INT32_MAX }, // nan(casts to maximum value)
  3261. { 0xfffa5a5a5a5a5a5aU, INT64_MAX, INT32_MAX }, // nan(casts to maximum value)
  3262. { 0x7fe123456789abcdU, INT64_MAX, INT32_MAX }, // 9.627645455595956656406699747E307
  3263. { 0xffe123456789abcdU, INT64_MIN, INT32_MIN }, // -9.627645455595956656406699747E307
  3264. { 0x43ffffffffffffffU, INT64_MAX, INT32_MAX }, // (2^53-1)*2^12
  3265. { 0xc3ffffffffffffffU, INT64_MIN, INT32_MIN }, // -(2^53-1)*2^12
  3266. { 0x43f0000000000000U, INT64_MAX, INT32_MAX }, // 2^64
  3267. { 0xc3f0000000000000U, INT64_MIN, INT32_MIN }, // -2^64
  3268. { 0x43efffffffffffffU, INT64_MAX, INT32_MAX }, // (2^53-1)*2^11
  3269. { 0xc3efffffffffffffU, INT64_MIN, INT32_MIN }, // -(2^53-1)*2^11
  3270. { 0x43e0000000000000U, INT64_MAX, INT32_MAX }, // 2^63
  3271. { 0xc3e0000000000000U, -0x7fffffffffffffff-1, INT32_MIN }, // -2^63
  3272. { 0x43dfffffffffffffU, 0x7ffffffffffffc00, INT32_MAX }, // (2^53-1)*2^10
  3273. { 0xc3dfffffffffffffU, -0x7ffffffffffffc00, INT32_MIN }, // -(2^53-1)*2^10
  3274. { 0x433fffffffffffffU, 0x1fffffffffffff, INT32_MAX }, // (2^53-1)
  3275. { 0xc33fffffffffffffU, -0x1fffffffffffff, INT32_MIN }, // -(2^53-1)
  3276. { 0x432fffffffffffffU, 0x10000000000000, INT32_MAX }, // (2^52-1) + 0.5
  3277. { 0xc32fffffffffffffU, -0x10000000000000, INT32_MIN }, // -(2^52-1) - 0.5
  3278. { 0x431fffffffffffffU, 0x8000000000000, INT32_MAX }, // (2^51-1) + 0.75
  3279. { 0xc31fffffffffffffU, -0x8000000000000, INT32_MIN }, // -(2^51-1) - 0.75
  3280. { 0x431ffffffffffffeU, 0x8000000000000, INT32_MAX }, // (2^51-1) + 0.5
  3281. { 0xc31ffffffffffffeU, -0x8000000000000, INT32_MIN }, // -(2^51-1) - 0.5
  3282. { 0x431ffffffffffffdU, 0x7ffffffffffff, INT32_MAX }, // (2^51-1) + 0.25
  3283. { 0xc31ffffffffffffdU, -0x7ffffffffffff, INT32_MIN }, // -(2^51-1) - 0.25
  3284. { 0x41f0000000000000U, 0x100000000, INT32_MAX }, // 2^32 = 4294967296
  3285. { 0xc1f0000000000000U, -0x100000000, INT32_MIN }, // -2^32 = -4294967296
  3286. { 0x41efffffffffffffU, 0x100000000, INT32_MAX }, // 4294967295.99999952316284179688
  3287. { 0xc1efffffffffffffU, -0x100000000, INT32_MIN }, // -4294967295.99999952316284179688
  3288. { 0x41effffffff00000U, 0x100000000, INT32_MAX }, // (2^32-1) + 0.5 = 4294967295.5
  3289. { 0xc1effffffff00000U, -0x100000000, INT32_MIN }, // -(2^32-1) - 0.5 = -4294967295.5
  3290. { 0x41efffffffe00000U, 0xffffffffll, INT32_MAX }, // (2^32-1)
  3291. { 0xc1efffffffe00000U, -0xffffffffll, INT32_MIN }, // -(2^32-1)
  3292. { 0x41e0000000000000U, 0x80000000ll, INT32_MAX }, // 2^31 = 2147483648
  3293. { 0xc1e0000000000000U, -0x80000000ll, -0x7fffffff-1 }, // -2^31 = -2147483648
  3294. { 0x41dfffffffffffffU, 0x80000000ll, INT32_MAX }, // 2147483647.99999976158142089844
  3295. { 0xc1dfffffffffffffU, -0x80000000ll, -0x7fffffff-1 }, // -2147483647.99999976158142089844
  3296. { 0x41dffffffff00000U, 0x80000000ll, INT32_MAX }, // (2^31-1) + 0.75
  3297. { 0xc1dffffffff00000U, -0x80000000ll, -0x7fffffff-1 }, // -(2^31-1) - 0.75
  3298. { 0x41dfffffffe00001U, 0x80000000ll, INT32_MAX }, // (2^31-1) + 0.5 + 2^-22
  3299. { 0xc1dfffffffe00001U, -0x80000000ll, -0x7fffffff-1 }, // -(2^31-1) - 0.5 - 2^-22
  3300. { 0x41dfffffffe00000U, 0x80000000ll, INT32_MAX }, // (2^31-1) + 0.5
  3301. { 0xc1dfffffffe00000U, -0x80000000ll, -0x7fffffff-1 }, // -(2^31-1) - 0.5
  3302. { 0x41dfffffffdfffffU, 0x7fffffff, 0x7fffffff }, // (2^31-1) + 0.5 - 2^-22
  3303. { 0xc1dfffffffdfffffU, -0x7fffffff, -0x7fffffff }, // -(2^31-1) - 0.5 + 2^-22
  3304. { 0x41dfffffffd00000U, 0x7fffffff, 0x7fffffff }, // (2^31-1) + 0.25
  3305. { 0xc1dfffffffd00000U, -0x7fffffff, -0x7fffffff }, // -(2^31-1) - 0.25
  3306. { 0x41dfffffffc00000U, 0x7fffffff, 0x7fffffff }, // (2^31-1)
  3307. { 0xc1dfffffffc00000U, -0x7fffffff, -0x7fffffff }, // -(2^31-1)
  3308. { 0x41d0000000000000U, 0x40000000, 0x40000000 }, // 2^30 = 2147483648
  3309. { 0xc1d0000000000000U, -0x40000000, -0x40000000 }, // -2^30 = -2147483648
  3310. { 0x4006000000000000U, 3, 3 }, // 2.75
  3311. { 0xc006000000000000U, -3, -3 }, // -2.75
  3312. { 0x4004000000000001U, 3, 3 }, // 2.5 + 2^-51
  3313. { 0xc004000000000001U, -3, -3 }, // -2.5 - 2^-51
  3314. { 0x4004000000000000U, 2, 2 }, // 2.5
  3315. { 0xc004000000000000U, -2, -2 }, // -2.5
  3316. { 0x4003ffffffffffffU, 2, 2 }, // 2.5 - 2^-51
  3317. { 0xc003ffffffffffffU, -2, -2 }, // -2.5 + 2^-51
  3318. { 0x4002000000000000U, 2, 2 }, // 2.25
  3319. { 0xc002000000000000U, -2, -2 }, // -2.25
  3320. { 0x3ffc000000000000U, 2, 2 }, // 1.75
  3321. { 0xbffc000000000000U, -2, -2 }, // -1.75
  3322. { 0x3ff8000000000001U, 2, 2 }, // 1.5 + 2^-52
  3323. { 0xbff8000000000001U, -2, -2 }, // -1.5 - 2^-52
  3324. { 0x3ff8000000000000U, 2, 2 }, // 1.5
  3325. { 0xbff8000000000000U, -2, -2 }, // -1.5
  3326. { 0x3ff7ffffffffffffU, 1, 1 }, // 1.5 - 2^-52
  3327. { 0xbff7ffffffffffffU, -1, -1 }, // -1.5 + 2^-52
  3328. { 0x3ff4000000000000U, 1, 1 }, // 1.25
  3329. { 0xbff4000000000000U, -1, -1 }, // -1.25
  3330. { 0x3fe8000000000000U, 1, 1 }, // 0.75
  3331. { 0xbfe8000000000000U, -1, -1 }, // -0.75
  3332. { 0x3fe0000000000001U, 1, 1 }, // 0.5 + 2^-53
  3333. { 0xbfe0000000000001U, -1, -1 }, // -0.5 - 2^-53
  3334. { 0x3fe0000000000000U, 0, 0 }, // 0.5
  3335. { 0xbfe0000000000000U, 0, 0 }, // -0.5
  3336. { 0x3fd8000000000000U, 0, 0 }, // 0.375
  3337. { 0xbfd8000000000000U, 0, 0 }, // -0.375
  3338. { 0x3fd0000000000000U, 0, 0 }, // 0.25
  3339. { 0xbfd0000000000000U, 0, 0 }, // -0.25
  3340. { 0x0ff123456789abcdU, 0, 0 }, // 6.89918601543515033558134828315E-232
  3341. { 0x8ff123456789abcdU, 0, 0 } // -6.89918601543515033558134828315E-232
  3342. };
  3343. struct testvalues
  3344. {
  3345. softdouble inVal;
  3346. int64_t out64;
  3347. int32_t out32;
  3348. } *values = (testvalues*)_values;
  3349. for (int i = 0, maxi = sizeof(_values) / sizeof(_values[0]); i < maxi; i++)
  3350. {
  3351. EXPECT_EQ(values[i].out64, cvRound64(values[i].inVal));
  3352. EXPECT_EQ(values[i].out64, saturate_cast<int64_t>(values[i].inVal));
  3353. EXPECT_EQ((uint64_t)(values[i].out64), saturate_cast<uint64_t>(values[i].inVal));
  3354. EXPECT_EQ(values[i].out32, cvRound(values[i].inVal));
  3355. EXPECT_EQ(values[i].out32, saturate_cast<int32_t>(values[i].inVal));
  3356. EXPECT_EQ((uint32_t)(values[i].out32), saturate_cast<uint32_t>(values[i].inVal));
  3357. }
  3358. }
  3359. template<typename T>
  3360. static void checkRounding(T in, int outCeil, int outFloor)
  3361. {
  3362. EXPECT_EQ(outCeil,cvCeil(in));
  3363. EXPECT_EQ(outFloor,cvFloor(in));
  3364. /* cvRound is not expected to be IEEE compliant. The implementation
  3365. should round to one of the above. */
  3366. EXPECT_TRUE((cvRound(in) == outCeil) || (cvRound(in) == outFloor));
  3367. }
  3368. TEST(Core_FastMath, InlineRoundingOps)
  3369. {
  3370. struct
  3371. {
  3372. double in;
  3373. int outCeil;
  3374. int outFloor;
  3375. } values[] =
  3376. {
  3377. // Values are chosen to convert to binary float 32/64 exactly
  3378. { 1.0, 1, 1 },
  3379. { 1.5, 2, 1 },
  3380. { -1.5, -1, -2}
  3381. };
  3382. for (int i = 0, maxi = sizeof(values) / sizeof(values[0]); i < maxi; i++)
  3383. {
  3384. checkRounding<double>(values[i].in, values[i].outCeil, values[i].outFloor);
  3385. checkRounding<float>((float)values[i].in, values[i].outCeil, values[i].outFloor);
  3386. }
  3387. }
  3388. TEST(Core_FastMath, InlineNaN)
  3389. {
  3390. EXPECT_EQ( cvIsNaN((float) NAN), 1);
  3391. EXPECT_EQ( cvIsNaN((float) -NAN), 1);
  3392. EXPECT_EQ( cvIsNaN(0.0f), 0);
  3393. EXPECT_EQ( cvIsNaN((double) NAN), 1);
  3394. EXPECT_EQ( cvIsNaN((double) -NAN), 1);
  3395. EXPECT_EQ( cvIsNaN(0.0), 0);
  3396. }
  3397. TEST(Core_FastMath, InlineIsInf)
  3398. {
  3399. // Assume HUGE_VAL is infinity. Strictly speaking, may not always be true.
  3400. EXPECT_EQ( cvIsInf((float) HUGE_VAL), 1);
  3401. EXPECT_EQ( cvIsInf((float) -HUGE_VAL), 1);
  3402. EXPECT_EQ( cvIsInf(0.0f), 0);
  3403. EXPECT_EQ( cvIsInf((double) HUGE_VAL), 1);
  3404. EXPECT_EQ( cvIsInf((double) -HUGE_VAL), 1);
  3405. EXPECT_EQ( cvIsInf(0.0), 0);
  3406. }
  3407. }} // namespace
  3408. /* End of file. */