test_math.cpp 134 KB

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