mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Compare commits
1096 Commits
f7dd7df170
..
5.x
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d69623051 | |||
| 279bc4a279 | |||
| f968fb969f | |||
| 5aa9c9562a | |||
| 47d9544d90 | |||
| c2bf59ca0c | |||
| 5aff519a06 | |||
| 430909e2a3 | |||
| f07e06fd47 | |||
| 3701817083 | |||
| c64d89e75c | |||
| 507c824cd8 | |||
| 34074075b2 | |||
| 18f9bffb0d | |||
| 8ee67ccb65 | |||
| 60c705e93b | |||
| 5c7b438295 | |||
| 647b32ac7c | |||
| 2d2611d5bd | |||
| 3803eb828e | |||
| a88eac3223 | |||
| 4c936e6c18 | |||
| 42f41f749a | |||
| 526e42f355 | |||
| d94b6d0df3 | |||
| bb90bb0d64 | |||
| eec2c6fd3d | |||
| 60825757e4 | |||
| 56ae1e603b | |||
| 0fb620f0f0 | |||
| 8fdf15e26e | |||
| 498e4692d6 | |||
| 97c2c31d9a | |||
| bc647fe3ec | |||
| cbd227741f | |||
| 7559555599 | |||
| 4b38c5562b | |||
| aa1b8a2a21 | |||
| 112959651a | |||
| c86d642d19 | |||
| abb0115648 | |||
| 71d900dc36 | |||
| 9ce06a5675 | |||
| eafce2f0ce | |||
| 4ce2389a62 | |||
| 35bf0b4ac6 | |||
| d1264cc6ec | |||
| 0b5ff7b3a2 | |||
| f7ad23157f | |||
| 77dff6dc75 | |||
| 3d0ae71ac1 | |||
| 80da12e55a | |||
| bb96382942 | |||
| 854cf4225d | |||
| 100496b371 | |||
| e770c269b0 | |||
| bbfe2eb0de | |||
| ae93a81ec0 | |||
| db37d38eb4 | |||
| 3aadaa8385 | |||
| d82fbe3530 | |||
| 1439136ef8 | |||
| ee9c019556 | |||
| e39c6c6bcc | |||
| dcae1f1dc1 | |||
| c7b8fb28b6 | |||
| 5866bbd9ff | |||
| 80f48cc952 | |||
| e2f0876777 | |||
| 68fb8aeb30 | |||
| d36133b325 | |||
| 97f62825a2 | |||
| cb0b3d820b | |||
| 4d839a16f0 | |||
| 8b06f28e1b | |||
| 5d121b768f | |||
| ae3542afa4 | |||
| bb645944e2 | |||
| 01efb9f92b | |||
| c833519366 | |||
| 4ceb58f9f5 | |||
| c02b096a77 | |||
| bb3c1558e0 | |||
| b8e82fa2c2 | |||
| 81621ced10 | |||
| 5049343874 | |||
| 6fd1b687a1 | |||
| 48a063158a | |||
| 47eefa5abf | |||
| d939383524 | |||
| 7334957476 | |||
| f831c94309 | |||
| 6d2cd14bb2 | |||
| bc11496dcb | |||
| 72d21d7241 | |||
| 20d3018169 | |||
| 555f0901a3 | |||
| 3f45dab070 | |||
| a3a4d4adac | |||
| 8bbe8eeb86 | |||
| a18356853d | |||
| a8c0c30046 | |||
| 03539f67f5 | |||
| 9a966e96ad | |||
| 7b7a62528f | |||
| 4c8c215d59 | |||
| a3dc35d47d | |||
| 172ea5a00c | |||
| 845d95aaac | |||
| e32cab0e31 | |||
| f55665e5ca | |||
| 3f0664973c | |||
| c4caa07d62 | |||
| 410b6fdd97 | |||
| 43dd75bf43 | |||
| 40738fb16c | |||
| c9514a7783 | |||
| 79a9145c56 | |||
| 5b65e5ec15 | |||
| 2058f7b627 | |||
| 5e6a591357 | |||
| ded27244dd | |||
| afdf415c45 | |||
| 18abac7d02 | |||
| 7af8065580 | |||
| 49a4522ea9 | |||
| b7264acb69 | |||
| 64a18fbdc1 | |||
| 563dcf5b91 | |||
| 527f01449d | |||
| 04aee009aa | |||
| c9e7878a1d | |||
| 28df43c56e | |||
| 40ddc700aa | |||
| ada32973b4 | |||
| 35ac66291f | |||
| 37c9ab1815 | |||
| 0417b03bad | |||
| d9038ad00d | |||
| dd1a12c6ff | |||
| 29eec42012 | |||
| 6a66ec4df5 | |||
| fc3803c67b | |||
| a68b702ed5 | |||
| 9803eb0443 | |||
| 6a1a2754c8 | |||
| e3fc091de4 | |||
| b0b77e7b32 | |||
| a46c6d65d3 | |||
| a0a660fcb1 | |||
| 04ab09f6f3 | |||
| b67ad9a422 | |||
| 42fc6939f8 | |||
| 22cdc28471 | |||
| b7846531fe | |||
| 8e434d68f9 | |||
| a68e8d8289 | |||
| 1d4d81103e | |||
| e20acee958 | |||
| 89e0ca8749 | |||
| 8756e68bff | |||
| 9937cc22da | |||
| 4d0b381f03 | |||
| 46e8224cf0 | |||
| 61d49e12f6 | |||
| ad5829e55f | |||
| 59218f9edd | |||
| 14a475aa0b | |||
| 2995f2e191 | |||
| d4468bd7c0 | |||
| 75bb662258 | |||
| a3ced1a94b | |||
| 9d94a236a6 | |||
| 9f5028d53c | |||
| 98d75abf2d | |||
| b0027c938f | |||
| aac582119c | |||
| ccb808ba55 | |||
| a1ad509753 | |||
| 0c76634841 | |||
| 0908a2db6f | |||
| 27d5b2b8dd | |||
| e19b0ebc5c | |||
| 13dd2f5293 | |||
| dafe7cef97 | |||
| bf0cf34963 | |||
| 2405556989 | |||
| aed3df4ed9 | |||
| cd302920ee | |||
| ed47719ac4 | |||
| f251467b55 | |||
| bae8cb1915 | |||
| be2c53c2b7 | |||
| 9370343d50 | |||
| d8263a9899 | |||
| d8d1cc8c58 | |||
| c2594b41bf | |||
| 07e0dd2fbd | |||
| f0d44c0b45 | |||
| 3218dbb0ab | |||
| 62930a207b | |||
| f539c0907e | |||
| 133e218484 | |||
| 1c44eaf8bd | |||
| ac1ed5c160 | |||
| bdf348c13a | |||
| 104d987ca2 | |||
| 2c7e9ebbaf | |||
| c7b299a9a5 | |||
| ac70e5e8c9 | |||
| fe94255a5f | |||
| c9147d6e1f | |||
| 2bf262441f | |||
| 4d44d22d41 | |||
| e791995f10 | |||
| 0a8603b3ac | |||
| 1d54398f07 | |||
| 2d528c49d2 | |||
| 28f4e22bd7 | |||
| b745bbf539 | |||
| 657496cab4 | |||
| 7a23e57680 | |||
| 996713974c | |||
| c9070f9f35 | |||
| 7be1853b0b | |||
| 1e731a2e2a | |||
| 2f89729f2d | |||
| cc8f683b6a | |||
| f85a662563 | |||
| e739e0a7e8 | |||
| 8eeacc3cc6 | |||
| bd0bc5af59 | |||
| a7e02e5742 | |||
| 873a4635c6 | |||
| 851e0196b4 | |||
| 0ba56c3ecc | |||
| 914c0b2bc8 | |||
| 72e0bc2bf3 | |||
| 7b6dc220b1 | |||
| 223b110c30 | |||
| 2ad46b860b | |||
| 3cebf7d61e | |||
| 8cc3f68cd4 | |||
| cc2b7659b4 | |||
| 642a7307c4 | |||
| e519173241 | |||
| 2760c0c08a | |||
| 90fc83d926 | |||
| 8ea86e0445 | |||
| 5af1571073 | |||
| 0dbe5e7c35 | |||
| d089304bb9 | |||
| d2c2a82cc9 | |||
| ae1f3a991c | |||
| faf34f95af | |||
| c83b86eb57 | |||
| a17db08c21 | |||
| 237be03b7e | |||
| 457120bb94 | |||
| 0ba385abe4 | |||
| 7afa28bd1f | |||
| 75c56661d7 | |||
| 7bde3f9ae9 | |||
| 323ea1782d | |||
| aab70b9a63 | |||
| 50ba8fdbdb | |||
| fa0954db82 | |||
| d95badefa4 | |||
| 7fcfafff8b | |||
| 0102afa86f | |||
| 562628eb71 | |||
| 4e722f9904 | |||
| 5e315bcc97 | |||
| beec5c28df | |||
| 69020c6517 | |||
| 924a10069c | |||
| ad08edab42 | |||
| 7d3a764ba5 | |||
| c244bc3279 | |||
| 8dfc236476 | |||
| 1492b5e8a2 | |||
| 519b88cbc3 | |||
| 6751304b35 | |||
| c0ab6b69a8 | |||
| 6e8e90c664 | |||
| 99fc573913 | |||
| b883454620 | |||
| 5166a6b716 | |||
| 66e994d839 | |||
| a9e04ff9f1 | |||
| c44d03d8e1 | |||
| de851d24a5 | |||
| 3d77645a3a | |||
| 29746e2cd0 | |||
| 53d9a67cf3 | |||
| 1a6f669763 | |||
| 2ec6a6bb65 | |||
| 3d988eb7a9 | |||
| a49a293d3c | |||
| d0313879da | |||
| 48b39616b8 | |||
| 47ac80995f | |||
| e59506bbf5 | |||
| 44bf6a2db3 | |||
| 7514c4b770 | |||
| 7c64ea1e48 | |||
| 40ce5b4132 | |||
| ea485c628c | |||
| 78efccad75 | |||
| 185b48cfd6 | |||
| 2d15169ab5 | |||
| df7d437b86 | |||
| b5a7e0c662 | |||
| 7394d128c6 | |||
| 2dec80044b | |||
| f059d3b517 | |||
| 1b483ffea6 | |||
| 5c8d3b60f4 | |||
| e188ffd190 | |||
| 31cab2a055 | |||
| b54d0fbbbf | |||
| 7da3af2c41 | |||
| 95c66292b5 | |||
| 54b743dca8 | |||
| 2219b49a3a | |||
| 6c995c768f | |||
| a9da03f6c8 | |||
| ca69b54521 | |||
| 196a8afe76 | |||
| a0b7134d25 | |||
| 82ff8e45e9 | |||
| 6420d2b929 | |||
| 1719aa1339 | |||
| ca0d47c8e6 | |||
| 371b802103 | |||
| 9b57034c56 | |||
| abc9100c9b | |||
| d851f3bc80 | |||
| 9e06d19164 | |||
| bc67db9951 | |||
| 378b3c8742 | |||
| ac58382620 | |||
| eb36a78f5e | |||
| f48a12641e | |||
| 9a11c673a3 | |||
| 71c2b944a1 | |||
| 2ea31d5075 | |||
| d218732a70 | |||
| 4c8646bb78 | |||
| 111354bfef | |||
| e466110245 | |||
| f64d5771c1 | |||
| 5e874512e3 | |||
| 1c43a9418a | |||
| 3363599b66 | |||
| f79fbfa51c | |||
| 5ea5b5864d | |||
| 65b2fa9c2b | |||
| d771165f9d | |||
| 7408e349f4 | |||
| b258926e54 | |||
| 74fae2770e | |||
| 4eb5345e29 | |||
| bfc534e258 | |||
| 7bef50ba0b | |||
| 57970de586 | |||
| 15dc935190 | |||
| 1b6fb61b89 | |||
| d1da626502 | |||
| b8c9c070ea | |||
| 21b2c91814 | |||
| 1d7411e0f0 | |||
| e9298fb73e | |||
| c8eafa3ee4 | |||
| 27ac5f0cc6 | |||
| 473c250831 | |||
| 14eb474a75 | |||
| 82fe39760a | |||
| 98bf72b319 | |||
| 90a73210fc | |||
| 0fb49827c1 | |||
| 879218500d | |||
| cc400acefe | |||
| a489d9d557 | |||
| e794c11b0b | |||
| 91768f9a27 | |||
| f79f193a10 | |||
| 93385c6cdf | |||
| 66c9f569bd | |||
| 1c1d2f923b | |||
| 9c33ddea31 | |||
| 2470c07f1b | |||
| 9c75140b1b | |||
| 317ba5f176 | |||
| 4cb91806b1 | |||
| eb4e853134 | |||
| da8c313a90 | |||
| eac7e794ba | |||
| 62369ed8a0 | |||
| 6345a9b961 | |||
| 61f723e2de | |||
| 289c9accad | |||
| a6c88cde7f | |||
| 1a74264ee9 | |||
| 664096aafd | |||
| cdea2c3f76 | |||
| 4159c0ad98 | |||
| 9d232fe7f2 | |||
| 83b7a0caf7 | |||
| d79e95c018 | |||
| 6a9aa0aba2 | |||
| 07b7dd02cd | |||
| b6eff512c8 | |||
| 619f47d78a | |||
| 68a5aea843 | |||
| 96c2365d5f | |||
| 5185dfbaee | |||
| f3f9e70fe0 | |||
| aa0d486988 | |||
| cd4f2c2561 | |||
| 0b9ef2f2be | |||
| 16bb0600bd | |||
| 58a25ede74 | |||
| 57b813eaad | |||
| 8a039b4586 | |||
| bdab54f79e | |||
| abcfb3c1e7 | |||
| 59c87f3206 | |||
| 105a3c335b | |||
| cc1ddb5602 | |||
| 83b771f379 | |||
| 8562b15924 | |||
| 2d85996182 | |||
| f67ae273b3 | |||
| d1a5723864 | |||
| 7e6da007cd | |||
| cd20754910 | |||
| 99a8d4b762 | |||
| 86b9885c90 | |||
| defc988c0d | |||
| c41bc110aa | |||
| 71c7bf2366 | |||
| b00c38c57e | |||
| 8b2cda836d | |||
| 4e71abeaf6 | |||
| b35104d63d | |||
| d5f054cd43 | |||
| 87320416ce | |||
| 9bb330af5f | |||
| 38a72d57c1 | |||
| 120a46b0d1 | |||
| 46a4f6838e | |||
| 958ded3dcd | |||
| 0559a76c6b | |||
| 02f0779d0e | |||
| 094430c8f0 | |||
| 3f1402e081 | |||
| ffa32e2b4c | |||
| 6feee34c57 | |||
| a127abbbbd | |||
| 7e65c42964 | |||
| 3b2d7b3f1b | |||
| 56d7a7e4b3 | |||
| 5d6cce0b99 | |||
| d977b02297 | |||
| bd67770dcb | |||
| 06a78c2390 | |||
| 7a2f2a985f | |||
| 709eabda16 | |||
| 1c72264d00 | |||
| 2e6a0cab65 | |||
| 425d5cfcf0 | |||
| dd87ffc340 | |||
| ef9b42c05a | |||
| 4355309c3b | |||
| 350b211b57 | |||
| 74dae85a65 | |||
| 349b44a485 | |||
| cb87f05e4b | |||
| 736a73986b | |||
| f8de2e06e6 | |||
| ce1410e77c | |||
| 1df06488b1 | |||
| 3bfc408995 | |||
| bbd36a0ec1 | |||
| 7c17912426 | |||
| d8525e37d0 | |||
| 69b91cabb4 | |||
| a674ae1bce | |||
| 98cbe0ac49 | |||
| db2ba6a145 | |||
| 7635d9a012 | |||
| 4919cda8b2 | |||
| 77eb6ed52d | |||
| db40139f16 | |||
| b6b5a10a8e | |||
| b8a8b9e1dd | |||
| 1483504702 | |||
| 4d15b2a33f | |||
| b605fc13d8 | |||
| 48a7d8efbd | |||
| bf6f6d2db8 | |||
| b96e9fd1ce | |||
| 9bd246dd05 | |||
| 1623576a88 | |||
| 8badff598e | |||
| 603b1cafdf | |||
| 28deafcbd4 | |||
| a27b90c217 | |||
| 55a2ca58f0 | |||
| 6223bdbf7b | |||
| c99c7c3bfe | |||
| 162179748a | |||
| d229ac9c76 | |||
| 08042e0a67 | |||
| 41df003d06 | |||
| db43ffcd91 | |||
| 633ca0d6eb | |||
| c25f8024c0 | |||
| 76c2d01938 | |||
| f823143766 | |||
| 444d4c8360 | |||
| d666245695 | |||
| be1f3e8a7c | |||
| 0b4fdd729c | |||
| 616fd50947 | |||
| 816851c999 | |||
| 0c774c94f9 | |||
| ddfb9d1dc8 | |||
| 446787ab48 | |||
| 91a0bdb6ea | |||
| c69b5524ff | |||
| 95659ebe97 | |||
| 644cf0de08 | |||
| cb1e6250e6 | |||
| 69d0aacc2a | |||
| 2b28a6e205 | |||
| 3b1ec72cf5 | |||
| 22d4735de1 | |||
| 0c4fd4f7ee | |||
| 650f2c3da3 | |||
| a492068a3a | |||
| efbe580ff3 | |||
| 5b03d82814 | |||
| b476ed6d06 | |||
| b7dacbd5e3 | |||
| 18e8d69097 | |||
| 0213483c18 | |||
| b31bc1a295 | |||
| d0ccd85a02 | |||
| 85a844e9c2 | |||
| e1ba8f2659 | |||
| 2ba82c2c88 | |||
| ff142b8ef9 | |||
| 3672a14b42 | |||
| b9914065e8 | |||
| 939aac47a2 | |||
| d6b674a3de | |||
| 37e13f9dcf | |||
| 57b31e2d4b | |||
| 997a2bf0bb | |||
| f7483cd978 | |||
| 6e229bda2b | |||
| 83a1621527 | |||
| ae0a06c206 | |||
| 7808d50412 | |||
| 5a3e18973b | |||
| f85a51ed18 | |||
| d39810d5c5 | |||
| 5fe6b9c8f8 | |||
| ce7c0f0e65 | |||
| d0820dac38 | |||
| 2ed6d0f590 | |||
| ea0f9336e2 | |||
| 8b84fcb376 | |||
| db1aa3c8a9 | |||
| 1d420dc9c0 | |||
| b89c041227 | |||
| 0d7d045a3b | |||
| 206a30bce9 | |||
| d46280507e | |||
| cd5dbf9389 | |||
| 77b45145d1 | |||
| 0310b081f9 | |||
| dc1f7ea5cb | |||
| 3cc130db5d | |||
| 07d519fe88 | |||
| 614e250fd3 | |||
| 22f7002ed2 | |||
| c7a21dc5bf | |||
| e83a7fef9f | |||
| c445a000c9 | |||
| a4ab68f9f4 | |||
| 2d9c0c8592 | |||
| 979428d590 | |||
| 1ae304bb83 | |||
| a7bb17b092 | |||
| 3fac9a9d69 | |||
| 03983549fc | |||
| 286f7524bb | |||
| ef0d83643d | |||
| 25b67bc99e | |||
| 55105719dd | |||
| 853fa9dd40 | |||
| 7a5f12c630 | |||
| df06d2eac2 | |||
| 65a606966b | |||
| a59a66a2c7 | |||
| a95658f106 | |||
| 6a8300c1a0 | |||
| e44e3ab0a7 | |||
| 299aa14c4b | |||
| 66a29b422c | |||
| a2fa1d49a4 | |||
| 7b0a082dd4 | |||
| f217656916 | |||
| 331d327760 | |||
| 3b01a4d4e9 | |||
| 8a5ec4bf7b | |||
| 29e712ed93 | |||
| 05e7988e9c | |||
| d223e796f5 | |||
| 3a4c88c33e | |||
| 8e55659afe | |||
| 9f0c3f5b2b | |||
| a40ceff215 | |||
| 6648482b69 | |||
| 6e3c5db1c6 | |||
| 2f35847960 | |||
| 9773694527 | |||
| 1696819abb | |||
| 3cd57ea09e | |||
| e2f583a9ee | |||
| 12738deaef | |||
| 3c627b0a97 | |||
| 58fac15a98 | |||
| 08c6d00d96 | |||
| 5aa45e9053 | |||
| 70380a7988 | |||
| ef98c25d60 | |||
| 16ea1382f7 | |||
| d0e410da93 | |||
| 9dbfba0fd8 | |||
| 26985f1043 | |||
| ebc39adbe0 | |||
| 68a81888ec | |||
| a97c99e49f | |||
| 254db60667 | |||
| 56673d969a | |||
| ff9820ea5c | |||
| 79e0763d17 | |||
| 91775af2dd | |||
| b03dd764a1 | |||
| 110b701bba | |||
| 97681bdfce | |||
| ebf11d36f4 | |||
| ae52db549d | |||
| 916fb7df16 | |||
| a669c5cb03 | |||
| 886934dba8 | |||
| 2688248df7 | |||
| 6f18a10012 | |||
| 5901170c78 | |||
| 3bcab8db0a | |||
| 6c743f8e4b | |||
| 6ed4e7acae | |||
| 6dcf6d9dd1 | |||
| e66d38e15f | |||
| 51ace51ea5 | |||
| 0fa4b0ead2 | |||
| bd26d02908 | |||
| 4a81b4e51f | |||
| f9a297e52c | |||
| 8256ef3321 | |||
| 5c870bd5a2 | |||
| 938dabef0e | |||
| 4d5beef7db | |||
| fe1a4b61bc | |||
| 9daad187af | |||
| 317012e85e | |||
| cb3af0a08f | |||
| 2529af9719 | |||
| e823493af1 | |||
| 46b800f506 | |||
| f8a75bccab | |||
| b574db2cff | |||
| 99bc88c259 | |||
| 073488896e | |||
| 7bdc618697 | |||
| ce5823c5eb | |||
| 8263c804de | |||
| a18d793dbd | |||
| f8fb3a7f55 | |||
| f73560293f | |||
| babc669dba | |||
| ea8f091a08 | |||
| 82da334ff3 | |||
| 8b3b19d185 | |||
| a735660cc3 | |||
| 0f8bbf4677 | |||
| 8def9f75c8 | |||
| 81ab6a3fbd | |||
| 100db1bc0b | |||
| 41097a48ad | |||
| 050085c996 | |||
| 9dcac41c66 | |||
| 7d31463fea | |||
| 79a731aff0 | |||
| eee383fde8 | |||
| d69db7aac4 | |||
| 45fd4d8217 | |||
| a69cd7d6ba | |||
| f3cc5a9e1e | |||
| 7e8f2a1bc4 | |||
| 35eba9ca90 | |||
| 3dcc8c38b4 | |||
| f24e80297a | |||
| ca2d17758f | |||
| ae4c67e3a0 | |||
| 908c59ae25 | |||
| 7d12392a7d | |||
| 672a662dff | |||
| 459a9c60ed | |||
| 8ba70194b1 | |||
| b8f5c08306 | |||
| 88f05e49be | |||
| 060c24bec9 | |||
| d05047ae41 | |||
| fc9208cff5 | |||
| 420663498f | |||
| 9aa5f3f1db | |||
| 1d9ca7160b | |||
| 6a11847d57 | |||
| bd1f9cd1ed | |||
| 48b457f8c7 | |||
| fc85d2a551 | |||
| b083d36d68 | |||
| 96a8e6d76c | |||
| 55a2a945b6 | |||
| 9772ec861b | |||
| fef2c95472 | |||
| b39ca66a5d | |||
| 190eddf8c3 | |||
| 07ec6cb2c2 | |||
| 3abd9f2a28 | |||
| 12b8ed1443 | |||
| fd7cb1be85 | |||
| 719b49ffa9 | |||
| 26ea34c4cb | |||
| 759fc701ab | |||
| a2d2ea6536 | |||
| 70df023317 | |||
| 5bc450d211 | |||
| 1f874028fb | |||
| 6feb765ebb | |||
| f676cb3c62 | |||
| 9238eb2ab2 | |||
| 6af0394cd2 | |||
| 5bdc41964a | |||
| 5260b48695 | |||
| 48c31bddc4 | |||
| 17e6b3f931 | |||
| 021e5184bc | |||
| b637e3a66e | |||
| 4422bc9a7f | |||
| 039cf6592c | |||
| d231b4e362 | |||
| 76f607a44c | |||
| 94f4678d3a | |||
| 72ad06bcf3 | |||
| bbe86e6dea | |||
| f08933b051 | |||
| 4f81d78c39 | |||
| b5ffdd4673 | |||
| ac37f337d0 | |||
| 43d243dd0e | |||
| 65d86b2628 | |||
| c28342f7f2 | |||
| 18a78988a1 | |||
| 448375d1e7 | |||
| b009a63e6b | |||
| 9d14ce3739 | |||
| 3d88db02d4 | |||
| c3fdb9769d | |||
| 3def7d09bc | |||
| 153f147cde | |||
| 5c1fbc2d0f | |||
| 6b438835eb | |||
| 7c966efcad | |||
| db3e5620cd | |||
| 68967cf6d7 | |||
| 6699ca1a40 | |||
| 3e561d8353 | |||
| 869016d8b1 | |||
| 282c762ead | |||
| 0e1d326ed0 | |||
| f454303f6a | |||
| e8a52c7e94 | |||
| ab7ab7b6be | |||
| f2c3d4dfe3 | |||
| 3b02f3b7ae | |||
| a31f4f4040 | |||
| bfd1504de3 | |||
| 719830959c | |||
| 22b1b1edac | |||
| 244c771fb6 | |||
| 2e784bc7e6 | |||
| 5f98674fe3 | |||
| ba62811cc8 | |||
| 5144766380 | |||
| 87e0246bb0 | |||
| 5196b575fe | |||
| 753e2c1dfa | |||
| 82038be4cd | |||
| 65074651a4 | |||
| 56d586aa3e | |||
| b64ce1e7f1 | |||
| 357203facd | |||
| c1e2f16f91 | |||
| cb6d295f15 | |||
| eddace4d98 | |||
| 55426ee195 | |||
| 5319772a56 | |||
| f0323fdd1e | |||
| a33de44b0b | |||
| f8319de976 | |||
| d188319b82 | |||
| 8e342f8857 | |||
| aa9e80b07b | |||
| f2cf3c8890 | |||
| aa5ea340f7 | |||
| 213e1a4d9d | |||
| 11eac62ac3 | |||
| d2d6869a26 | |||
| 85cc02f4de | |||
| de29223217 | |||
| c6776ec136 | |||
| 216c6c3da1 | |||
| 8cbdd0c833 | |||
| 1d1faaabef | |||
| 81956ad83e | |||
| 0e47b05106 | |||
| 010772b492 | |||
| 92b940792a | |||
| a22130fbfa | |||
| e02d256ff3 | |||
| 161c402f02 | |||
| 40dfe8e8fe | |||
| 6722d4a524 | |||
| cb7d38b477 | |||
| 4c549b8707 | |||
| 093ed08892 | |||
| a0df2f5328 | |||
| fa745553bf | |||
| f084a229b4 | |||
| d4fd5157fa | |||
| 3125f9708d | |||
| 12b7aac1a0 | |||
| 0957437bbe | |||
| 201a753e4a | |||
| 52be0b64fb | |||
| fa3f1822ae | |||
| f96111ef05 | |||
| 466ad96b1d | |||
| 5ce0acce40 | |||
| 3a55f50133 | |||
| 3b85d5fac7 | |||
| 1d18aba587 | |||
| f05ef64df8 | |||
| 4930c9cebc | |||
| decf6538a2 | |||
| d6424233f0 | |||
| dcc4dcedba | |||
| f1e1145546 | |||
| 0e6b7f1656 | |||
| 775210e701 | |||
| 4e2c7221f2 | |||
| c739117a7c | |||
| 788c7252dc | |||
| 6c28d7140a | |||
| bae435a5a7 | |||
| 4b4c130f0a | |||
| 607d92858f | |||
| 3af68fa857 | |||
| fefbcfeb0b | |||
| 53aad98a1a | |||
| 34f34f6227 | |||
| 0e6430abcb | |||
| b71be65f57 | |||
| 8495910165 | |||
| 97620c053f | |||
| d789cb459c | |||
| 0976765c62 | |||
| 3a424b7f1c | |||
| 163d544ecf | |||
| c5ff405d94 | |||
| c3a37d0fcb | |||
| 416bf3253d | |||
| fdab565711 | |||
| a6748df587 | |||
| b47704eabc | |||
| 2311c14582 | |||
| 5f5fb11c66 | |||
| b5a189a978 | |||
| 518486ed3d | |||
| fa91c1445e | |||
| da28c62855 | |||
| 9ddf1e5c77 | |||
| 285108e2e1 | |||
| 802af10e44 | |||
| 7889ed7f80 | |||
| 36d688ec10 | |||
| eab8eb8f3b | |||
| 47188b7c7e | |||
| 0e8748746f | |||
| 4d695cd2f4 | |||
| 18f280b869 | |||
| 8595066afc | |||
| a484f39f47 | |||
| 1a3523d2d8 | |||
| cea26341a5 | |||
| eb717a7e91 | |||
| bd9a3ee161 | |||
| f987bf2961 | |||
| 5af40a0269 | |||
| 277b0231f2 | |||
| d24ffe9a65 | |||
| 67a3d35b4e | |||
| 0c55ed0ca8 | |||
| a792252b55 | |||
| f7ce715596 | |||
| 23dec329b4 | |||
| 29dc07b1f3 | |||
| e880d51e1c | |||
| 3c8e97ff6a | |||
| 1d530eb2e2 | |||
| 4500a5369c | |||
| f33598f55e | |||
| 285218915c | |||
| 8329c09ba8 | |||
| a42d879925 | |||
| 6904207b60 | |||
| 44c46e545a | |||
| 593a376566 | |||
| 8a62b03761 | |||
| d49958141e | |||
| 86c6e07326 | |||
| a423b07149 | |||
| 2407ab4e61 | |||
| a9d98bfb34 | |||
| d976272d23 | |||
| 7e3d56e2ff | |||
| 733fb673c8 | |||
| a09bb3c2f6 | |||
| b00ac7b07a | |||
| 95ab8517ae | |||
| a1820ff3d4 | |||
| 097b0245da | |||
| 52d82bb44a | |||
| 8b7e586faa | |||
| 8358efaca1 | |||
| 3aaa9251e9 | |||
| 6c2eba2877 | |||
| 67be6a334f | |||
| 5b97f6abec | |||
| 07b62376af | |||
| 3857173845 | |||
| 752e5fdc26 | |||
| 520bf4697e | |||
| f92a1aa07d | |||
| 44d6872837 | |||
| 9ba4bb7355 | |||
| f199cf91f3 | |||
| b1020639f1 | |||
| 8bfb419b0f | |||
| a8b4ffac50 | |||
| 8a43956a1b | |||
| bfc4bdd9d0 | |||
| 96e2d32618 | |||
| 487619e5fe | |||
| 335d7bd16e | |||
| 3a02561c40 | |||
| eb571b500b | |||
| 505bbab75b | |||
| 3cf3e3f6f7 | |||
| 232a83ecb8 | |||
| c25f776151 | |||
| 48c10620cb | |||
| 99d216c8d4 | |||
| a2593a392f | |||
| 4c1f9fb042 | |||
| 869123d6f9 | |||
| 02d864070a | |||
| 0b34d90dfa | |||
| 7bdacb8098 | |||
| d4e28f27b7 | |||
| 638a0788fe | |||
| 7ea095cc38 | |||
| d2603cbf94 | |||
| c2ab4c052d | |||
| 8d38922571 | |||
| ee8b414a1e | |||
| 75a8e3e956 | |||
| 3c3eba868a | |||
| 2ae7438c6b | |||
| 2b767f9bc8 | |||
| 9c78dc2490 | |||
| 94e5ae6043 | |||
| fd14b959cf | |||
| 492d9dba1e | |||
| 44c0b58258 | |||
| 6b2d1033bd | |||
| 162bd5be4c | |||
| d56e8f053f | |||
| bf8f7b4e57 | |||
| 4e1ce3e0eb | |||
| 770c0d1416 | |||
| c12d4c82df | |||
| bee410c748 | |||
| 83cfeb9f14 | |||
| 66fee4a8d2 | |||
| df490c6399 | |||
| b06544bd54 | |||
| 6e9ab70359 | |||
| 2f65a1b501 | |||
| 8b3d2a57ad | |||
| a99b4071a2 | |||
| 627e6a0447 | |||
| 6bffbe4938 | |||
| d5c45116cd | |||
| c4c47d91e4 | |||
| 08c268bfc5 | |||
| 0fbd58bef9 | |||
| 3d12581798 | |||
| aa5055261f | |||
| 899b4d1452 | |||
| e5d648d2d0 | |||
| 9c87d8bf9c | |||
| 4ba2b05df8 | |||
| 0a0714bd1b | |||
| 2c2d7774b9 | |||
| a0d5277e0d | |||
| 80c5d18f9c | |||
| 7d05f92855 | |||
| 9d6f388809 | |||
| 9c61d80bc4 | |||
| 4d9365990a | |||
| 5714868726 | |||
| 196e6aaa50 | |||
| b167115b5b | |||
| 5d04e5b063 | |||
| 6ab4659840 | |||
| 0cf0a5e9d4 | |||
| 4f0fe1de96 | |||
| 1470f90c2a | |||
| 6544c7b787 | |||
| fce4a19d0d | |||
| 7ba26ada12 | |||
| 91a7a4523a | |||
| 8c7dc1f6b7 | |||
| 14dedda023 | |||
| 19116471fe | |||
| bae9cef0b5 | |||
| 6b199bd1bb | |||
| ee893a08ef | |||
| 7a5f554bc4 | |||
| 4dc811946d | |||
| 5c0ac37163 | |||
| 958d3e8c60 | |||
| eff6d32337 | |||
| b91e0dca90 | |||
| b754406352 | |||
| fa73b91e39 | |||
| c105402dfc | |||
| fc628014bb | |||
| 4e691587ef | |||
| 263de1f86e | |||
| 703dea4817 | |||
| 178240ccf1 | |||
| c073e09956 | |||
| 71be47e04a | |||
| ed8696566b | |||
| 9668831c13 | |||
| 89e059d8ac | |||
| 6d06368760 | |||
| 65b0383059 | |||
| d6c699c014 | |||
| 9d2eabaaa2 | |||
| 3268cc46ba | |||
| d42665d9e2 | |||
| 1088d95c50 | |||
| 2ee9d21dae | |||
| 690725980c | |||
| d0310c2a6a | |||
| 9794ff1398 | |||
| 53e6a25b6f |
@@ -1,14 +0,0 @@
|
||||
name: 4.x
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
CodeQL:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-CodeQL.yaml@main
|
||||
with:
|
||||
target_branch: '4.x'
|
||||
workflow_branch: main
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
name: 5.x
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
CodeQL:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-CodeQL.yaml@main
|
||||
with:
|
||||
target_branch: '5.x'
|
||||
workflow_branch: main
|
||||
@@ -1,61 +0,0 @@
|
||||
name: PR:4.x
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 4.x
|
||||
|
||||
jobs:
|
||||
|
||||
Linux:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux.yaml@main
|
||||
with:
|
||||
workflow_branch: main
|
||||
|
||||
Linux-no-HAL:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux-NoHAL.yaml@main
|
||||
|
||||
Linux-Apline:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux-Alpine.yaml@main
|
||||
|
||||
Windows:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Windows.yaml@main
|
||||
with:
|
||||
workflow_branch: main
|
||||
|
||||
Ubuntu2404-ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-ARM64.yaml@main
|
||||
|
||||
Ubuntu2404-ARM64-Debug:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-ARM64-Debug.yaml@main
|
||||
|
||||
Ubuntu2004-x64-OpenVINO:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U20-OpenVINO.yaml@main
|
||||
|
||||
Ubuntu2004-x64-CUDA:
|
||||
if: "${{ contains(github.event.pull_request.labels.*.name, 'category: dnn') }} || ${{ contains(github.event.pull_request.labels.*.name, 'category: dnn (onnx)') }}"
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-U20-Cuda.yaml@main
|
||||
|
||||
macOS-ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-macOS-ARM64.yaml@main
|
||||
|
||||
macOS-x64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-macOS-x86_64.yaml@main
|
||||
|
||||
macOS-ARM64-Vulkan:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-macOS-ARM64-Vulkan.yaml@main
|
||||
|
||||
iOS:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-iOS.yaml@main
|
||||
|
||||
Android-SDK:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-4.x-Android-SDK.yaml@main
|
||||
|
||||
TIM-VX:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-timvx-backend-tests-4.x.yml@main
|
||||
|
||||
docs:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-docs.yaml@main
|
||||
|
||||
Linux-RISC-V-Clang:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-4.x-RISCV.yaml@main
|
||||
@@ -0,0 +1,62 @@
|
||||
name: PR:5.x
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 5.x
|
||||
|
||||
jobs:
|
||||
Linux:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux.yaml@main
|
||||
with:
|
||||
workflow_branch: 'main'
|
||||
|
||||
Linux-no-HAL:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux-NoHAL.yaml@main
|
||||
|
||||
Linux-Apline:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Linux-Alpine.yaml@main
|
||||
|
||||
Windows:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-Windows.yaml@main
|
||||
with:
|
||||
workflow_branch: main
|
||||
|
||||
Ubuntu2404-ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-ARM64.yaml@main
|
||||
|
||||
Ubuntu2404-ARM64-Debug:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-ARM64-Debug.yaml@main
|
||||
|
||||
Ubuntu2004-x64-OpenVINO:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-U20-OpenVINO.yaml@main
|
||||
|
||||
Ubuntu2004-x64-CUDA:
|
||||
if: "${{ contains(github.event.pull_request.labels.*.name, 'category: dnn') }} || ${{ contains(github.event.pull_request.labels.*.name, 'category: dnn (onnx)') }}"
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-U20-Cuda.yaml@main
|
||||
|
||||
# Vulkan configuration disabled as Vulkan backend for DNN does not support int/int64 for now
|
||||
# Details: https://github.com/opencv/opencv/issues/25110
|
||||
# Windows10-x64-Vulkan:
|
||||
# uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-W10-Vulkan.yaml@main
|
||||
|
||||
macOS-ARM64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-macOS-ARM64.yaml@main
|
||||
|
||||
# macOS-ARM64-Vulkan:
|
||||
# uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-macOS-ARM64-Vulkan.yaml@main
|
||||
|
||||
macOS-x64:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-macOS-x86_64.yaml@main
|
||||
|
||||
iOS:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-iOS.yaml@main
|
||||
|
||||
Android:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-Android.yaml@main
|
||||
|
||||
docs:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-docs.yaml@main
|
||||
|
||||
Linux-RISC-V-Clang:
|
||||
uses: opencv/ci-gha-workflow/.github/workflows/OCV-PR-5.x-RISCV.yaml@main
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
# CMake file for opencv_lapack. See root CMakeLists.txt
|
||||
#
|
||||
# ----------------------------------------------------------------------------
|
||||
project(clapack)
|
||||
|
||||
# TODO: extract it from sources somehow
|
||||
set(CLAPACK_VERSION "3.9.0" PARENT_SCOPE)
|
||||
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
|
||||
# The .cpp files:
|
||||
file(GLOB lapack_srcs src/*.c)
|
||||
file(GLOB runtime_srcs runtime/*.c)
|
||||
file(GLOB lib_hdrs include/*.h)
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
# Define the library target:
|
||||
# ----------------------------------------------------------------------------------
|
||||
|
||||
set(the_target "libclapack")
|
||||
|
||||
add_library(${the_target} STATIC ${lapack_srcs} ${runtime_srcs} ${lib_hdrs})
|
||||
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS -Wno-parentheses -Wno-uninitialized -Wno-array-bounds
|
||||
-Wno-implicit-function-declaration -Wno-unused -Wunused-parameter -Wstringop-truncation
|
||||
-Wtautological-negation-compare) # gcc/clang warnings
|
||||
ocv_warnings_disable(CMAKE_C_FLAGS /wd4244 /wd4554 /wd4723 /wd4819) # visual studio warnings
|
||||
|
||||
set_target_properties(${the_target}
|
||||
PROPERTIES OUTPUT_NAME ${the_target}
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
COMPILE_PDB_NAME ${the_target}
|
||||
COMPILE_PDB_NAME_DEBUG "${the_target}${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}
|
||||
)
|
||||
|
||||
set(CLAPACK_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
|
||||
set(CLAPACK_LIBRARIES ${the_target} PARENT_SCOPE)
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${the_target} PROPERTIES FOLDER "3rdparty")
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
ocv_install_target(${the_target} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
|
||||
endif()
|
||||
|
||||
ocv_install_3rdparty_licenses(clapack lapack_LICENSE)
|
||||
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
#ifndef __CBLAS_H__
|
||||
#define __CBLAS_H__
|
||||
|
||||
/* most of the stuff is in lapacke.h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct lapack_complex
|
||||
{
|
||||
float r, i;
|
||||
} lapack_complex;
|
||||
|
||||
typedef struct lapack_doublecomplex
|
||||
{
|
||||
double r, i;
|
||||
} lapack_doublecomplex;
|
||||
|
||||
typedef enum {CblasRowMajor=101, CblasColMajor=102} CBLAS_LAYOUT;
|
||||
typedef enum {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113} CBLAS_TRANSPOSE;
|
||||
|
||||
void cblas_xerbla(const CBLAS_LAYOUT layout, int info,
|
||||
const char *rout, const char *form, ...);
|
||||
|
||||
void cblas_sgemm(CBLAS_LAYOUT layout, CBLAS_TRANSPOSE TransA,
|
||||
CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const float alpha, const float *A,
|
||||
const int lda, const float *B, const int ldb,
|
||||
const float beta, float *C, const int ldc);
|
||||
|
||||
void cblas_dgemm(CBLAS_LAYOUT layout, CBLAS_TRANSPOSE TransA,
|
||||
CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const double alpha, const double *A,
|
||||
const int lda, const double *B, const int ldb,
|
||||
const double beta, double *C, const int ldc);
|
||||
|
||||
void cblas_cgemm(CBLAS_LAYOUT layout, CBLAS_TRANSPOSE TransA,
|
||||
CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const void *alpha, const void *A,
|
||||
const int lda, const void *B, const int ldb,
|
||||
const void *beta, void *C, const int ldc);
|
||||
|
||||
void cblas_zgemm(CBLAS_LAYOUT layout, CBLAS_TRANSPOSE TransA,
|
||||
CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const void *alpha, const void *A,
|
||||
const int lda, const void *B, const int ldb,
|
||||
const void *beta, void *C, const int ldc);
|
||||
|
||||
int xerbla_(char *, int *);
|
||||
int lsame_(char *, char *);
|
||||
double slamch_(char* cmach);
|
||||
double slamc3_(float *a, float *b);
|
||||
double dlamch_(char* cmach);
|
||||
double dlamc3_(double *a, double *b);
|
||||
|
||||
int dgels_(char *trans, int *m, int *n, int *nrhs, double *a,
|
||||
int *lda, double *b, int *ldb, double *work, int *lwork, int *info);
|
||||
|
||||
int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv,
|
||||
double *b, int *ldb, int *info);
|
||||
|
||||
int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv,
|
||||
int *info);
|
||||
|
||||
int dposv_(char *uplo, int *n, int *nrhs, double *a, int *
|
||||
lda, double *b, int *ldb, int *info);
|
||||
|
||||
int dpotrf_(char *uplo, int *n, double *a, int *lda, int *
|
||||
info);
|
||||
|
||||
int sgels_(char *trans, int *m, int *n, int *nrhs, float *a,
|
||||
int *lda, float *b, int *ldb, float *work, int *lwork, int *info);
|
||||
|
||||
int sgeev_(char *jobvl, char *jobvr, int *n, float *a, int *
|
||||
lda, float *wr, float *wi, float *vl, int *ldvl, float *vr, int *
|
||||
ldvr, float *work, int *lwork, int *info);
|
||||
|
||||
int sgeqrf_(int *m, int *n, float *a, int *lda, float *tau,
|
||||
float *work, int *lwork, int *info);
|
||||
|
||||
int sgesv_(int *n, int *nrhs, float *a, int *lda, int *ipiv,
|
||||
float *b, int *ldb, int *info);
|
||||
|
||||
int sgetrf_(int *m, int *n, float *a, int *lda, int *ipiv,
|
||||
int *info);
|
||||
|
||||
int sposv_(char *uplo, int *n, int *nrhs, float *a, int *
|
||||
lda, float *b, int *ldb, int *info);
|
||||
|
||||
int spotrf_(char *uplo, int *n, float *a, int *lda, int *
|
||||
info);
|
||||
|
||||
int sgesdd_(char *jobz, int *m, int *n, float *a, int *lda,
|
||||
float *s, float *u, int *ldu, float *vt, int *ldvt, float *work,
|
||||
int *lwork, int *iwork, int *info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CBLAS_H__ */
|
||||
Vendored
+129
@@ -0,0 +1,129 @@
|
||||
/* f2c.h -- Standard Fortran to C header file */
|
||||
|
||||
/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
|
||||
|
||||
- From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
|
||||
|
||||
#ifndef __F2C_H__
|
||||
#define __F2C_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cblas.h"
|
||||
#include "lapack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#undef complex
|
||||
|
||||
typedef int integer;
|
||||
typedef unsigned int uinteger;
|
||||
typedef char *address;
|
||||
typedef short int shortint;
|
||||
typedef float real;
|
||||
typedef double doublereal;
|
||||
typedef lapack_complex complex;
|
||||
typedef lapack_doublecomplex doublecomplex;
|
||||
typedef int logical;
|
||||
typedef short int shortlogical;
|
||||
typedef char logical1;
|
||||
typedef char integer1;
|
||||
|
||||
#define TRUE_ (1)
|
||||
#define FALSE_ (0)
|
||||
|
||||
#ifndef abs
|
||||
#define abs(x) ((x) >= 0 ? (x) : -(x))
|
||||
#endif
|
||||
#define dabs(x) (double)abs(x)
|
||||
#ifndef min
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(a,b) ((a) >= (b) ? (a) : (b))
|
||||
#endif
|
||||
#define dmin(a,b) (double)min(a,b)
|
||||
#define dmax(a,b) (double)max(a,b)
|
||||
#define bit_test(a,b) ((a) >> (b) & 1)
|
||||
#define bit_clear(a,b) ((a) & ~((uinteger)1 << (b)))
|
||||
#define bit_set(a,b) ((a) | ((uinteger)1 << (b)))
|
||||
|
||||
static __inline double r_lg10(float *x)
|
||||
{
|
||||
return 0.43429448190325182765*log(*x);
|
||||
}
|
||||
|
||||
static __inline double d_lg10(double *x)
|
||||
{
|
||||
return 0.43429448190325182765*log(*x);
|
||||
}
|
||||
|
||||
static __inline double d_sign(double *a, double *b)
|
||||
{
|
||||
double x = fabs(*a);
|
||||
return *b >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
static __inline double r_sign(float *a, float *b)
|
||||
{
|
||||
double x = fabs((double)*a);
|
||||
return *b >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
static __inline int i_nint(float *x)
|
||||
{
|
||||
return (int)(*x >= 0 ? floor(*x + .5) : -floor(.5 - *x));
|
||||
}
|
||||
|
||||
int pow_ii(int *ap, int *bp);
|
||||
double pow_di(double *ap, int *bp);
|
||||
static __inline double pow_ri(float *ap, int *bp)
|
||||
{
|
||||
double apd = *ap;
|
||||
return pow_di(&apd, bp);
|
||||
}
|
||||
static __inline double pow_dd(double *ap, double *bp)
|
||||
{
|
||||
return pow(*ap, *bp);
|
||||
}
|
||||
|
||||
static __inline void d_cnjg(doublecomplex *r, doublecomplex *z)
|
||||
{
|
||||
double zi = z->i;
|
||||
r->r = z->r;
|
||||
r->i = -zi;
|
||||
}
|
||||
|
||||
static __inline void r_cnjg(complex *r, complex *z)
|
||||
{
|
||||
float zi = z->i;
|
||||
r->r = z->r;
|
||||
r->i = -zi;
|
||||
}
|
||||
|
||||
static __inline int s_copy(char *a, char *b, int maxlen)
|
||||
{
|
||||
strncpy(a, b, maxlen);
|
||||
a[maxlen] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int s_cat(char *lp, char **rpp, int* rnp, int *np);
|
||||
int s_cmp(char *a0, char *b0);
|
||||
static __inline int i_len(char* s)
|
||||
{
|
||||
return (int)strlen(s);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
+386
@@ -0,0 +1,386 @@
|
||||
// this is auto-generated header for Lapack subset
|
||||
#ifndef __CLAPACK_H__
|
||||
#define __CLAPACK_H__
|
||||
|
||||
#include "cblas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int cgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, lapack_complex *alpha, lapack_complex *a, int *lda, lapack_complex *b, int *ldb,
|
||||
lapack_complex *beta, lapack_complex *c__, int *ldc);
|
||||
|
||||
int daxpy_(int *n, double *da, double *dx, int *incx, double
|
||||
*dy, int *incy);
|
||||
|
||||
int dbdsdc_(char *uplo, char *compq, int *n, double *d__,
|
||||
double *e, double *u, int *ldu, double *vt, int *ldvt, double *q, int
|
||||
*iq, double *work, int *iwork, int *info);
|
||||
|
||||
int dbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *
|
||||
ncc, double *d__, double *e, double *vt, int *ldvt, double *u, int *
|
||||
ldu, double *c__, int *ldc, double *work, int *info);
|
||||
|
||||
int dcombssq_(double *v1, double *v2);
|
||||
|
||||
int dcopy_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy);
|
||||
|
||||
double ddot_(int *n, double *dx, int *incx, double *dy, int *incy);
|
||||
|
||||
int dgebak_(char *job, char *side, int *n, int *ilo, int *
|
||||
ihi, double *scale, int *m, double *v, int *ldv, int *info);
|
||||
|
||||
int dgebal_(char *job, int *n, double *a, int *lda, int *ilo,
|
||||
int *ihi, double *scale, int *info);
|
||||
|
||||
int dgebd2_(int *m, int *n, double *a, int *lda, double *d__,
|
||||
double *e, double *tauq, double *taup, double *work, int *info);
|
||||
|
||||
int dgebrd_(int *m, int *n, double *a, int *lda, double *d__,
|
||||
double *e, double *tauq, double *taup, double *work, int *lwork, int
|
||||
*info);
|
||||
|
||||
int dgeev_(char *jobvl, char *jobvr, int *n, double *a, int *
|
||||
lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *
|
||||
ldvr, double *work, int *lwork, int *info);
|
||||
|
||||
int dgehd2_(int *n, int *ilo, int *ihi, double *a, int *lda,
|
||||
double *tau, double *work, int *info);
|
||||
|
||||
int dgehrd_(int *n, int *ilo, int *ihi, double *a, int *lda,
|
||||
double *tau, double *work, int *lwork, int *info);
|
||||
|
||||
int dgelq2_(int *m, int *n, double *a, int *lda, double *tau,
|
||||
double *work, int *info);
|
||||
|
||||
int dgelqf_(int *m, int *n, double *a, int *lda, double *tau,
|
||||
double *work, int *lwork, int *info);
|
||||
|
||||
int dgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, double *alpha, double *a, int *lda, double *b, int *ldb, double *
|
||||
beta, double *c__, int *ldc);
|
||||
|
||||
int dgemv_(char *trans, int *m, int *n, double *alpha,
|
||||
double *a, int *lda, double *x, int *incx, double *beta, double *y,
|
||||
int *incy);
|
||||
|
||||
int dgeqr2_(int *m, int *n, double *a, int *lda, double *tau,
|
||||
double *work, int *info);
|
||||
|
||||
int dgeqrf_(int *m, int *n, double *a, int *lda, double *tau,
|
||||
double *work, int *lwork, int *info);
|
||||
|
||||
int dger_(int *m, int *n, double *alpha, double *x, int *
|
||||
incx, double *y, int *incy, double *a, int *lda);
|
||||
|
||||
int dgesdd_(char *jobz, int *m, int *n, double *a, int *lda,
|
||||
double *s, double *u, int *ldu, double *vt, int *ldvt, double *work,
|
||||
int *lwork, int *iwork, int *info);
|
||||
|
||||
int dhseqr_(char *job, char *compz, int *n, int *ilo, int *
|
||||
ihi, double *h__, int *ldh, double *wr, double *wi, double *z__, int *
|
||||
ldz, double *work, int *lwork, int *info);
|
||||
|
||||
int disnan_(double *din);
|
||||
|
||||
// "small" is a macro defined in Windows headers: https://stackoverflow.com/a/27794577
|
||||
#ifdef small
|
||||
#undef small
|
||||
#endif
|
||||
|
||||
int dlabad_(double *small, double *large);
|
||||
|
||||
int dlabrd_(int *m, int *n, int *nb, double *a, int *lda,
|
||||
double *d__, double *e, double *tauq, double *taup, double *x, int *
|
||||
ldx, double *y, int *ldy);
|
||||
|
||||
int dlacpy_(char *uplo, int *m, int *n, double *a, int *lda,
|
||||
double *b, int *ldb);
|
||||
|
||||
int dladiv1_(double *a, double *b, double *c__, double *d__,
|
||||
double *p, double *q);
|
||||
|
||||
double dladiv2_(double *a, double *b, double *c__, double *d__, double *r__,
|
||||
double *t);
|
||||
|
||||
int dladiv_(double *a, double *b, double *c__, double *d__,
|
||||
double *p, double *q);
|
||||
|
||||
int dlaed6_(int *kniter, int *orgati, double *rho, double *
|
||||
d__, double *z__, double *finit, double *tau, int *info);
|
||||
|
||||
int dlaexc_(int *wantq, int *n, double *t, int *ldt, double *
|
||||
q, int *ldq, int *j1, int *n1, int *n2, double *work, int *info);
|
||||
|
||||
int dlahqr_(int *wantt, int *wantz, int *n, int *ilo, int *
|
||||
ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int *
|
||||
ihiz, double *z__, int *ldz, int *info);
|
||||
|
||||
int dlahr2_(int *n, int *k, int *nb, double *a, int *lda,
|
||||
double *tau, double *t, int *ldt, double *y, int *ldy);
|
||||
|
||||
int dlaisnan_(double *din1, double *din2);
|
||||
|
||||
int dlaln2_(int *ltrans, int *na, int *nw, double *smin,
|
||||
double *ca, double *a, int *lda, double *d1, double *d2, double *b,
|
||||
int *ldb, double *wr, double *wi, double *x, int *ldx, double *scale,
|
||||
double *xnorm, int *info);
|
||||
|
||||
int dlamrg_(int *n1, int *n2, double *a, int *dtrd1, int *
|
||||
dtrd2, int *index);
|
||||
|
||||
double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work);
|
||||
|
||||
double dlanst_(char *norm, int *n, double *d__, double *e);
|
||||
|
||||
int dlanv2_(double *a, double *b, double *c__, double *d__,
|
||||
double *rt1r, double *rt1i, double *rt2r, double *rt2i, double *cs,
|
||||
double *sn);
|
||||
|
||||
double dlapy2_(double *x, double *y);
|
||||
|
||||
int dlaqr0_(int *wantt, int *wantz, int *n, int *ilo, int *
|
||||
ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int *
|
||||
ihiz, double *z__, int *ldz, double *work, int *lwork, int *info);
|
||||
|
||||
int dlaqr1_(int *n, double *h__, int *ldh, double *sr1,
|
||||
double *si1, double *sr2, double *si2, double *v);
|
||||
|
||||
int dlaqr2_(int *wantt, int *wantz, int *n, int *ktop, int *
|
||||
kbot, int *nw, double *h__, int *ldh, int *iloz, int *ihiz, double *
|
||||
z__, int *ldz, int *ns, int *nd, double *sr, double *si, double *v,
|
||||
int *ldv, int *nh, double *t, int *ldt, int *nv, double *wv, int *
|
||||
ldwv, double *work, int *lwork);
|
||||
|
||||
int dlaqr3_(int *wantt, int *wantz, int *n, int *ktop, int *
|
||||
kbot, int *nw, double *h__, int *ldh, int *iloz, int *ihiz, double *
|
||||
z__, int *ldz, int *ns, int *nd, double *sr, double *si, double *v,
|
||||
int *ldv, int *nh, double *t, int *ldt, int *nv, double *wv, int *
|
||||
ldwv, double *work, int *lwork);
|
||||
|
||||
int dlaqr4_(int *wantt, int *wantz, int *n, int *ilo, int *
|
||||
ihi, double *h__, int *ldh, double *wr, double *wi, int *iloz, int *
|
||||
ihiz, double *z__, int *ldz, double *work, int *lwork, int *info);
|
||||
|
||||
int dlaqr5_(int *wantt, int *wantz, int *kacc22, int *n, int
|
||||
*ktop, int *kbot, int *nshfts, double *sr, double *si, double *h__,
|
||||
int *ldh, int *iloz, int *ihiz, double *z__, int *ldz, double *v, int
|
||||
*ldv, double *u, int *ldu, int *nv, double *wv, int *ldwv, int *nh,
|
||||
double *wh, int *ldwh);
|
||||
|
||||
int dlarf_(char *side, int *m, int *n, double *v, int *incv,
|
||||
double *tau, double *c__, int *ldc, double *work);
|
||||
|
||||
int dlarfb_(char *side, char *trans, char *direct, char *
|
||||
storev, int *m, int *n, int *k, double *v, int *ldv, double *t, int *
|
||||
ldt, double *c__, int *ldc, double *work, int *ldwork);
|
||||
|
||||
int dlarfg_(int *n, double *alpha, double *x, int *incx,
|
||||
double *tau);
|
||||
|
||||
int dlarft_(char *direct, char *storev, int *n, int *k,
|
||||
double *v, int *ldv, double *tau, double *t, int *ldt);
|
||||
|
||||
int dlarfx_(char *side, int *m, int *n, double *v, double *
|
||||
tau, double *c__, int *ldc, double *work);
|
||||
|
||||
int dlartg_(double *f, double *g, double *cs, double *sn,
|
||||
double *r__);
|
||||
|
||||
int dlas2_(double *f, double *g, double *h__, double *ssmin,
|
||||
double *ssmax);
|
||||
|
||||
int dlascl_(char *type__, int *kl, int *ku, double *cfrom,
|
||||
double *cto, int *m, int *n, double *a, int *lda, int *info);
|
||||
|
||||
int dlasd0_(int *n, int *sqre, double *d__, double *e,
|
||||
double *u, int *ldu, double *vt, int *ldvt, int *smlsiz, int *iwork,
|
||||
double *work, int *info);
|
||||
|
||||
int dlasd1_(int *nl, int *nr, int *sqre, double *d__, double
|
||||
*alpha, double *beta, double *u, int *ldu, double *vt, int *ldvt, int
|
||||
*idxq, int *iwork, double *work, int *info);
|
||||
|
||||
int dlasd2_(int *nl, int *nr, int *sqre, int *k, double *d__,
|
||||
double *z__, double *alpha, double *beta, double *u, int *ldu,
|
||||
double *vt, int *ldvt, double *dsigma, double *u2, int *ldu2, double *
|
||||
vt2, int *ldvt2, int *idxp, int *idx, int *idxc, int *idxq, int *
|
||||
coltyp, int *info);
|
||||
|
||||
int dlasd3_(int *nl, int *nr, int *sqre, int *k, double *d__,
|
||||
double *q, int *ldq, double *dsigma, double *u, int *ldu, double *u2,
|
||||
int *ldu2, double *vt, int *ldvt, double *vt2, int *ldvt2, int *idxc,
|
||||
int *ctot, double *z__, int *info);
|
||||
|
||||
int dlasd4_(int *n, int *i__, double *d__, double *z__,
|
||||
double *delta, double *rho, double *sigma, double *work, int *info);
|
||||
|
||||
int dlasd5_(int *i__, double *d__, double *z__, double *
|
||||
delta, double *rho, double *dsigma, double *work);
|
||||
|
||||
int dlasd6_(int *icompq, int *nl, int *nr, int *sqre, double
|
||||
*d__, double *vf, double *vl, double *alpha, double *beta, int *idxq,
|
||||
int *perm, int *givptr, int *givcol, int *ldgcol, double *givnum, int
|
||||
*ldgnum, double *poles, double *difl, double *difr, double *z__, int *
|
||||
k, double *c__, double *s, double *work, int *iwork, int *info);
|
||||
|
||||
int dlasd7_(int *icompq, int *nl, int *nr, int *sqre, int *k,
|
||||
double *d__, double *z__, double *zw, double *vf, double *vfw,
|
||||
double *vl, double *vlw, double *alpha, double *beta, double *dsigma,
|
||||
int *idx, int *idxp, int *idxq, int *perm, int *givptr, int *givcol,
|
||||
int *ldgcol, double *givnum, int *ldgnum, double *c__, double *s, int
|
||||
*info);
|
||||
|
||||
int dlasd8_(int *icompq, int *k, double *d__, double *z__,
|
||||
double *vf, double *vl, double *difl, double *difr, int *lddifr,
|
||||
double *dsigma, double *work, int *info);
|
||||
|
||||
int dlasda_(int *icompq, int *smlsiz, int *n, int *sqre,
|
||||
double *d__, double *e, double *u, int *ldu, double *vt, int *k,
|
||||
double *difl, double *difr, double *z__, double *poles, int *givptr,
|
||||
int *givcol, int *ldgcol, int *perm, double *givnum, double *c__,
|
||||
double *s, double *work, int *iwork, int *info);
|
||||
|
||||
int dlasdq_(char *uplo, int *sqre, int *n, int *ncvt, int *
|
||||
nru, int *ncc, double *d__, double *e, double *vt, int *ldvt, double *
|
||||
u, int *ldu, double *c__, int *ldc, double *work, int *info);
|
||||
|
||||
int dlasdt_(int *n, int *lvl, int *nd, int *inode, int *
|
||||
ndiml, int *ndimr, int *msub);
|
||||
|
||||
int dlaset_(char *uplo, int *m, int *n, double *alpha,
|
||||
double *beta, double *a, int *lda);
|
||||
|
||||
int dlasq1_(int *n, double *d__, double *e, double *work,
|
||||
int *info);
|
||||
|
||||
int dlasq2_(int *n, double *z__, int *info);
|
||||
|
||||
int dlasq3_(int *i0, int *n0, double *z__, int *pp, double *
|
||||
dmin__, double *sigma, double *desig, double *qmax, int *nfail, int *
|
||||
iter, int *ndiv, int *ieee, int *ttype, double *dmin1, double *dmin2,
|
||||
double *dn, double *dn1, double *dn2, double *g, double *tau);
|
||||
|
||||
int dlasq4_(int *i0, int *n0, double *z__, int *pp, int *
|
||||
n0in, double *dmin__, double *dmin1, double *dmin2, double *dn,
|
||||
double *dn1, double *dn2, double *tau, int *ttype, double *g);
|
||||
|
||||
int dlasq5_(int *i0, int *n0, double *z__, int *pp, double *
|
||||
tau, double *sigma, double *dmin__, double *dmin1, double *dmin2,
|
||||
double *dn, double *dnm1, double *dnm2, int *ieee, double *eps);
|
||||
|
||||
int dlasq6_(int *i0, int *n0, double *z__, int *pp, double *
|
||||
dmin__, double *dmin1, double *dmin2, double *dn, double *dnm1,
|
||||
double *dnm2);
|
||||
|
||||
int dlasr_(char *side, char *pivot, char *direct, int *m,
|
||||
int *n, double *c__, double *s, double *a, int *lda);
|
||||
|
||||
int dlasrt_(char *id, int *n, double *d__, int *info);
|
||||
|
||||
int dlassq_(int *n, double *x, int *incx, double *scale,
|
||||
double *sumsq);
|
||||
|
||||
int dlasv2_(double *f, double *g, double *h__, double *ssmin,
|
||||
double *ssmax, double *snr, double *csr, double *snl, double *csl);
|
||||
|
||||
int dlasy2_(int *ltranl, int *ltranr, int *isgn, int *n1,
|
||||
int *n2, double *tl, int *ldtl, double *tr, int *ldtr, double *b, int
|
||||
*ldb, double *scale, double *x, int *ldx, double *xnorm, int *info);
|
||||
|
||||
double dnrm2_(int *n, double *x, int *incx);
|
||||
|
||||
int dorg2r_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *info);
|
||||
|
||||
int dorgbr_(char *vect, int *m, int *n, int *k, double *a,
|
||||
int *lda, double *tau, double *work, int *lwork, int *info);
|
||||
|
||||
int dorghr_(int *n, int *ilo, int *ihi, double *a, int *lda,
|
||||
double *tau, double *work, int *lwork, int *info);
|
||||
|
||||
int dorgl2_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *info);
|
||||
|
||||
int dorglq_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *lwork, int *info);
|
||||
|
||||
int dorgqr_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *lwork, int *info);
|
||||
|
||||
int dorm2r_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *info);
|
||||
|
||||
int dormbr_(char *vect, char *side, char *trans, int *m, int
|
||||
*n, int *k, double *a, int *lda, double *tau, double *c__, int *ldc,
|
||||
double *work, int *lwork, int *info);
|
||||
|
||||
int dormhr_(char *side, char *trans, int *m, int *n, int *
|
||||
ilo, int *ihi, double *a, int *lda, double *tau, double *c__, int *
|
||||
ldc, double *work, int *lwork, int *info);
|
||||
|
||||
int dorml2_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *info);
|
||||
|
||||
int dormlq_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *lwork, int *info);
|
||||
|
||||
int dormqr_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *lwork, int *info);
|
||||
|
||||
int drot_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy, double *c__, double *s);
|
||||
|
||||
int dscal_(int *n, double *da, double *dx, int *incx);
|
||||
|
||||
int dswap_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy);
|
||||
|
||||
int dtrevc3_(char *side, char *howmny, int *select, int *n,
|
||||
double *t, int *ldt, double *vl, int *ldvl, double *vr, int *ldvr,
|
||||
int *mm, int *m, double *work, int *lwork, int *info);
|
||||
|
||||
int dtrexc_(char *compq, int *n, double *t, int *ldt, double
|
||||
*q, int *ldq, int *ifst, int *ilst, double *work, int *info);
|
||||
|
||||
int dtrmm_(char *side, char *uplo, char *transa, char *diag,
|
||||
int *m, int *n, double *alpha, double *a, int *lda, double *b, int *
|
||||
ldb);
|
||||
|
||||
int dtrmv_(char *uplo, char *trans, char *diag, int *n,
|
||||
double *a, int *lda, double *x, int *incx);
|
||||
|
||||
int idamax_(int *n, double *dx, int *incx);
|
||||
|
||||
int ieeeck_(int *ispec, float *zero, float *one);
|
||||
|
||||
int iladlc_(int *m, int *n, double *a, int *lda);
|
||||
|
||||
int iladlr_(int *m, int *n, double *a, int *lda);
|
||||
|
||||
int ilaenv_(int *ispec, char *name__, char *opts, int *n1, int *n2, int *n3,
|
||||
int *n4);
|
||||
|
||||
int iparmq_(int *ispec, char *name__, char *opts, int *n, int *ilo, int *ihi,
|
||||
int *lwork);
|
||||
|
||||
int sgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta,
|
||||
float *c__, int *ldc);
|
||||
|
||||
int zgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, lapack_doublecomplex *alpha, lapack_doublecomplex *a, int *lda, lapack_doublecomplex *b,
|
||||
int *ldb, lapack_doublecomplex *beta, lapack_doublecomplex *c__, int *ldc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
+48
@@ -0,0 +1,48 @@
|
||||
Copyright (c) 1992-2017 The University of Tennessee and The University
|
||||
of Tennessee Research Foundation. All rights
|
||||
reserved.
|
||||
Copyright (c) 2000-2017 The University of California Berkeley. All
|
||||
rights reserved.
|
||||
Copyright (c) 2006-2017 The University of Colorado Denver. All rights
|
||||
reserved.
|
||||
|
||||
$COPYRIGHT$
|
||||
|
||||
Additional copyrights may follow
|
||||
|
||||
$HEADER$
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer listed
|
||||
in this license in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
- Neither the name of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
The copyright holders provide no reassurances that the source code
|
||||
provided does not infringe any patent, copyright, or any other
|
||||
intellectual property rights of third parties. The copyright holders
|
||||
disclaim any liability to any recipient for claims brought against
|
||||
recipient by any third party for infringement of that parties
|
||||
intellectual property rights.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Vendored
+272
@@ -0,0 +1,272 @@
|
||||
appdoc = """
|
||||
This is generator of CLapack subset.
|
||||
The usage:
|
||||
|
||||
1. Make sure you have the special version of f2c installed.
|
||||
Grab it from https://github.com/vpisarev/f2c/tree/for_lapack.
|
||||
2. Download fresh version of Lapack from
|
||||
https://github.com/Reference-LAPACK/lapack.
|
||||
You may choose some specific version or the latest snapshot.
|
||||
3. If necessary, edit "roots" and "banlist" variables in this script, specify the needed and unneeded functions
|
||||
4. From within a working directory run
|
||||
|
||||
$ python3 <opencv_root>/3rdparty/clapack/make_clapack.py <lapack_root>
|
||||
or
|
||||
$ F2C=<path_to_custom_f2c> python3 <opencv_root>/3rdparty/clapack/make_clapack.py <lapack_root>
|
||||
|
||||
it will generate "new_clapack" directory with "include" and "src" subdirectories.
|
||||
5. erase opencv/3rdparty/clapack/src and replace it with new_clapack/src.
|
||||
6. copy new_clapack/include/lapack.h to opencv/3rdparty/clapack/include.
|
||||
7. optionally, edit opencv/3rdparty/clapack/CMakeLists.txt and update CLAPACK_VERSION as needed.
|
||||
|
||||
This is it. Now build it and enjoy.
|
||||
"""
|
||||
|
||||
import glob, re, os, shutil, subprocess, sys
|
||||
|
||||
roots = ["cgemm_", "dgemm_", "sgemm_", "zgemm_",
|
||||
"dgeev_", "dgesdd_",
|
||||
#"dsyevr_",
|
||||
#"dgesv_", "dgetrf_", "dposv_", "dpotrf_", "dgels_", "dgeqrf_",
|
||||
#"sgesv_", "sgetrf_", "sposv_", "spotrf_", "sgels_", "sgeqrf_"
|
||||
]
|
||||
banlist = ["slamch_", "slamc3_", "dlamch_", "dlamc3_", "lsame_", "xerbla_"]
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(appdoc)
|
||||
sys.exit(0)
|
||||
|
||||
lapack_root = sys.argv[1]
|
||||
dst_path = "."
|
||||
|
||||
def error(msg):
|
||||
print ("error: " + msg)
|
||||
sys.exit(0)
|
||||
|
||||
def file2fun(fname):
|
||||
return (os.path.basename(fname)[:-2]).upper()
|
||||
|
||||
def print_graph(m):
|
||||
for (k, neighbors) in sorted(m.items()):
|
||||
print (k + " : " + ", ".join(sorted(list(neighbors))))
|
||||
|
||||
blas_path = os.path.join(lapack_root, "BLAS/SRC")
|
||||
lapack_path = os.path.join(lapack_root, "SRC")
|
||||
|
||||
roots = [f[:-1].upper() for f in roots]
|
||||
banlist = [f[:-1].upper() for f in banlist]
|
||||
|
||||
def fun2file(func):
|
||||
filename = func.lower() + ".f"
|
||||
blas_loc = blas_path + "/" + filename
|
||||
lapack_loc = lapack_path + "/" + filename
|
||||
if os.path.exists(blas_loc):
|
||||
return blas_loc
|
||||
elif os.path.exists(lapack_loc):
|
||||
return lapack_loc
|
||||
else:
|
||||
error("neither %s nor %s exist" % (blas_loc, lapack_loc))
|
||||
|
||||
all_files = glob.glob(blas_path + "/*.f") + glob.glob(lapack_path + "/*.f")
|
||||
all_funcs = [file2fun(fname) for fname in all_files]
|
||||
all_funcs_set = set(all_funcs).difference(set(banlist))
|
||||
all_funcs = sorted(list(all_funcs_set))
|
||||
|
||||
func_deps = {}
|
||||
|
||||
#print all_funcs
|
||||
|
||||
words_regexp = re.compile(r'\w+')
|
||||
|
||||
def scan_deps(func):
|
||||
global func_deps
|
||||
if func in func_deps:
|
||||
return
|
||||
func_deps[func] = set([]) # to avoid possibly infinite recursion
|
||||
f = open(fun2file(func), 'rt')
|
||||
deps = []
|
||||
external_mode = False
|
||||
for l in f.readlines():
|
||||
if l.startswith('*'):
|
||||
continue
|
||||
l = l.strip().upper()
|
||||
if l.startswith('EXTERNAL '):
|
||||
external_mode = True
|
||||
elif l.startswith('$') and external_mode:
|
||||
pass
|
||||
else:
|
||||
external_mode = False
|
||||
if not external_mode:
|
||||
continue
|
||||
for w in words_regexp.findall(l):
|
||||
if w in all_funcs_set:
|
||||
deps.append(w)
|
||||
f.close()
|
||||
# remove func from its dependencies
|
||||
deps = set(deps).difference(set([func]))
|
||||
func_deps[func] = deps
|
||||
for d in deps:
|
||||
scan_deps(d)
|
||||
|
||||
for r in roots:
|
||||
scan_deps(r)
|
||||
|
||||
selected_funcs = sorted(func_deps.keys())
|
||||
print ("total files before amalgamation: %d" % len(selected_funcs))
|
||||
|
||||
inv_deps = {}
|
||||
for func in selected_funcs:
|
||||
inv_deps[func] = set([])
|
||||
|
||||
for (func, deps) in func_deps.items():
|
||||
for d in deps:
|
||||
inv_deps[d] = inv_deps[d].union(set([func]))
|
||||
|
||||
#print_graph(inv_deps)
|
||||
|
||||
func_home = {}
|
||||
for func in selected_funcs:
|
||||
func_home[func] = func
|
||||
|
||||
def get_home0(func, func0):
|
||||
used_by = inv_deps[func]
|
||||
if len(used_by) == 1:
|
||||
p = list(used_by)[0]
|
||||
if p != func and p != func0:
|
||||
return get_home0(p, func0)
|
||||
return func
|
||||
return func
|
||||
|
||||
# try to merge some files
|
||||
for func in selected_funcs:
|
||||
func_home[func] = get_home0(func, func)
|
||||
|
||||
# try to merge some files even more
|
||||
for iters in range(100):
|
||||
homes_changed = False
|
||||
for (func, used_by) in inv_deps.items():
|
||||
p0 = func_home[func]
|
||||
n = len(used_by)
|
||||
if n == 1:
|
||||
p = list(used_by)[0]
|
||||
p1 = func_home[p]
|
||||
if p1 != p0:
|
||||
func_home[func] = p1
|
||||
homes_changed = True
|
||||
continue
|
||||
elif n > 1:
|
||||
phomes = set([])
|
||||
for p in used_by:
|
||||
phomes.add(func_home[p])
|
||||
if len(phomes) == 1:
|
||||
p1 = list(phomes)[0]
|
||||
if p1 != p0:
|
||||
func_home[func] = p1
|
||||
homes_changed = True
|
||||
if not homes_changed:
|
||||
break
|
||||
|
||||
res_files = {}
|
||||
for (func, h) in func_home.items():
|
||||
elems = res_files.get(h, set([]))
|
||||
elems.add(func)
|
||||
res_files[h] = elems
|
||||
|
||||
print ("total files after amalgamation: %d" % len(res_files))
|
||||
#print_graph(res_files)
|
||||
|
||||
outdir = os.path.join(dst_path, "new_clapack")
|
||||
outdir_src = os.path.join(outdir, "src")
|
||||
outdir_inc = os.path.join(outdir, "include")
|
||||
|
||||
shutil.rmtree(outdir, ignore_errors=True)
|
||||
try:
|
||||
os.makedirs(outdir_src)
|
||||
except os.error:
|
||||
pass
|
||||
try:
|
||||
os.makedirs(outdir_inc)
|
||||
except os.error:
|
||||
pass
|
||||
|
||||
f2c_appname = os.getenv("F2C", default="f2c")
|
||||
print ("f2c used: %s" % f2c_appname)
|
||||
|
||||
f2c_getver_cmd = f2c_appname + " -v"
|
||||
|
||||
verstr = subprocess.check_output(f2c_getver_cmd.split(' ')).decode("utf-8")
|
||||
if "for_lapack" not in verstr:
|
||||
error("invalid version of f2c\n" + appdoc)
|
||||
|
||||
f2c_flags = "-ctypes -localconst -no-proto"
|
||||
f2c_cmd0 = f2c_appname + " " + f2c_flags
|
||||
f2c_cmd1 = f2c_appname + " -hdr none " + f2c_flags
|
||||
|
||||
lapack_protos = {}
|
||||
extract_fn_regexp = re.compile(r'.+?(\w+)\s*\(')
|
||||
|
||||
def extract_proto(func, csrc):
|
||||
global lapack_protos
|
||||
cname = func.lower() + "_"
|
||||
cfname = func.lower() + ".c"
|
||||
regexp_str = r'\n(?:/\* Subroutine \*/\s*)?\w+\s+\w+\s*\((?:.|\n)+?\)[\s\n]*\{'
|
||||
proto_regexp = re.compile(regexp_str)
|
||||
ps = proto_regexp.findall(csrc)
|
||||
for p in ps:
|
||||
n = p.find("*/")
|
||||
if n < 0:
|
||||
n = 0
|
||||
else:
|
||||
n += 2
|
||||
p = p[n:-1].strip() + ";"
|
||||
fns = extract_fn_regexp.findall(p)
|
||||
if len(fns) != 1:
|
||||
error("prototype of function (%s) when analyzing %s cannot be parsed" % (p, cfname))
|
||||
fn = fns[0]
|
||||
if fn not in lapack_protos:
|
||||
p = re.sub(r'\bcomplex\b', 'lapack_complex', p)
|
||||
p = re.sub(r'\bdoublecomplex\b', 'lapack_doublecomplex', p)
|
||||
lapack_protos[fn] = p
|
||||
|
||||
for (filename, funcs) in sorted(res_files.items()):
|
||||
out = ""
|
||||
f2c_cmd = f2c_cmd0
|
||||
for func in sorted(list(funcs)):
|
||||
ffilename = fun2file(func)
|
||||
print ("running " + f2c_cmd + " on " + ffilename + " ...")
|
||||
ffile = open(ffilename, 'rt')
|
||||
delta_out = subprocess.check_output(f2c_cmd.split(' '), stdin=ffile).decode("utf-8")
|
||||
# remove trailing whitespaces
|
||||
delta_out = '\n'.join([l.rstrip() for l in delta_out.split('\n')])
|
||||
extract_proto(func, delta_out)
|
||||
out += delta_out
|
||||
ffile.close()
|
||||
f2c_cmd = f2c_cmd1
|
||||
outname = os.path.join(outdir_src, filename.lower() + ".c")
|
||||
outfile = open(outname, 'wt')
|
||||
outfile.write(out)
|
||||
outfile.close()
|
||||
|
||||
proto_hdr = """// this is auto-generated header for Lapack subset
|
||||
#ifndef __CLAPACK_H__
|
||||
#define __CLAPACK_H__
|
||||
|
||||
#include "cblas.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
%s
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
""" % "\n\n".join([p for (n, p) in sorted(lapack_protos.items())])
|
||||
|
||||
proto_hdr_fname = os.path.join(outdir_inc, "lapack.h")
|
||||
f = open(proto_hdr_fname, 'wt')
|
||||
f.write(proto_hdr)
|
||||
f.close()
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
#include "f2c.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
void cblas_cgemm(const CBLAS_LAYOUT layout, const CBLAS_TRANSPOSE TransA,
|
||||
const CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const void *alpha, const void *A,
|
||||
const int lda, const void *B, const int ldb,
|
||||
const void *beta, void *C, const int ldc)
|
||||
{
|
||||
char TA, TB;
|
||||
|
||||
if( layout == CblasColMajor )
|
||||
{
|
||||
if(TransA == CblasTrans) TA='T';
|
||||
else if ( TransA == CblasConjTrans ) TA='C';
|
||||
else if ( TransA == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_cgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
|
||||
if(TransB == CblasTrans) TB='T';
|
||||
else if ( TransB == CblasConjTrans ) TB='C';
|
||||
else if ( TransB == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 3, "cblas_cgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
cgemm_(&TA, &TB, (int*)&M, (int*)&N, (int*)&K, (complex*)alpha, (complex*)A, (int*)&lda,
|
||||
(complex*)B, (int*)&ldb, (complex*)beta, (complex*)C, (int*)&ldc);
|
||||
}
|
||||
else if (layout == CblasRowMajor)
|
||||
{
|
||||
if(TransA == CblasTrans) TB='T';
|
||||
else if ( TransA == CblasConjTrans ) TB='C';
|
||||
else if ( TransA == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_cgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
if(TransB == CblasTrans) TA='T';
|
||||
else if ( TransB == CblasConjTrans ) TA='C';
|
||||
else if ( TransB == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_cgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
cgemm_(&TA, &TB, (int*)&N, (int*)&M, (int*)&K, (complex*)alpha, (complex*)B, (int*)&ldb,
|
||||
(complex*)A, (int*)&lda, (complex*)beta, (complex*)C, (int*)&ldc);
|
||||
}
|
||||
else cblas_xerbla(layout, 1, "cblas_cgemm", "Illegal layout setting, %d\n", layout);
|
||||
}
|
||||
|
||||
void cblas_dgemm(const CBLAS_LAYOUT layout, const CBLAS_TRANSPOSE TransA,
|
||||
const CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const double alpha, const double *A,
|
||||
const int lda, const double *B, const int ldb,
|
||||
const double beta, double *C, const int ldc)
|
||||
{
|
||||
char TA, TB;
|
||||
|
||||
if( layout == CblasColMajor )
|
||||
{
|
||||
if(TransA == CblasTrans) TA='T';
|
||||
else if ( TransA == CblasConjTrans ) TA='C';
|
||||
else if ( TransA == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_dgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
|
||||
if(TransB == CblasTrans) TB='T';
|
||||
else if ( TransB == CblasConjTrans ) TB='C';
|
||||
else if ( TransB == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 3, "cblas_dgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
dgemm_(&TA, &TB, (int*)&M, (int*)&N, (int*)&K, (double*)&alpha, (double*)A, (int*)&lda,
|
||||
(double*)B, (int*)&ldb, (double*)&beta, (double*)C, (int*)&ldc);
|
||||
}
|
||||
else if (layout == CblasRowMajor)
|
||||
{
|
||||
if(TransA == CblasTrans) TB='T';
|
||||
else if ( TransA == CblasConjTrans ) TB='C';
|
||||
else if ( TransA == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_dgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
if(TransB == CblasTrans) TA='T';
|
||||
else if ( TransB == CblasConjTrans ) TA='C';
|
||||
else if ( TransB == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_dgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
dgemm_(&TA, &TB, (int*)&N, (int*)&M, (int*)&K, (double*)&alpha, (double*)B, (int*)&ldb,
|
||||
(double*)A, (int*)&lda, (double*)&beta, (double*)C, (int*)&ldc);
|
||||
}
|
||||
else cblas_xerbla(layout, 1, "cblas_dgemm", "Illegal layout setting, %d\n", layout);
|
||||
}
|
||||
|
||||
|
||||
void cblas_sgemm(const CBLAS_LAYOUT layout, const CBLAS_TRANSPOSE TransA,
|
||||
const CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const float alpha, const float *A,
|
||||
const int lda, const float *B, const int ldb,
|
||||
const float beta, float *C, const int ldc)
|
||||
{
|
||||
char TA, TB;
|
||||
|
||||
if( layout == CblasColMajor )
|
||||
{
|
||||
if(TransA == CblasTrans) TA='T';
|
||||
else if ( TransA == CblasConjTrans ) TA='C';
|
||||
else if ( TransA == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_sgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
|
||||
if(TransB == CblasTrans) TB='T';
|
||||
else if ( TransB == CblasConjTrans ) TB='C';
|
||||
else if ( TransB == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 3, "cblas_sgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
sgemm_(&TA, &TB, (int*)&M, (int*)&N, (int*)&K, (float*)&alpha, (float*)A, (int*)&lda,
|
||||
(float*)B, (int*)&ldb, (float*)&beta, (float*)C, (int*)&ldc);
|
||||
}
|
||||
else if (layout == CblasRowMajor)
|
||||
{
|
||||
if(TransA == CblasTrans) TB='T';
|
||||
else if ( TransA == CblasConjTrans ) TB='C';
|
||||
else if ( TransA == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_sgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
if(TransB == CblasTrans) TA='T';
|
||||
else if ( TransB == CblasConjTrans ) TA='C';
|
||||
else if ( TransB == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_sgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
sgemm_(&TA, &TB, (int*)&N, (int*)&M, (int*)&K, (float*)&alpha, (float*)B, (int*)&ldb,
|
||||
(float*)A, (int*)&lda, (float*)&beta, (float*)C, (int*)&ldc);
|
||||
}
|
||||
else cblas_xerbla(layout, 1, "cblas_sgemm", "Illegal layout setting, %d\n", layout);
|
||||
}
|
||||
|
||||
void cblas_zgemm(const CBLAS_LAYOUT layout, const CBLAS_TRANSPOSE TransA,
|
||||
const CBLAS_TRANSPOSE TransB, const int M, const int N,
|
||||
const int K, const void *alpha, const void *A,
|
||||
const int lda, const void *B, const int ldb,
|
||||
const void *beta, void *C, const int ldc)
|
||||
{
|
||||
char TA, TB;
|
||||
|
||||
if( layout == CblasColMajor )
|
||||
{
|
||||
if(TransA == CblasTrans) TA='T';
|
||||
else if ( TransA == CblasConjTrans ) TA='C';
|
||||
else if ( TransA == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_zgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
|
||||
if(TransB == CblasTrans) TB='T';
|
||||
else if ( TransB == CblasConjTrans ) TB='C';
|
||||
else if ( TransB == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 3, "cblas_zgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
zgemm_(&TA, &TB, (int*)&M, (int*)&N, (int*)&K, (doublecomplex*)alpha, (doublecomplex*)A, (int*)&lda,
|
||||
(doublecomplex*)B, (int*)&ldb, (doublecomplex*)beta, (doublecomplex*)C, (int*)&ldc);
|
||||
}
|
||||
else if (layout == CblasRowMajor)
|
||||
{
|
||||
if(TransA == CblasTrans) TB='T';
|
||||
else if ( TransA == CblasConjTrans ) TB='C';
|
||||
else if ( TransA == CblasNoTrans ) TB='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_zgemm", "Illegal TransA setting, %d\n", TransA);
|
||||
return;
|
||||
}
|
||||
if(TransB == CblasTrans) TA='T';
|
||||
else if ( TransB == CblasConjTrans ) TA='C';
|
||||
else if ( TransB == CblasNoTrans ) TA='N';
|
||||
else
|
||||
{
|
||||
cblas_xerbla(layout, 2, "cblas_zgemm", "Illegal TransB setting, %d\n", TransB);
|
||||
return;
|
||||
}
|
||||
|
||||
zgemm_(&TA, &TB, (int*)&N, (int*)&M, (int*)&K, (doublecomplex*)alpha, (doublecomplex*)B, (int*)&ldb,
|
||||
(doublecomplex*)A, (int*)&lda, (doublecomplex*)beta, (doublecomplex*)C, (int*)&ldc);
|
||||
}
|
||||
else cblas_xerbla(layout, 1, "cblas_zgemm", "Illegal layout setting, %d\n", layout);
|
||||
}
|
||||
|
||||
void cblas_xerbla(const CBLAS_LAYOUT layout, int info, const char *rout, const char *form, ...)
|
||||
{
|
||||
extern int RowMajorStrg;
|
||||
char empty[1] = "";
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr, form);
|
||||
|
||||
if (layout == CblasRowMajor)
|
||||
{
|
||||
if (strstr(rout,"gemm") != 0)
|
||||
{
|
||||
if (info == 5 ) info = 4;
|
||||
else if (info == 4 ) info = 5;
|
||||
else if (info == 11) info = 9;
|
||||
else if (info == 9 ) info = 11;
|
||||
}
|
||||
else if (strstr(rout,"symm") != 0 || strstr(rout,"hemm") != 0)
|
||||
{
|
||||
if (info == 5 ) info = 4;
|
||||
else if (info == 4 ) info = 5;
|
||||
}
|
||||
else if (strstr(rout,"trmm") != 0 || strstr(rout,"trsm") != 0)
|
||||
{
|
||||
if (info == 7 ) info = 6;
|
||||
else if (info == 6 ) info = 7;
|
||||
}
|
||||
else if (strstr(rout,"gemv") != 0)
|
||||
{
|
||||
if (info == 4) info = 3;
|
||||
else if (info == 3) info = 4;
|
||||
}
|
||||
else if (strstr(rout,"gbmv") != 0)
|
||||
{
|
||||
if (info == 4) info = 3;
|
||||
else if (info == 3) info = 4;
|
||||
else if (info == 6) info = 5;
|
||||
else if (info == 5) info = 6;
|
||||
}
|
||||
else if (strstr(rout,"ger") != 0)
|
||||
{
|
||||
if (info == 3) info = 2;
|
||||
else if (info == 2) info = 3;
|
||||
else if (info == 8) info = 6;
|
||||
else if (info == 6) info = 8;
|
||||
}
|
||||
else if ( (strstr(rout,"her2") != 0 || strstr(rout,"hpr2") != 0)
|
||||
&& strstr(rout,"her2k") == 0 )
|
||||
{
|
||||
if (info == 8) info = 6;
|
||||
else if (info == 6) info = 8;
|
||||
}
|
||||
}
|
||||
if (info)
|
||||
fprintf(stderr, "Parameter %d to routine %s was incorrect\n", info, rout);
|
||||
vfprintf(stderr, form, argptr);
|
||||
va_end(argptr);
|
||||
if (info && !info)
|
||||
xerbla_(empty, &info); /* Force link of our F77 error handler */
|
||||
exit(-1);
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
#include "f2c.h"
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
double dlamc3_(double *a, double *b)
|
||||
{
|
||||
/* -- LAPACK auxiliary routine (version 3.1) -- */
|
||||
/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
|
||||
/* November 2006 */
|
||||
|
||||
/* .. Scalar Arguments .. */
|
||||
/* .. */
|
||||
|
||||
/* Purpose */
|
||||
/* ======= */
|
||||
|
||||
/* DLAMC3 is intended to force A and B to be stored prior to doing */
|
||||
/* the addition of A and B , for use in situations where optimizers */
|
||||
/* might hold one of these in a register. */
|
||||
|
||||
/* Arguments */
|
||||
/* ========= */
|
||||
|
||||
/* A (input) DOUBLE PRECISION */
|
||||
/* B (input) DOUBLE PRECISION */
|
||||
/* The values A and B. */
|
||||
|
||||
/* ===================================================================== */
|
||||
|
||||
/* .. Executable Statements .. */
|
||||
|
||||
double ret_val = *a + *b;
|
||||
|
||||
return ret_val;
|
||||
|
||||
/* End of DLAMC3 */
|
||||
|
||||
} /* dlamc3_ */
|
||||
|
||||
|
||||
/* simpler version of dlamch for the case of IEEE754-compliant FPU module by Piotr Luszczek S.
|
||||
taken from http://www.mail-archive.com/numpy-discussion@lists.sourceforge.net/msg02448.html */
|
||||
|
||||
#ifndef DBL_DIGITS
|
||||
#define DBL_DIGITS 53
|
||||
#endif
|
||||
|
||||
static const unsigned char lapack_dlamch_tab0[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 0, 8, 9, 0, 10, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 0, 8, 9,
|
||||
0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const double lapack_dlamch_tab1[] =
|
||||
{
|
||||
0, FLT_RADIX, DBL_EPSILON, DBL_MAX_EXP, DBL_MIN_EXP, DBL_DIGITS, DBL_MAX,
|
||||
DBL_EPSILON*FLT_RADIX, 1, DBL_MIN*(1 + DBL_EPSILON), DBL_MIN
|
||||
};
|
||||
|
||||
double dlamch_(char* cmach)
|
||||
{
|
||||
return lapack_dlamch_tab1[lapack_dlamch_tab0[(unsigned char)cmach[0]]];
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#include "f2c.h"
|
||||
|
||||
static const int CLAPACK_NOT_IMPLEMENTED = -1024;
|
||||
|
||||
int sgesdd_(char *jobz, int *m, int *n, float *a, int *lda,
|
||||
float *s, float *u, int *ldu, float *vt, int *ldvt, float *work,
|
||||
int *lwork, int *iwork, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dgels_(char *trans, int *m, int *n, int *nrhs, double *a,
|
||||
int *lda, double *b, int *ldb, double *work, int *lwork, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv,
|
||||
double *b, int *ldb, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv,
|
||||
int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dposv_(char *uplo, int *n, int *nrhs, double *a, int *
|
||||
lda, double *b, int *ldb, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpotrf_(char *uplo, int *n, double *a, int *lda, int *
|
||||
info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgels_(char *trans, int *m, int *n, int *nrhs, float *a,
|
||||
int *lda, float *b, int *ldb, float *work, int *lwork, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgeev_(char *jobvl, char *jobvr, int *n, float *a, int *
|
||||
lda, float *wr, float *wi, float *vl, int *ldvl, float *vr, int *
|
||||
ldvr, float *work, int *lwork, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgeqrf_(int *m, int *n, float *a, int *lda, float *tau,
|
||||
float *work, int *lwork, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgesv_(int *n, int *nrhs, float *a, int *lda, int *ipiv,
|
||||
float *b, int *ldb, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgetrf_(int *m, int *n, float *a, int *lda, int *ipiv,
|
||||
int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sposv_(char *uplo, int *n, int *nrhs, float *a, int *
|
||||
lda, float *b, int *ldb, int *info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spotrf_(char *uplo, int *n, float *a, int *lda, int *
|
||||
info)
|
||||
{
|
||||
*info = CLAPACK_NOT_IMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#include "f2c.h"
|
||||
|
||||
static const unsigned char lapack_toupper_tab[] =
|
||||
{
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
||||
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
|
||||
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
|
||||
90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131,
|
||||
132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
|
||||
168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
|
||||
186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
|
||||
204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
|
||||
222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
|
||||
};
|
||||
|
||||
#define lapack_toupper(c) ((char)lapack_toupper_tab[(unsigned char)(c)])
|
||||
|
||||
int lsame_(char *ca, char *cb)
|
||||
{
|
||||
return lapack_toupper(ca[0]) == lapack_toupper(cb[0]);
|
||||
}
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
#include "f2c.h"
|
||||
|
||||
double pow_di(double *ap, int *bp)
|
||||
{
|
||||
double p = 1;
|
||||
double x = *ap;
|
||||
int n = *bp;
|
||||
|
||||
if(n != 0)
|
||||
{
|
||||
if(n < 0)
|
||||
{
|
||||
n = -n;
|
||||
x = 1/x;
|
||||
}
|
||||
unsigned u = (unsigned)n;
|
||||
for(;;)
|
||||
{
|
||||
if((u & 1) != 0)
|
||||
p *= x;
|
||||
if((u >>= 1) == 0)
|
||||
break;
|
||||
x *= x;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
#include "f2c.h"
|
||||
|
||||
int pow_ii(int *ap, int *bp)
|
||||
{
|
||||
int p;
|
||||
int x = *ap;
|
||||
int n = *bp;
|
||||
|
||||
if (n <= 0) {
|
||||
if (n == 0 || x == 1)
|
||||
return 1;
|
||||
return x != -1 ? 0 : (n & 1) ? -1 : 1;
|
||||
}
|
||||
unsigned u = (unsigned)n;
|
||||
for(p = 1; ; )
|
||||
{
|
||||
if(u & 01)
|
||||
p *= x;
|
||||
if(u >>= 1)
|
||||
x *= x;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
/* Unless compiled with -DNO_OVERWRITE, this variant of s_cat allows the
|
||||
* target of a concatenation to appear on its right-hand side (contrary
|
||||
* to the Fortran 77 Standard, but in accordance with Fortran 90).
|
||||
*/
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
int s_cat(char *lp, char **rpp, int* rnp, int *np)
|
||||
{
|
||||
int i, L = 0;
|
||||
int n = *np;
|
||||
|
||||
for(i = 0; i < n; i++) {
|
||||
int ni = rnp[i];
|
||||
if(ni > 0) {
|
||||
memcpy(lp + L, rpp[i], ni);
|
||||
L += ni;
|
||||
}
|
||||
}
|
||||
lp[L] = '\0';
|
||||
return 0;
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
#include "f2c.h"
|
||||
|
||||
/* compare two strings */
|
||||
int s_cmp(char *a0, char *b0)
|
||||
{
|
||||
int la = (int)strlen(a0);
|
||||
int lb = (int)strlen(b0);
|
||||
unsigned char *a, *aend, *b, *bend;
|
||||
a = (unsigned char *)a0;
|
||||
b = (unsigned char *)b0;
|
||||
aend = a + la;
|
||||
bend = b + lb;
|
||||
|
||||
if(la <= lb)
|
||||
{
|
||||
while(a < aend)
|
||||
if(*a != *b)
|
||||
return( *a - *b );
|
||||
else
|
||||
{ ++a; ++b; }
|
||||
|
||||
while(b < bend)
|
||||
if(*b != ' ')
|
||||
return( ' ' - *b );
|
||||
else ++b;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(b < bend)
|
||||
if(*a == *b)
|
||||
{ ++a; ++b; }
|
||||
else
|
||||
return( *a - *b );
|
||||
while(a < aend)
|
||||
if(*a != ' ')
|
||||
return(*a - ' ');
|
||||
else ++a;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
#include "f2c.h"
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* *********************************************************************** */
|
||||
|
||||
double slamc3_(float *a, float *b)
|
||||
{
|
||||
/* -- LAPACK auxiliary routine (version 3.1) -- */
|
||||
/* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
|
||||
/* November 2006 */
|
||||
|
||||
/* .. Scalar Arguments .. */
|
||||
/* .. */
|
||||
|
||||
/* Purpose */
|
||||
/* ======= */
|
||||
|
||||
/* SLAMC3 is intended to force A and B to be stored prior to doing */
|
||||
/* the addition of A and B , for use in situations where optimizers */
|
||||
/* might hold one of these in a register. */
|
||||
|
||||
/* Arguments */
|
||||
/* ========= */
|
||||
|
||||
/* A (input) REAL */
|
||||
/* B (input) REAL */
|
||||
/* The values A and B. */
|
||||
|
||||
/* ===================================================================== */
|
||||
|
||||
/* .. Executable Statements .. */
|
||||
|
||||
float ret_val = *a + *b;
|
||||
|
||||
return ret_val;
|
||||
|
||||
/* End of SLAMC3 */
|
||||
|
||||
} /* slamc3_ */
|
||||
|
||||
/* simpler version of slamch for the case of IEEE754-compliant FPU module by Piotr Luszczek S.
|
||||
taken from http://www.mail-archive.com/numpy-discussion@lists.sourceforge.net/msg02448.html */
|
||||
|
||||
#ifndef FLT_DIGITS
|
||||
#define FLT_DIGITS 24
|
||||
#endif
|
||||
|
||||
static const unsigned char lapack_slamch_tab0[] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 0, 8, 9, 0, 10, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 0, 8, 9,
|
||||
0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
const double lapack_slamch_tab1[] =
|
||||
{
|
||||
0, FLT_RADIX, FLT_EPSILON, FLT_MAX_EXP, FLT_MIN_EXP, FLT_DIGITS, FLT_MAX,
|
||||
FLT_EPSILON*FLT_RADIX, 1, FLT_MIN*(1 + FLT_EPSILON), FLT_MIN
|
||||
};
|
||||
|
||||
double slamch_(char* cmach)
|
||||
{
|
||||
return lapack_slamch_tab1[lapack_slamch_tab0[(unsigned char)cmach[0]]];
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/* xerbla.f -- translated by f2c (version 20061008).
|
||||
You must link the resulting object file with libf2c:
|
||||
on Microsoft Windows system, link with libf2c.lib;
|
||||
on Linux or Unix systems, link with .../path/to/libf2c.a -lm
|
||||
or, if you install libf2c.a in a standard place, with -lf2c -lm
|
||||
-- in that order, at the end of the command line, as in
|
||||
cc *.o -lf2c -lm
|
||||
Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
|
||||
|
||||
http://www.netlib.org/f2c/libf2c.zip
|
||||
*/
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
/* Subroutine */ int xerbla_(char *srname, int *info)
|
||||
{
|
||||
printf("** On entry to %s, parameter number %2i had an illegal value\n", srname, *info);
|
||||
return 0;
|
||||
} /* xerbla_ */
|
||||
Vendored
+752
@@ -0,0 +1,752 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b CGEMM
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE CGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// COMPLEX ALPHA,BETA
|
||||
// INTEGER K,LDA,LDB,LDC,M,N
|
||||
// CHARACTER TRANSA,TRANSB
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// COMPLEX A(LDA,*),B(LDB,*),C(LDC,*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> CGEMM performs one of the matrix-matrix operations
|
||||
//>
|
||||
//> C := alpha*op( A )*op( B ) + beta*C,
|
||||
//>
|
||||
//> where op( X ) is one of
|
||||
//>
|
||||
//> op( X ) = X or op( X ) = X**T or op( X ) = X**H,
|
||||
//>
|
||||
//> alpha and beta are scalars, and A, B and C are matrices, with op( A )
|
||||
//> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TRANSA
|
||||
//> \verbatim
|
||||
//> TRANSA is CHARACTER*1
|
||||
//> On entry, TRANSA specifies the form of op( A ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSA = 'N' or 'n', op( A ) = A.
|
||||
//>
|
||||
//> TRANSA = 'T' or 't', op( A ) = A**T.
|
||||
//>
|
||||
//> TRANSA = 'C' or 'c', op( A ) = A**H.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANSB
|
||||
//> \verbatim
|
||||
//> TRANSB is CHARACTER*1
|
||||
//> On entry, TRANSB specifies the form of op( B ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSB = 'N' or 'n', op( B ) = B.
|
||||
//>
|
||||
//> TRANSB = 'T' or 't', op( B ) = B**T.
|
||||
//>
|
||||
//> TRANSB = 'C' or 'c', op( B ) = B**H.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix
|
||||
//> op( A ) and of the matrix C. M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix
|
||||
//> op( B ) and the number of columns of the matrix C. N must be
|
||||
//> at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> On entry, K specifies the number of columns of the matrix
|
||||
//> op( A ) and the number of rows of the matrix op( B ). K must
|
||||
//> be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is COMPLEX
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is COMPLEX array, dimension ( LDA, ka ), where ka is
|
||||
//> k when TRANSA = 'N' or 'n', and is m otherwise.
|
||||
//> Before entry with TRANSA = 'N' or 'n', the leading m by k
|
||||
//> part of the array A must contain the matrix A, otherwise
|
||||
//> the leading k by m part of the array A must contain the
|
||||
//> matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. When TRANSA = 'N' or 'n' then
|
||||
//> LDA must be at least max( 1, m ), otherwise LDA must be at
|
||||
//> least max( 1, k ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] B
|
||||
//> \verbatim
|
||||
//> B is COMPLEX array, dimension ( LDB, kb ), where kb is
|
||||
//> n when TRANSB = 'N' or 'n', and is k otherwise.
|
||||
//> Before entry with TRANSB = 'N' or 'n', the leading k by n
|
||||
//> part of the array B must contain the matrix B, otherwise
|
||||
//> the leading n by k part of the array B must contain the
|
||||
//> matrix B.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> On entry, LDB specifies the first dimension of B as declared
|
||||
//> in the calling (sub) program. When TRANSB = 'N' or 'n' then
|
||||
//> LDB must be at least max( 1, k ), otherwise LDB must be at
|
||||
//> least max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is COMPLEX
|
||||
//> On entry, BETA specifies the scalar beta. When BETA is
|
||||
//> supplied as zero then C need not be set on input.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is COMPLEX array, dimension ( LDC, N )
|
||||
//> Before entry, the leading m by n part of the array C must
|
||||
//> contain the matrix C, except when beta is zero, in which
|
||||
//> case C need not be set on entry.
|
||||
//> On exit, the array C is overwritten by the m by n matrix
|
||||
//> ( alpha*op( A )*op( B ) + beta*C ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> On entry, LDC specifies the first dimension of C as declared
|
||||
//> in the calling (sub) program. LDC must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup complex_blas_level3
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 3 Blas routine.
|
||||
//>
|
||||
//> -- Written on 8-February-1989.
|
||||
//> Jack Dongarra, Argonne National Laboratory.
|
||||
//> Iain Duff, AERE Harwell.
|
||||
//> Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
||||
//> Sven Hammarling, Numerical Algorithms Group Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int cgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, complex *alpha, complex *a, int *lda, complex *b, int *ldb,
|
||||
complex *beta, complex *c__, int *ldc)
|
||||
{
|
||||
// Table of constant values
|
||||
complex c_b1 = {1.f,0.f};
|
||||
complex c_b2 = {0.f,0.f};
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2,
|
||||
i__3, i__4, i__5, i__6;
|
||||
complex q__1, q__2, q__3, q__4;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l, info;
|
||||
int nota, notb;
|
||||
complex temp;
|
||||
int conja, conjb;
|
||||
int ncola;
|
||||
extern int lsame_(char *, char *);
|
||||
int nrowa, nrowb;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level3 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
//
|
||||
// Set NOTA and NOTB as true if A and B respectively are not
|
||||
// conjugated or transposed, set CONJA and CONJB as true if A and
|
||||
// B respectively are to be transposed but not conjugated and set
|
||||
// NROWA, NCOLA and NROWB as the number of rows and columns of A
|
||||
// and the number of rows of B respectively.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
|
||||
// Function Body
|
||||
nota = lsame_(transa, "N");
|
||||
notb = lsame_(transb, "N");
|
||||
conja = lsame_(transa, "C");
|
||||
conjb = lsame_(transb, "C");
|
||||
if (nota) {
|
||||
nrowa = *m;
|
||||
ncola = *k;
|
||||
} else {
|
||||
nrowa = *k;
|
||||
ncola = *m;
|
||||
}
|
||||
if (notb) {
|
||||
nrowb = *k;
|
||||
} else {
|
||||
nrowb = *n;
|
||||
}
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
info = 0;
|
||||
if (! nota && ! conja && ! lsame_(transa, "T")) {
|
||||
info = 1;
|
||||
} else if (! notb && ! conjb && ! lsame_(transb, "T")) {
|
||||
info = 2;
|
||||
} else if (*m < 0) {
|
||||
info = 3;
|
||||
} else if (*n < 0) {
|
||||
info = 4;
|
||||
} else if (*k < 0) {
|
||||
info = 5;
|
||||
} else if (*lda < max(1,nrowa)) {
|
||||
info = 8;
|
||||
} else if (*ldb < max(1,nrowb)) {
|
||||
info = 10;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
info = 13;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("CGEMM ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || (alpha->r == 0.f && alpha->i == 0.f || *k == 0)
|
||||
&& (beta->r == 1.f && beta->i == 0.f)) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// And when alpha.eq.zero.
|
||||
//
|
||||
if (alpha->r == 0.f && alpha->i == 0.f) {
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0.f, c__[i__3].i = 0.f;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4].i,
|
||||
q__1.i = beta->r * c__[i__4].i + beta->i * c__[
|
||||
i__4].r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations.
|
||||
//
|
||||
if (notb) {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0.f, c__[i__3].i = 0.f;
|
||||
// L50:
|
||||
}
|
||||
} else if (beta->r != 1.f || beta->i != 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
i__3 = l + j * b_dim1;
|
||||
q__1.r = alpha->r * b[i__3].r - alpha->i * b[i__3].i,
|
||||
q__1.i = alpha->r * b[i__3].i + alpha->i * b[i__3]
|
||||
.r;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
q__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
q__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
q__1.r = c__[i__5].r + q__2.r, q__1.i = c__[i__5].i +
|
||||
q__2.i;
|
||||
c__[i__4].r = q__1.r, c__[i__4].i = q__1.i;
|
||||
// L70:
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else if (conja) {
|
||||
//
|
||||
// Form C := alpha*A**H*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
r_cnjg(&q__3, &a[l + i__ * a_dim1]);
|
||||
i__4 = l + j * b_dim1;
|
||||
q__2.r = q__3.r * b[i__4].r - q__3.i * b[i__4].i,
|
||||
q__2.i = q__3.r * b[i__4].i + q__3.i * b[i__4]
|
||||
.r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L100:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
// L120:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
i__5 = l + j * b_dim1;
|
||||
q__2.r = a[i__4].r * b[i__5].r - a[i__4].i * b[i__5]
|
||||
.i, q__2.i = a[i__4].r * b[i__5].i + a[i__4]
|
||||
.i * b[i__5].r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L130:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L140:
|
||||
}
|
||||
// L150:
|
||||
}
|
||||
}
|
||||
} else if (nota) {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A*B**H + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0.f, c__[i__3].i = 0.f;
|
||||
// L160:
|
||||
}
|
||||
} else if (beta->r != 1.f || beta->i != 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
// L170:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
r_cnjg(&q__2, &b[j + l * b_dim1]);
|
||||
q__1.r = alpha->r * q__2.r - alpha->i * q__2.i, q__1.i =
|
||||
alpha->r * q__2.i + alpha->i * q__2.r;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
q__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
q__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
q__1.r = c__[i__5].r + q__2.r, q__1.i = c__[i__5].i +
|
||||
q__2.i;
|
||||
c__[i__4].r = q__1.r, c__[i__4].i = q__1.i;
|
||||
// L180:
|
||||
}
|
||||
// L190:
|
||||
}
|
||||
// L200:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0.f, c__[i__3].i = 0.f;
|
||||
// L210:
|
||||
}
|
||||
} else if (beta->r != 1.f || beta->i != 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
// L220:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
i__3 = j + l * b_dim1;
|
||||
q__1.r = alpha->r * b[i__3].r - alpha->i * b[i__3].i,
|
||||
q__1.i = alpha->r * b[i__3].i + alpha->i * b[i__3]
|
||||
.r;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
q__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
q__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
q__1.r = c__[i__5].r + q__2.r, q__1.i = c__[i__5].i +
|
||||
q__2.i;
|
||||
c__[i__4].r = q__1.r, c__[i__4].i = q__1.i;
|
||||
// L230:
|
||||
}
|
||||
// L240:
|
||||
}
|
||||
// L250:
|
||||
}
|
||||
}
|
||||
} else if (conja) {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A**H*B**H + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
r_cnjg(&q__3, &a[l + i__ * a_dim1]);
|
||||
r_cnjg(&q__4, &b[j + l * b_dim1]);
|
||||
q__2.r = q__3.r * q__4.r - q__3.i * q__4.i, q__2.i =
|
||||
q__3.r * q__4.i + q__3.i * q__4.r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L260:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L270:
|
||||
}
|
||||
// L280:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**H*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
r_cnjg(&q__3, &a[l + i__ * a_dim1]);
|
||||
i__4 = j + l * b_dim1;
|
||||
q__2.r = q__3.r * b[i__4].r - q__3.i * b[i__4].i,
|
||||
q__2.i = q__3.r * b[i__4].i + q__3.i * b[i__4]
|
||||
.r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L290:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L300:
|
||||
}
|
||||
// L310:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A**T*B**H + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
r_cnjg(&q__3, &b[j + l * b_dim1]);
|
||||
q__2.r = a[i__4].r * q__3.r - a[i__4].i * q__3.i,
|
||||
q__2.i = a[i__4].r * q__3.i + a[i__4].i *
|
||||
q__3.r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L320:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L330:
|
||||
}
|
||||
// L340:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0.f, temp.i = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
i__5 = j + l * b_dim1;
|
||||
q__2.r = a[i__4].r * b[i__5].r - a[i__4].i * b[i__5]
|
||||
.i, q__2.i = a[i__4].r * b[i__5].i + a[i__4]
|
||||
.i * b[i__5].r;
|
||||
q__1.r = temp.r + q__2.r, q__1.i = temp.i + q__2.i;
|
||||
temp.r = q__1.r, temp.i = q__1.i;
|
||||
// L350:
|
||||
}
|
||||
if (beta->r == 0.f && beta->i == 0.f) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
q__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
q__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
q__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, q__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
q__1.r = q__2.r + q__3.r, q__1.i = q__2.i + q__3.i;
|
||||
c__[i__3].r = q__1.r, c__[i__3].i = q__1.i;
|
||||
}
|
||||
// L360:
|
||||
}
|
||||
// L370:
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of CGEMM .
|
||||
//
|
||||
} // cgemm_
|
||||
|
||||
Vendored
+171
@@ -0,0 +1,171 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DCOPY
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DCOPY(N,DX,INCX,DY,INCY)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX,INCY,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION DX(*),DY(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DCOPY copies a vector, x, to a vector, y.
|
||||
//> uses unrolled loops for increments equal to 1.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DX
|
||||
//> \verbatim
|
||||
//> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] DY
|
||||
//> \verbatim
|
||||
//> DY is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> storage spacing between elements of DY
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> jack dongarra, linpack, 3/11/78.
|
||||
//> modified 12/3/93, array(1) declarations changed to array(*)
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dcopy_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
|
||||
// Local variables
|
||||
int i__, m, ix, iy, mp1;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--dy;
|
||||
--dx;
|
||||
|
||||
// Function Body
|
||||
if (*n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (*incx == 1 && *incy == 1) {
|
||||
//
|
||||
// code for both increments equal to 1
|
||||
//
|
||||
//
|
||||
// clean-up loop
|
||||
//
|
||||
m = *n % 7;
|
||||
if (m != 0) {
|
||||
i__1 = m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dy[i__] = dx[i__];
|
||||
}
|
||||
if (*n < 7) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
mp1 = m + 1;
|
||||
i__1 = *n;
|
||||
for (i__ = mp1; i__ <= i__1; i__ += 7) {
|
||||
dy[i__] = dx[i__];
|
||||
dy[i__ + 1] = dx[i__ + 1];
|
||||
dy[i__ + 2] = dx[i__ + 2];
|
||||
dy[i__ + 3] = dx[i__ + 3];
|
||||
dy[i__ + 4] = dx[i__ + 4];
|
||||
dy[i__ + 5] = dx[i__ + 5];
|
||||
dy[i__ + 6] = dx[i__ + 6];
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// code for unequal increments or equal increments
|
||||
// not equal to 1
|
||||
//
|
||||
ix = 1;
|
||||
iy = 1;
|
||||
if (*incx < 0) {
|
||||
ix = (-(*n) + 1) * *incx + 1;
|
||||
}
|
||||
if (*incy < 0) {
|
||||
iy = (-(*n) + 1) * *incy + 1;
|
||||
}
|
||||
i__1 = *n;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dy[iy] = dx[ix];
|
||||
ix += *incx;
|
||||
iy += *incy;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // dcopy_
|
||||
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DDOT
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// DOUBLE PRECISION FUNCTION DDOT(N,DX,INCX,DY,INCY)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX,INCY,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION DX(*),DY(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DDOT forms the dot product of two vectors.
|
||||
//> uses unrolled loops for increments equal to one.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DX
|
||||
//> \verbatim
|
||||
//> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DY
|
||||
//> \verbatim
|
||||
//> DY is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> storage spacing between elements of DY
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> jack dongarra, linpack, 3/11/78.
|
||||
//> modified 12/3/93, array(1) declarations changed to array(*)
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
double ddot_(int *n, double *dx, int *incx, double *dy, int *incy)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
double ret_val;
|
||||
|
||||
// Local variables
|
||||
int i__, m, ix, iy, mp1;
|
||||
double dtemp;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--dy;
|
||||
--dx;
|
||||
|
||||
// Function Body
|
||||
ret_val = 0.;
|
||||
dtemp = 0.;
|
||||
if (*n <= 0) {
|
||||
return ret_val;
|
||||
}
|
||||
if (*incx == 1 && *incy == 1) {
|
||||
//
|
||||
// code for both increments equal to 1
|
||||
//
|
||||
//
|
||||
// clean-up loop
|
||||
//
|
||||
m = *n % 5;
|
||||
if (m != 0) {
|
||||
i__1 = m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp += dx[i__] * dy[i__];
|
||||
}
|
||||
if (*n < 5) {
|
||||
ret_val = dtemp;
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
mp1 = m + 1;
|
||||
i__1 = *n;
|
||||
for (i__ = mp1; i__ <= i__1; i__ += 5) {
|
||||
dtemp = dtemp + dx[i__] * dy[i__] + dx[i__ + 1] * dy[i__ + 1] +
|
||||
dx[i__ + 2] * dy[i__ + 2] + dx[i__ + 3] * dy[i__ + 3] +
|
||||
dx[i__ + 4] * dy[i__ + 4];
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// code for unequal increments or equal increments
|
||||
// not equal to 1
|
||||
//
|
||||
ix = 1;
|
||||
iy = 1;
|
||||
if (*incx < 0) {
|
||||
ix = (-(*n) + 1) * *incx + 1;
|
||||
}
|
||||
if (*incy < 0) {
|
||||
iy = (-(*n) + 1) * *incy + 1;
|
||||
}
|
||||
i__1 = *n;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp += dx[ix] * dy[iy];
|
||||
ix += *incx;
|
||||
iy += *incy;
|
||||
}
|
||||
}
|
||||
ret_val = dtemp;
|
||||
return ret_val;
|
||||
} // ddot_
|
||||
|
||||
Vendored
+14369
File diff suppressed because it is too large
Load Diff
Vendored
+444
@@ -0,0 +1,444 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DGEMM
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION ALPHA,BETA
|
||||
// INTEGER K,LDA,LDB,LDC,M,N
|
||||
// CHARACTER TRANSA,TRANSB
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A(LDA,*),B(LDB,*),C(LDC,*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DGEMM performs one of the matrix-matrix operations
|
||||
//>
|
||||
//> C := alpha*op( A )*op( B ) + beta*C,
|
||||
//>
|
||||
//> where op( X ) is one of
|
||||
//>
|
||||
//> op( X ) = X or op( X ) = X**T,
|
||||
//>
|
||||
//> alpha and beta are scalars, and A, B and C are matrices, with op( A )
|
||||
//> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TRANSA
|
||||
//> \verbatim
|
||||
//> TRANSA is CHARACTER*1
|
||||
//> On entry, TRANSA specifies the form of op( A ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSA = 'N' or 'n', op( A ) = A.
|
||||
//>
|
||||
//> TRANSA = 'T' or 't', op( A ) = A**T.
|
||||
//>
|
||||
//> TRANSA = 'C' or 'c', op( A ) = A**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANSB
|
||||
//> \verbatim
|
||||
//> TRANSB is CHARACTER*1
|
||||
//> On entry, TRANSB specifies the form of op( B ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSB = 'N' or 'n', op( B ) = B.
|
||||
//>
|
||||
//> TRANSB = 'T' or 't', op( B ) = B**T.
|
||||
//>
|
||||
//> TRANSB = 'C' or 'c', op( B ) = B**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix
|
||||
//> op( A ) and of the matrix C. M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix
|
||||
//> op( B ) and the number of columns of the matrix C. N must be
|
||||
//> at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> On entry, K specifies the number of columns of the matrix
|
||||
//> op( A ) and the number of rows of the matrix op( B ). K must
|
||||
//> be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION.
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension ( LDA, ka ), where ka is
|
||||
//> k when TRANSA = 'N' or 'n', and is m otherwise.
|
||||
//> Before entry with TRANSA = 'N' or 'n', the leading m by k
|
||||
//> part of the array A must contain the matrix A, otherwise
|
||||
//> the leading k by m part of the array A must contain the
|
||||
//> matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. When TRANSA = 'N' or 'n' then
|
||||
//> LDA must be at least max( 1, m ), otherwise LDA must be at
|
||||
//> least max( 1, k ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] B
|
||||
//> \verbatim
|
||||
//> B is DOUBLE PRECISION array, dimension ( LDB, kb ), where kb is
|
||||
//> n when TRANSB = 'N' or 'n', and is k otherwise.
|
||||
//> Before entry with TRANSB = 'N' or 'n', the leading k by n
|
||||
//> part of the array B must contain the matrix B, otherwise
|
||||
//> the leading n by k part of the array B must contain the
|
||||
//> matrix B.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> On entry, LDB specifies the first dimension of B as declared
|
||||
//> in the calling (sub) program. When TRANSB = 'N' or 'n' then
|
||||
//> LDB must be at least max( 1, k ), otherwise LDB must be at
|
||||
//> least max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is DOUBLE PRECISION.
|
||||
//> On entry, BETA specifies the scalar beta. When BETA is
|
||||
//> supplied as zero then C need not be set on input.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION array, dimension ( LDC, N )
|
||||
//> Before entry, the leading m by n part of the array C must
|
||||
//> contain the matrix C, except when beta is zero, in which
|
||||
//> case C need not be set on entry.
|
||||
//> On exit, the array C is overwritten by the m by n matrix
|
||||
//> ( alpha*op( A )*op( B ) + beta*C ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> On entry, LDC specifies the first dimension of C as declared
|
||||
//> in the calling (sub) program. LDC must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup double_blas_level3
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 3 Blas routine.
|
||||
//>
|
||||
//> -- Written on 8-February-1989.
|
||||
//> Jack Dongarra, Argonne National Laboratory.
|
||||
//> Iain Duff, AERE Harwell.
|
||||
//> Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
||||
//> Sven Hammarling, Numerical Algorithms Group Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, double *alpha, double *a, int *lda, double *b, int *ldb, double *
|
||||
beta, double *c__, int *ldc)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2,
|
||||
i__3;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l, info;
|
||||
int nota, notb;
|
||||
double temp;
|
||||
int ncola;
|
||||
extern int lsame_(char *, char *);
|
||||
int nrowa, nrowb;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level3 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
//
|
||||
// Set NOTA and NOTB as true if A and B respectively are not
|
||||
// transposed and set NROWA, NCOLA and NROWB as the number of rows
|
||||
// and columns of A and the number of rows of B respectively.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
|
||||
// Function Body
|
||||
nota = lsame_(transa, "N");
|
||||
notb = lsame_(transb, "N");
|
||||
if (nota) {
|
||||
nrowa = *m;
|
||||
ncola = *k;
|
||||
} else {
|
||||
nrowa = *k;
|
||||
ncola = *m;
|
||||
}
|
||||
if (notb) {
|
||||
nrowb = *k;
|
||||
} else {
|
||||
nrowb = *n;
|
||||
}
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
info = 0;
|
||||
if (! nota && ! lsame_(transa, "C") && ! lsame_(transa, "T")) {
|
||||
info = 1;
|
||||
} else if (! notb && ! lsame_(transb, "C") && ! lsame_(transb, "T")) {
|
||||
info = 2;
|
||||
} else if (*m < 0) {
|
||||
info = 3;
|
||||
} else if (*n < 0) {
|
||||
info = 4;
|
||||
} else if (*k < 0) {
|
||||
info = 5;
|
||||
} else if (*lda < max(1,nrowa)) {
|
||||
info = 8;
|
||||
} else if (*ldb < max(1,nrowb)) {
|
||||
info = 10;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
info = 13;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("DGEMM ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || (*alpha == 0. || *k == 0) && *beta == 1.) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// And if alpha.eq.zero.
|
||||
//
|
||||
if (*alpha == 0.) {
|
||||
if (*beta == 0.) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations.
|
||||
//
|
||||
if (notb) {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (*beta == 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.;
|
||||
// L50:
|
||||
}
|
||||
} else if (*beta != 1.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
temp = *alpha * b[l + j * b_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
c__[i__ + j * c_dim1] += temp * a[i__ + l * a_dim1];
|
||||
// L70:
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
temp += a[l + i__ * a_dim1] * b[l + j * b_dim1];
|
||||
// L100:
|
||||
}
|
||||
if (*beta == 0.) {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp;
|
||||
} else {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp + *beta * c__[
|
||||
i__ + j * c_dim1];
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
// L120:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (*beta == 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.;
|
||||
// L130:
|
||||
}
|
||||
} else if (*beta != 1.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L140:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
temp = *alpha * b[j + l * b_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
c__[i__ + j * c_dim1] += temp * a[i__ + l * a_dim1];
|
||||
// L150:
|
||||
}
|
||||
// L160:
|
||||
}
|
||||
// L170:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
temp += a[l + i__ * a_dim1] * b[j + l * b_dim1];
|
||||
// L180:
|
||||
}
|
||||
if (*beta == 0.) {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp;
|
||||
} else {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp + *beta * c__[
|
||||
i__ + j * c_dim1];
|
||||
}
|
||||
// L190:
|
||||
}
|
||||
// L200:
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DGEMM .
|
||||
//
|
||||
} // dgemm_
|
||||
|
||||
Vendored
+370
@@ -0,0 +1,370 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DGEMV
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DGEMV(TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION ALPHA,BETA
|
||||
// INTEGER INCX,INCY,LDA,M,N
|
||||
// CHARACTER TRANS
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DGEMV performs one of the matrix-vector operations
|
||||
//>
|
||||
//> y := alpha*A*x + beta*y, or y := alpha*A**T*x + beta*y,
|
||||
//>
|
||||
//> where alpha and beta are scalars, x and y are vectors and A is an
|
||||
//> m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TRANS
|
||||
//> \verbatim
|
||||
//> TRANS is CHARACTER*1
|
||||
//> On entry, TRANS specifies the operation to be performed as
|
||||
//> follows:
|
||||
//>
|
||||
//> TRANS = 'N' or 'n' y := alpha*A*x + beta*y.
|
||||
//>
|
||||
//> TRANS = 'T' or 't' y := alpha*A**T*x + beta*y.
|
||||
//>
|
||||
//> TRANS = 'C' or 'c' y := alpha*A**T*x + beta*y.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix A.
|
||||
//> M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix A.
|
||||
//> N must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION.
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension ( LDA, N )
|
||||
//> Before entry, the leading m by n part of the array A must
|
||||
//> contain the matrix of coefficients.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. LDA must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension at least
|
||||
//> ( 1 + ( n - 1 )*abs( INCX ) ) when TRANS = 'N' or 'n'
|
||||
//> and at least
|
||||
//> ( 1 + ( m - 1 )*abs( INCX ) ) otherwise.
|
||||
//> Before entry, the incremented array X must contain the
|
||||
//> vector x.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> On entry, INCX specifies the increment for the elements of
|
||||
//> X. INCX must not be zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is DOUBLE PRECISION.
|
||||
//> On entry, BETA specifies the scalar beta. When BETA is
|
||||
//> supplied as zero then Y need not be set on input.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] Y
|
||||
//> \verbatim
|
||||
//> Y is DOUBLE PRECISION array, dimension at least
|
||||
//> ( 1 + ( m - 1 )*abs( INCY ) ) when TRANS = 'N' or 'n'
|
||||
//> and at least
|
||||
//> ( 1 + ( n - 1 )*abs( INCY ) ) otherwise.
|
||||
//> Before entry with BETA non-zero, the incremented array Y
|
||||
//> must contain the vector y. On exit, Y is overwritten by the
|
||||
//> updated vector y.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> On entry, INCY specifies the increment for the elements of
|
||||
//> Y. INCY must not be zero.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup double_blas_level2
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 2 Blas routine.
|
||||
//> The vector and matrix arguments are not referenced when N = 0, or M = 0
|
||||
//>
|
||||
//> -- Written on 22-October-1986.
|
||||
//> Jack Dongarra, Argonne National Lab.
|
||||
//> Jeremy Du Croz, Nag Central Office.
|
||||
//> Sven Hammarling, Nag Central Office.
|
||||
//> Richard Hanson, Sandia National Labs.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dgemv_(char *trans, int *m, int *n, double *alpha,
|
||||
double *a, int *lda, double *x, int *incx, double *beta, double *y,
|
||||
int *incy)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, j, ix, iy, jx, jy, kx, ky, info;
|
||||
double temp;
|
||||
int lenx, leny;
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level2 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--x;
|
||||
--y;
|
||||
|
||||
// Function Body
|
||||
info = 0;
|
||||
if (! lsame_(trans, "N") && ! lsame_(trans, "T") && ! lsame_(trans, "C"))
|
||||
{
|
||||
info = 1;
|
||||
} else if (*m < 0) {
|
||||
info = 2;
|
||||
} else if (*n < 0) {
|
||||
info = 3;
|
||||
} else if (*lda < max(1,*m)) {
|
||||
info = 6;
|
||||
} else if (*incx == 0) {
|
||||
info = 8;
|
||||
} else if (*incy == 0) {
|
||||
info = 11;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("DGEMV ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || *alpha == 0. && *beta == 1.) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Set LENX and LENY, the lengths of the vectors x and y, and set
|
||||
// up the start points in X and Y.
|
||||
//
|
||||
if (lsame_(trans, "N")) {
|
||||
lenx = *n;
|
||||
leny = *m;
|
||||
} else {
|
||||
lenx = *m;
|
||||
leny = *n;
|
||||
}
|
||||
if (*incx > 0) {
|
||||
kx = 1;
|
||||
} else {
|
||||
kx = 1 - (lenx - 1) * *incx;
|
||||
}
|
||||
if (*incy > 0) {
|
||||
ky = 1;
|
||||
} else {
|
||||
ky = 1 - (leny - 1) * *incy;
|
||||
}
|
||||
//
|
||||
// Start the operations. In this version the elements of A are
|
||||
// accessed sequentially with one pass through A.
|
||||
//
|
||||
// First form y := beta*y.
|
||||
//
|
||||
if (*beta != 1.) {
|
||||
if (*incy == 1) {
|
||||
if (*beta == 0.) {
|
||||
i__1 = leny;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
y[i__] = 0.;
|
||||
// L10:
|
||||
}
|
||||
} else {
|
||||
i__1 = leny;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
y[i__] = *beta * y[i__];
|
||||
// L20:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iy = ky;
|
||||
if (*beta == 0.) {
|
||||
i__1 = leny;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
y[iy] = 0.;
|
||||
iy += *incy;
|
||||
// L30:
|
||||
}
|
||||
} else {
|
||||
i__1 = leny;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
y[iy] = *beta * y[iy];
|
||||
iy += *incy;
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*alpha == 0.) {
|
||||
return 0;
|
||||
}
|
||||
if (lsame_(trans, "N")) {
|
||||
//
|
||||
// Form y := alpha*A*x + y.
|
||||
//
|
||||
jx = kx;
|
||||
if (*incy == 1) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = *alpha * x[jx];
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
y[i__] += temp * a[i__ + j * a_dim1];
|
||||
// L50:
|
||||
}
|
||||
jx += *incx;
|
||||
// L60:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = *alpha * x[jx];
|
||||
iy = ky;
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
y[iy] += temp * a[i__ + j * a_dim1];
|
||||
iy += *incy;
|
||||
// L70:
|
||||
}
|
||||
jx += *incx;
|
||||
// L80:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form y := alpha*A**T*x + y.
|
||||
//
|
||||
jy = ky;
|
||||
if (*incx == 1) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = 0.;
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp += a[i__ + j * a_dim1] * x[i__];
|
||||
// L90:
|
||||
}
|
||||
y[jy] += *alpha * temp;
|
||||
jy += *incy;
|
||||
// L100:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = 0.;
|
||||
ix = kx;
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp += a[i__ + j * a_dim1] * x[ix];
|
||||
ix += *incx;
|
||||
// L110:
|
||||
}
|
||||
y[jy] += *alpha * temp;
|
||||
jy += *incy;
|
||||
// L120:
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DGEMV .
|
||||
//
|
||||
} // dgemv_
|
||||
|
||||
Vendored
+18599
File diff suppressed because it is too large
Load Diff
Vendored
+186
@@ -0,0 +1,186 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DISNAN tests input for NaN.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DISNAN + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/disnan.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/disnan.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/disnan.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// LOGICAL FUNCTION DISNAN( DIN )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION, INTENT(IN) :: DIN
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DISNAN returns .TRUE. if its argument is NaN, and .FALSE.
|
||||
//> otherwise. To be replaced by the Fortran 2003 intrinsic in the
|
||||
//> future.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] DIN
|
||||
//> \verbatim
|
||||
//> DIN is DOUBLE PRECISION
|
||||
//> Input to test for NaN.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date June 2017
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
int disnan_(double *din)
|
||||
{
|
||||
// System generated locals
|
||||
int ret_val;
|
||||
|
||||
// Local variables
|
||||
extern int dlaisnan_(double *, double *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.1) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// June 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
ret_val = dlaisnan_(din, din);
|
||||
return ret_val;
|
||||
} // disnan_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLAISNAN + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaisnan.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaisnan.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaisnan.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION, INTENT(IN) :: DIN1, DIN2
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> This routine is not for general use. It exists solely to avoid
|
||||
//> over-optimization in DISNAN.
|
||||
//>
|
||||
//> DLAISNAN checks for NaNs by comparing its two arguments for
|
||||
//> inequality. NaN is the only floating-point value where NaN != NaN
|
||||
//> returns .TRUE. To check for NaNs, pass the same variable as both
|
||||
//> arguments.
|
||||
//>
|
||||
//> A compiler must assume that the two arguments are
|
||||
//> not the same variable, and the test will not be optimized away.
|
||||
//> Interprocedural or whole-program optimization may delete this
|
||||
//> test. The ISNAN functions will be replaced by the correct
|
||||
//> Fortran 03 intrinsic once the intrinsic is widely available.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] DIN1
|
||||
//> \verbatim
|
||||
//> DIN1 is DOUBLE PRECISION
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DIN2
|
||||
//> \verbatim
|
||||
//> DIN2 is DOUBLE PRECISION
|
||||
//> Two numbers to compare for inequality.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date June 2017
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
int dlaisnan_(double *din1, double *din2)
|
||||
{
|
||||
// System generated locals
|
||||
int ret_val;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.1) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// June 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Executable Statements ..
|
||||
ret_val = *din1 != *din2;
|
||||
return ret_val;
|
||||
} // dlaisnan_
|
||||
|
||||
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLACPY copies all or part of one two-dimensional array to another.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLACPY + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlacpy.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlacpy.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlacpy.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLACPY( UPLO, M, N, A, LDA, B, LDB )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER UPLO
|
||||
// INTEGER LDA, LDB, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), B( LDB, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLACPY copies all or part of a two-dimensional matrix A to another
|
||||
//> matrix B.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] UPLO
|
||||
//> \verbatim
|
||||
//> UPLO is CHARACTER*1
|
||||
//> Specifies the part of the matrix A to be copied to B.
|
||||
//> = 'U': Upper triangular part
|
||||
//> = 'L': Lower triangular part
|
||||
//> Otherwise: All of the matrix A
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> The m by n matrix A. If UPLO = 'U', only the upper triangle
|
||||
//> or trapezoid is accessed; if UPLO = 'L', only the lower
|
||||
//> triangle or trapezoid is accessed.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] B
|
||||
//> \verbatim
|
||||
//> B is DOUBLE PRECISION array, dimension (LDB,N)
|
||||
//> On exit, B = A in the locations specified by UPLO.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> The leading dimension of the array B. LDB >= max(1,M).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlacpy_(char *uplo, int *m, int *n, double *a, int *lda,
|
||||
double *b, int *ldb)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, j;
|
||||
extern int lsame_(char *, char *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
|
||||
// Function Body
|
||||
if (lsame_(uplo, "U")) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = min(j,*m);
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] = a[i__ + j * a_dim1];
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else if (lsame_(uplo, "L")) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = j; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] = a[i__ + j * a_dim1];
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] = a[i__ + j * a_dim1];
|
||||
// L50:
|
||||
}
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLACPY
|
||||
//
|
||||
} // dlacpy_
|
||||
|
||||
Vendored
+367
@@ -0,0 +1,367 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DCOMBSSQ adds two scaled sum of squares quantities.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DCOMBSSQ( V1, V2 )
|
||||
//
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION V1( 2 ), V2( 2 )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DCOMBSSQ adds two scaled sum of squares quantities, V1 := V1 + V2.
|
||||
//> That is,
|
||||
//>
|
||||
//> V1_scale**2 * V1_sumsq := V1_scale**2 * V1_sumsq
|
||||
//> + V2_scale**2 * V2_sumsq
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in,out] V1
|
||||
//> \verbatim
|
||||
//> V1 is DOUBLE PRECISION array, dimension (2).
|
||||
//> The first scaled sum.
|
||||
//> V1(1) = V1_scale, V1(2) = V1_sumsq.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] V2
|
||||
//> \verbatim
|
||||
//> V2 is DOUBLE PRECISION array, dimension (2).
|
||||
//> The second scaled sum.
|
||||
//> V2(1) = V2_scale, V2(2) = V2_sumsq.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2018
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dcombssq_(double *v1, double *v2)
|
||||
{
|
||||
// System generated locals
|
||||
double d__1;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2018
|
||||
//
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
//=====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
--v2;
|
||||
--v1;
|
||||
|
||||
// Function Body
|
||||
if (v1[1] >= v2[1]) {
|
||||
if (v1[1] != 0.) {
|
||||
// Computing 2nd power
|
||||
d__1 = v2[1] / v1[1];
|
||||
v1[2] += d__1 * d__1 * v2[2];
|
||||
}
|
||||
} else {
|
||||
// Computing 2nd power
|
||||
d__1 = v1[1] / v2[1];
|
||||
v1[2] = v2[2] + d__1 * d__1 * v1[2];
|
||||
v1[1] = v2[1];
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DCOMBSSQ
|
||||
//
|
||||
} // dcombssq_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value of any element of a general rectangular matrix.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLANGE + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlange.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlange.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlange.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// DOUBLE PRECISION FUNCTION DLANGE( NORM, M, N, A, LDA, WORK )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER NORM
|
||||
// INTEGER LDA, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLANGE returns the value of the one norm, or the Frobenius norm, or
|
||||
//> the infinity norm, or the element of largest absolute value of a
|
||||
//> real matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \return DLANGE
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLANGE = ( max(abs(A(i,j))), NORM = 'M' or 'm'
|
||||
//> (
|
||||
//> ( norm1(A), NORM = '1', 'O' or 'o'
|
||||
//> (
|
||||
//> ( normI(A), NORM = 'I' or 'i'
|
||||
//> (
|
||||
//> ( normF(A), NORM = 'F', 'f', 'E' or 'e'
|
||||
//>
|
||||
//> where norm1 denotes the one norm of a matrix (maximum column sum),
|
||||
//> normI denotes the infinity norm of a matrix (maximum row sum) and
|
||||
//> normF denotes the Frobenius norm of a matrix (square root of sum of
|
||||
//> squares). Note that max(abs(A(i,j))) is not a consistent matrix norm.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] NORM
|
||||
//> \verbatim
|
||||
//> NORM is CHARACTER*1
|
||||
//> Specifies the value to be returned in DLANGE as described
|
||||
//> above.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A. M >= 0. When M = 0,
|
||||
//> DLANGE is set to zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A. N >= 0. When N = 0,
|
||||
//> DLANGE is set to zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> The m by n matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A. LDA >= max(M,1).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)),
|
||||
//> where LWORK >= M when NORM = 'I'; otherwise, WORK is not
|
||||
//> referenced.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleGEauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2;
|
||||
double ret_val, d__1;
|
||||
|
||||
// Local variables
|
||||
extern /* Subroutine */ int dcombssq_(double *, double *);
|
||||
int i__, j;
|
||||
double sum, ssq[2], temp;
|
||||
extern int lsame_(char *, char *);
|
||||
double value;
|
||||
extern int disnan_(double *);
|
||||
extern /* Subroutine */ int dlassq_(int *, double *, int *, double *,
|
||||
double *);
|
||||
double colssq[2];
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
//=====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Local Arrays ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
if (min(*m,*n) == 0) {
|
||||
value = 0.;
|
||||
} else if (lsame_(norm, "M")) {
|
||||
//
|
||||
// Find max(abs(A(i,j))).
|
||||
//
|
||||
value = 0.;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = (d__1 = a[i__ + j * a_dim1], abs(d__1));
|
||||
if (value < temp || disnan_(&temp)) {
|
||||
value = temp;
|
||||
}
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else if (lsame_(norm, "O") || *(unsigned char *)norm == '1') {
|
||||
//
|
||||
// Find norm1(A).
|
||||
//
|
||||
value = 0.;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
sum = 0.;
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
sum += (d__1 = a[i__ + j * a_dim1], abs(d__1));
|
||||
// L30:
|
||||
}
|
||||
if (value < sum || disnan_(&sum)) {
|
||||
value = sum;
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
} else if (lsame_(norm, "I")) {
|
||||
//
|
||||
// Find normI(A).
|
||||
//
|
||||
i__1 = *m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
work[i__] = 0.;
|
||||
// L50:
|
||||
}
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
work[i__] += (d__1 = a[i__ + j * a_dim1], abs(d__1));
|
||||
// L60:
|
||||
}
|
||||
// L70:
|
||||
}
|
||||
value = 0.;
|
||||
i__1 = *m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
temp = work[i__];
|
||||
if (value < temp || disnan_(&temp)) {
|
||||
value = temp;
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
} else if (lsame_(norm, "F") || lsame_(norm, "E")) {
|
||||
//
|
||||
// Find normF(A).
|
||||
// SSQ(1) is scale
|
||||
// SSQ(2) is sum-of-squares
|
||||
// For better accuracy, sum each column separately.
|
||||
//
|
||||
ssq[0] = 0.;
|
||||
ssq[1] = 1.;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
colssq[0] = 0.;
|
||||
colssq[1] = 1.;
|
||||
dlassq_(m, &a[j * a_dim1 + 1], &c__1, colssq, &colssq[1]);
|
||||
dcombssq_(ssq, colssq);
|
||||
// L90:
|
||||
}
|
||||
value = ssq[0] * sqrt(ssq[1]);
|
||||
}
|
||||
ret_val = value;
|
||||
return ret_val;
|
||||
//
|
||||
// End of DLANGE
|
||||
//
|
||||
} // dlange_
|
||||
|
||||
Vendored
+125
@@ -0,0 +1,125 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLAPY2 returns sqrt(x2+y2).
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLAPY2 + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlapy2.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlapy2.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlapy2.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// DOUBLE PRECISION FUNCTION DLAPY2( X, Y )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION X, Y
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLAPY2 returns sqrt(x**2+y**2), taking care not to cause unnecessary
|
||||
//> overflow.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] Y
|
||||
//> \verbatim
|
||||
//> Y is DOUBLE PRECISION
|
||||
//> X and Y specify the values x and y.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date June 2017
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
double dlapy2_(double *x, double *y)
|
||||
{
|
||||
// System generated locals
|
||||
double ret_val, d__1;
|
||||
|
||||
// Local variables
|
||||
int x_is_nan__, y_is_nan__;
|
||||
double w, z__, xabs, yabs;
|
||||
extern int disnan_(double *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.1) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// June 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
x_is_nan__ = disnan_(x);
|
||||
y_is_nan__ = disnan_(y);
|
||||
if (x_is_nan__) {
|
||||
ret_val = *x;
|
||||
}
|
||||
if (y_is_nan__) {
|
||||
ret_val = *y;
|
||||
}
|
||||
if (! (x_is_nan__ || y_is_nan__)) {
|
||||
xabs = abs(*x);
|
||||
yabs = abs(*y);
|
||||
w = max(xabs,yabs);
|
||||
z__ = min(xabs,yabs);
|
||||
if (z__ == 0.) {
|
||||
ret_val = w;
|
||||
} else {
|
||||
// Computing 2nd power
|
||||
d__1 = z__ / w;
|
||||
ret_val = w * sqrt(d__1 * d__1 + 1.);
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
//
|
||||
// End of DLAPY2
|
||||
//
|
||||
} // dlapy2_
|
||||
|
||||
Vendored
+768
@@ -0,0 +1,768 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DGER
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DGER(M,N,ALPHA,X,INCX,Y,INCY,A,LDA)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION ALPHA
|
||||
// INTEGER INCX,INCY,LDA,M,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A(LDA,*),X(*),Y(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DGER performs the rank 1 operation
|
||||
//>
|
||||
//> A := alpha*x*y**T + A,
|
||||
//>
|
||||
//> where alpha is a scalar, x is an m element vector, y is an n element
|
||||
//> vector and A is an m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix A.
|
||||
//> M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix A.
|
||||
//> N must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION.
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension at least
|
||||
//> ( 1 + ( m - 1 )*abs( INCX ) ).
|
||||
//> Before entry, the incremented array X must contain the m
|
||||
//> element vector x.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> On entry, INCX specifies the increment for the elements of
|
||||
//> X. INCX must not be zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] Y
|
||||
//> \verbatim
|
||||
//> Y is DOUBLE PRECISION array, dimension at least
|
||||
//> ( 1 + ( n - 1 )*abs( INCY ) ).
|
||||
//> Before entry, the incremented array Y must contain the n
|
||||
//> element vector y.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> On entry, INCY specifies the increment for the elements of
|
||||
//> Y. INCY must not be zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension ( LDA, N )
|
||||
//> Before entry, the leading m by n part of the array A must
|
||||
//> contain the matrix of coefficients. On exit, A is
|
||||
//> overwritten by the updated matrix.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. LDA must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup double_blas_level2
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 2 Blas routine.
|
||||
//>
|
||||
//> -- Written on 22-October-1986.
|
||||
//> Jack Dongarra, Argonne National Lab.
|
||||
//> Jeremy Du Croz, Nag Central Office.
|
||||
//> Sven Hammarling, Nag Central Office.
|
||||
//> Richard Hanson, Sandia National Labs.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dger_(int *m, int *n, double *alpha, double *x, int *
|
||||
incx, double *y, int *incy, double *a, int *lda)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, j, ix, jy, kx, info;
|
||||
double temp;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level2 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
// Parameter adjustments
|
||||
--x;
|
||||
--y;
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
|
||||
// Function Body
|
||||
info = 0;
|
||||
if (*m < 0) {
|
||||
info = 1;
|
||||
} else if (*n < 0) {
|
||||
info = 2;
|
||||
} else if (*incx == 0) {
|
||||
info = 5;
|
||||
} else if (*incy == 0) {
|
||||
info = 7;
|
||||
} else if (*lda < max(1,*m)) {
|
||||
info = 9;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("DGER ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || *alpha == 0.) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations. In this version the elements of A are
|
||||
// accessed sequentially with one pass through A.
|
||||
//
|
||||
if (*incy > 0) {
|
||||
jy = 1;
|
||||
} else {
|
||||
jy = 1 - (*n - 1) * *incy;
|
||||
}
|
||||
if (*incx == 1) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (y[jy] != 0.) {
|
||||
temp = *alpha * y[jy];
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] += x[i__] * temp;
|
||||
// L10:
|
||||
}
|
||||
}
|
||||
jy += *incy;
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
if (*incx > 0) {
|
||||
kx = 1;
|
||||
} else {
|
||||
kx = 1 - (*m - 1) * *incx;
|
||||
}
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (y[jy] != 0.) {
|
||||
temp = *alpha * y[jy];
|
||||
ix = kx;
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] += x[ix] * temp;
|
||||
ix += *incx;
|
||||
// L30:
|
||||
}
|
||||
}
|
||||
jy += *incy;
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DGER .
|
||||
//
|
||||
} // dger_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b DLARF applies an elementary reflector to a general rectangular matrix.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLARF + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarf.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarf.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarf.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLARF( SIDE, M, N, V, INCV, TAU, C, LDC, WORK )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER SIDE
|
||||
// INTEGER INCV, LDC, M, N
|
||||
// DOUBLE PRECISION TAU
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION C( LDC, * ), V( * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLARF applies a real elementary reflector H to a real m by n matrix
|
||||
//> C, from either the left or the right. H is represented in the form
|
||||
//>
|
||||
//> H = I - tau * v * v**T
|
||||
//>
|
||||
//> where tau is a real scalar and v is a real vector.
|
||||
//>
|
||||
//> If tau = 0, then H is taken to be the unit matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] SIDE
|
||||
//> \verbatim
|
||||
//> SIDE is CHARACTER*1
|
||||
//> = 'L': form H * C
|
||||
//> = 'R': form C * H
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix C.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix C.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] V
|
||||
//> \verbatim
|
||||
//> V is DOUBLE PRECISION array, dimension
|
||||
//> (1 + (M-1)*abs(INCV)) if SIDE = 'L'
|
||||
//> or (1 + (N-1)*abs(INCV)) if SIDE = 'R'
|
||||
//> The vector v in the representation of H. V is not used if
|
||||
//> TAU = 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCV
|
||||
//> \verbatim
|
||||
//> INCV is INTEGER
|
||||
//> The increment between elements of v. INCV <> 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION
|
||||
//> The value tau in the representation of H.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION array, dimension (LDC,N)
|
||||
//> On entry, the m by n matrix C.
|
||||
//> On exit, C is overwritten by the matrix H * C if SIDE = 'L',
|
||||
//> or C * H if SIDE = 'R'.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> The leading dimension of the array C. LDC >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension
|
||||
//> (N) if SIDE = 'L'
|
||||
//> or (M) if SIDE = 'R'
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlarf_(char *side, int *m, int *n, double *v, int *incv,
|
||||
double *tau, double *c__, int *ldc, double *work)
|
||||
{
|
||||
// Table of constant values
|
||||
double c_b4 = 1.;
|
||||
double c_b5 = 0.;
|
||||
int c__1 = 1;
|
||||
|
||||
// System generated locals
|
||||
int c_dim1, c_offset;
|
||||
double d__1;
|
||||
|
||||
// Local variables
|
||||
int i__;
|
||||
int applyleft;
|
||||
extern /* Subroutine */ int dger_(int *, int *, double *, double *, int *,
|
||||
double *, int *, double *, int *);
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int dgemv_(char *, int *, int *, double *, double
|
||||
*, int *, double *, int *, double *, double *, int *);
|
||||
int lastc, lastv;
|
||||
extern int iladlc_(int *, int *, double *, int *), iladlr_(int *, int *,
|
||||
double *, int *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
--v;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
applyleft = lsame_(side, "L");
|
||||
lastv = 0;
|
||||
lastc = 0;
|
||||
if (*tau != 0.) {
|
||||
// Set up variables for scanning V. LASTV begins pointing to the end
|
||||
// of V.
|
||||
if (applyleft) {
|
||||
lastv = *m;
|
||||
} else {
|
||||
lastv = *n;
|
||||
}
|
||||
if (*incv > 0) {
|
||||
i__ = (lastv - 1) * *incv + 1;
|
||||
} else {
|
||||
i__ = 1;
|
||||
}
|
||||
// Look for the last non-zero row in V.
|
||||
while(lastv > 0 && v[i__] == 0.) {
|
||||
--lastv;
|
||||
i__ -= *incv;
|
||||
}
|
||||
if (applyleft) {
|
||||
// Scan for the last non-zero column in C(1:lastv,:).
|
||||
lastc = iladlc_(&lastv, n, &c__[c_offset], ldc);
|
||||
} else {
|
||||
// Scan for the last non-zero row in C(:,1:lastv).
|
||||
lastc = iladlr_(m, &lastv, &c__[c_offset], ldc);
|
||||
}
|
||||
}
|
||||
// Note that lastc.eq.0 renders the BLAS operations null; no special
|
||||
// case is needed at this level.
|
||||
if (applyleft) {
|
||||
//
|
||||
// Form H * C
|
||||
//
|
||||
if (lastv > 0) {
|
||||
//
|
||||
// w(1:lastc,1) := C(1:lastv,1:lastc)**T * v(1:lastv,1)
|
||||
//
|
||||
dgemv_("Transpose", &lastv, &lastc, &c_b4, &c__[c_offset], ldc, &
|
||||
v[1], incv, &c_b5, &work[1], &c__1);
|
||||
//
|
||||
// C(1:lastv,1:lastc) := C(...) - v(1:lastv,1) * w(1:lastc,1)**T
|
||||
//
|
||||
d__1 = -(*tau);
|
||||
dger_(&lastv, &lastc, &d__1, &v[1], incv, &work[1], &c__1, &c__[
|
||||
c_offset], ldc);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C * H
|
||||
//
|
||||
if (lastv > 0) {
|
||||
//
|
||||
// w(1:lastc,1) := C(1:lastc,1:lastv) * v(1:lastv,1)
|
||||
//
|
||||
dgemv_("No transpose", &lastc, &lastv, &c_b4, &c__[c_offset], ldc,
|
||||
&v[1], incv, &c_b5, &work[1], &c__1);
|
||||
//
|
||||
// C(1:lastc,1:lastv) := C(...) - w(1:lastc,1) * v(1:lastv,1)**T
|
||||
//
|
||||
d__1 = -(*tau);
|
||||
dger_(&lastc, &lastv, &d__1, &work[1], &c__1, &v[1], incv, &c__[
|
||||
c_offset], ldc);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLARF
|
||||
//
|
||||
} // dlarf_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b ILADLC scans a matrix for its last non-zero column.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download ILADLC + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlc.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlc.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlc.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// INTEGER FUNCTION ILADLC( M, N, A, LDA )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER M, N, LDA
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> ILADLC scans A for its last non-zero column.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> The m by n matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
int iladlc_(int *m, int *n, double *a, int *lda)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, ret_val, i__1;
|
||||
|
||||
// Local variables
|
||||
int i__;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Quick test for the common case where one corner is non-zero.
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
|
||||
// Function Body
|
||||
if (*n == 0) {
|
||||
ret_val = *n;
|
||||
} else if (a[*n * a_dim1 + 1] != 0. || a[*m + *n * a_dim1] != 0.) {
|
||||
ret_val = *n;
|
||||
} else {
|
||||
// Now scan each column from the end, returning with the first non-zero.
|
||||
for (ret_val = *n; ret_val >= 1; --ret_val) {
|
||||
i__1 = *m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
if (a[i__ + ret_val * a_dim1] != 0.) {
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
} // iladlc_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b ILADLR scans a matrix for its last non-zero row.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download ILADLR + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/iladlr.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/iladlr.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/iladlr.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// INTEGER FUNCTION ILADLR( M, N, A, LDA )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER M, N, LDA
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> ILADLR scans A for its last non-zero row.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> The m by n matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
int iladlr_(int *m, int *n, double *a, int *lda)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, ret_val, i__1;
|
||||
|
||||
// Local variables
|
||||
int i__, j;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Quick test for the common case where one corner is non-zero.
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
|
||||
// Function Body
|
||||
if (*m == 0) {
|
||||
ret_val = *m;
|
||||
} else if (a[*m + a_dim1] != 0. || a[*m + *n * a_dim1] != 0.) {
|
||||
ret_val = *m;
|
||||
} else {
|
||||
// Scan up each column tracking the last zero row seen.
|
||||
ret_val = 0;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__ = *m;
|
||||
while(a[max(i__,1) + j * a_dim1] == 0. && i__ >= 1) {
|
||||
--i__;
|
||||
}
|
||||
ret_val = max(ret_val,i__);
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
} // iladlr_
|
||||
|
||||
Vendored
+824
@@ -0,0 +1,824 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLARFB applies a block reflector or its transpose to a general rectangular matrix.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLARFB + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarfb.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarfb.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfb.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
|
||||
// T, LDT, C, LDC, WORK, LDWORK )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER DIRECT, SIDE, STOREV, TRANS
|
||||
// INTEGER K, LDC, LDT, LDV, LDWORK, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
|
||||
// $ WORK( LDWORK, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLARFB applies a real block reflector H or its transpose H**T to a
|
||||
//> real m by n matrix C, from either the left or the right.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] SIDE
|
||||
//> \verbatim
|
||||
//> SIDE is CHARACTER*1
|
||||
//> = 'L': apply H or H**T from the Left
|
||||
//> = 'R': apply H or H**T from the Right
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANS
|
||||
//> \verbatim
|
||||
//> TRANS is CHARACTER*1
|
||||
//> = 'N': apply H (No transpose)
|
||||
//> = 'T': apply H**T (Transpose)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DIRECT
|
||||
//> \verbatim
|
||||
//> DIRECT is CHARACTER*1
|
||||
//> Indicates how H is formed from a product of elementary
|
||||
//> reflectors
|
||||
//> = 'F': H = H(1) H(2) . . . H(k) (Forward)
|
||||
//> = 'B': H = H(k) . . . H(2) H(1) (Backward)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] STOREV
|
||||
//> \verbatim
|
||||
//> STOREV is CHARACTER*1
|
||||
//> Indicates how the vectors which define the elementary
|
||||
//> reflectors are stored:
|
||||
//> = 'C': Columnwise
|
||||
//> = 'R': Rowwise
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix C.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix C.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The order of the matrix T (= the number of elementary
|
||||
//> reflectors whose product defines the block reflector).
|
||||
//> If SIDE = 'L', M >= K >= 0;
|
||||
//> if SIDE = 'R', N >= K >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] V
|
||||
//> \verbatim
|
||||
//> V is DOUBLE PRECISION array, dimension
|
||||
//> (LDV,K) if STOREV = 'C'
|
||||
//> (LDV,M) if STOREV = 'R' and SIDE = 'L'
|
||||
//> (LDV,N) if STOREV = 'R' and SIDE = 'R'
|
||||
//> The matrix V. See Further Details.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDV
|
||||
//> \verbatim
|
||||
//> LDV is INTEGER
|
||||
//> The leading dimension of the array V.
|
||||
//> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
|
||||
//> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
|
||||
//> if STOREV = 'R', LDV >= K.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] T
|
||||
//> \verbatim
|
||||
//> T is DOUBLE PRECISION array, dimension (LDT,K)
|
||||
//> The triangular k by k matrix T in the representation of the
|
||||
//> block reflector.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDT
|
||||
//> \verbatim
|
||||
//> LDT is INTEGER
|
||||
//> The leading dimension of the array T. LDT >= K.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION array, dimension (LDC,N)
|
||||
//> On entry, the m by n matrix C.
|
||||
//> On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> The leading dimension of the array C. LDC >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension (LDWORK,K)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDWORK
|
||||
//> \verbatim
|
||||
//> LDWORK is INTEGER
|
||||
//> The leading dimension of the array WORK.
|
||||
//> If SIDE = 'L', LDWORK >= max(1,N);
|
||||
//> if SIDE = 'R', LDWORK >= max(1,M).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date June 2013
|
||||
//
|
||||
//> \ingroup doubleOTHERauxiliary
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> The shape of the matrix V and the storage of the vectors which define
|
||||
//> the H(i) is best illustrated by the following example with n = 5 and
|
||||
//> k = 3. The elements equal to 1 are not stored; the corresponding
|
||||
//> array elements are modified but restored on exit. The rest of the
|
||||
//> array is not used.
|
||||
//>
|
||||
//> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
|
||||
//>
|
||||
//> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
|
||||
//> ( v1 1 ) ( 1 v2 v2 v2 )
|
||||
//> ( v1 v2 1 ) ( 1 v3 v3 )
|
||||
//> ( v1 v2 v3 )
|
||||
//> ( v1 v2 v3 )
|
||||
//>
|
||||
//> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
|
||||
//>
|
||||
//> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
|
||||
//> ( v1 v2 v3 ) ( v2 v2 v2 1 )
|
||||
//> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
|
||||
//> ( 1 v3 )
|
||||
//> ( 1 )
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlarfb_(char *side, char *trans, char *direct, char *
|
||||
storev, int *m, int *n, int *k, double *v, int *ldv, double *t, int *
|
||||
ldt, double *c__, int *ldc, double *work, int *ldwork)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
double c_b14 = 1.;
|
||||
double c_b25 = -1.;
|
||||
|
||||
// System generated locals
|
||||
int c_dim1, c_offset, t_dim1, t_offset, v_dim1, v_offset, work_dim1,
|
||||
work_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, j;
|
||||
extern /* Subroutine */ int dgemm_(char *, char *, int *, int *, int *,
|
||||
double *, double *, int *, double *, int *, double *, double *,
|
||||
int *);
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int dcopy_(int *, double *, int *, double *, int *
|
||||
), dtrmm_(char *, char *, char *, char *, int *, int *, double *,
|
||||
double *, int *, double *, int *);
|
||||
char transt[1+1]={'\0'};
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// June 2013
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
// Parameter adjustments
|
||||
v_dim1 = *ldv;
|
||||
v_offset = 1 + v_dim1;
|
||||
v -= v_offset;
|
||||
t_dim1 = *ldt;
|
||||
t_offset = 1 + t_dim1;
|
||||
t -= t_offset;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
work_dim1 = *ldwork;
|
||||
work_offset = 1 + work_dim1;
|
||||
work -= work_offset;
|
||||
|
||||
// Function Body
|
||||
if (*m <= 0 || *n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lsame_(trans, "N")) {
|
||||
*(unsigned char *)transt = 'T';
|
||||
} else {
|
||||
*(unsigned char *)transt = 'N';
|
||||
}
|
||||
if (lsame_(storev, "C")) {
|
||||
if (lsame_(direct, "F")) {
|
||||
//
|
||||
// Let V = ( V1 ) (first K rows)
|
||||
// ( V2 )
|
||||
// where V1 is unit lower triangular.
|
||||
//
|
||||
if (lsame_(side, "L")) {
|
||||
//
|
||||
// Form H * C or H**T * C where C = ( C1 )
|
||||
// ( C2 )
|
||||
//
|
||||
// W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
|
||||
//
|
||||
// W := C1**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(n, &c__[j + c_dim1], ldc, &work[j * work_dim1 + 1],
|
||||
&c__1);
|
||||
// L10:
|
||||
}
|
||||
//
|
||||
// W := W * V1
|
||||
//
|
||||
dtrmm_("Right", "Lower", "No transpose", "Unit", n, k, &c_b14,
|
||||
&v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
if (*m > *k) {
|
||||
//
|
||||
// W := W + C2**T * V2
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "No transpose", n, k, &i__1, &c_b14, &
|
||||
c__[*k + 1 + c_dim1], ldc, &v[*k + 1 + v_dim1],
|
||||
ldv, &c_b14, &work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T**T or W * T
|
||||
//
|
||||
dtrmm_("Right", "Upper", transt, "Non-unit", n, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - V * W**T
|
||||
//
|
||||
if (*m > *k) {
|
||||
//
|
||||
// C2 := C2 - V2 * W**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("No transpose", "Transpose", &i__1, n, k, &c_b25, &
|
||||
v[*k + 1 + v_dim1], ldv, &work[work_offset],
|
||||
ldwork, &c_b14, &c__[*k + 1 + c_dim1], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V1**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", "Transpose", "Unit", n, k, &c_b14, &
|
||||
v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
//
|
||||
// C1 := C1 - W**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *n;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[j + i__ * c_dim1] -= work[i__ + j * work_dim1];
|
||||
// L20:
|
||||
}
|
||||
// L30:
|
||||
}
|
||||
} else if (lsame_(side, "R")) {
|
||||
//
|
||||
// Form C * H or C * H**T where C = ( C1 C2 )
|
||||
//
|
||||
// W := C * V = (C1*V1 + C2*V2) (stored in WORK)
|
||||
//
|
||||
// W := C1
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(m, &c__[j * c_dim1 + 1], &c__1, &work[j *
|
||||
work_dim1 + 1], &c__1);
|
||||
// L40:
|
||||
}
|
||||
//
|
||||
// W := W * V1
|
||||
//
|
||||
dtrmm_("Right", "Lower", "No transpose", "Unit", m, k, &c_b14,
|
||||
&v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
if (*n > *k) {
|
||||
//
|
||||
// W := W + C2 * V2
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "No transpose", m, k, &i__1, &
|
||||
c_b14, &c__[(*k + 1) * c_dim1 + 1], ldc, &v[*k +
|
||||
1 + v_dim1], ldv, &c_b14, &work[work_offset],
|
||||
ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T or W * T**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", trans, "Non-unit", m, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - W * V**T
|
||||
//
|
||||
if (*n > *k) {
|
||||
//
|
||||
// C2 := C2 - W * V2**T
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "Transpose", m, &i__1, k, &c_b25, &
|
||||
work[work_offset], ldwork, &v[*k + 1 + v_dim1],
|
||||
ldv, &c_b14, &c__[(*k + 1) * c_dim1 + 1], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V1**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", "Transpose", "Unit", m, k, &c_b14, &
|
||||
v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
//
|
||||
// C1 := C1 - W
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] -= work[i__ + j * work_dim1];
|
||||
// L50:
|
||||
}
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Let V = ( V1 )
|
||||
// ( V2 ) (last K rows)
|
||||
// where V2 is unit upper triangular.
|
||||
//
|
||||
if (lsame_(side, "L")) {
|
||||
//
|
||||
// Form H * C or H**T * C where C = ( C1 )
|
||||
// ( C2 )
|
||||
//
|
||||
// W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
|
||||
//
|
||||
// W := C2**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(n, &c__[*m - *k + j + c_dim1], ldc, &work[j *
|
||||
work_dim1 + 1], &c__1);
|
||||
// L70:
|
||||
}
|
||||
//
|
||||
// W := W * V2
|
||||
//
|
||||
dtrmm_("Right", "Upper", "No transpose", "Unit", n, k, &c_b14,
|
||||
&v[*m - *k + 1 + v_dim1], ldv, &work[work_offset],
|
||||
ldwork);
|
||||
if (*m > *k) {
|
||||
//
|
||||
// W := W + C1**T * V1
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "No transpose", n, k, &i__1, &c_b14, &
|
||||
c__[c_offset], ldc, &v[v_offset], ldv, &c_b14, &
|
||||
work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T**T or W * T
|
||||
//
|
||||
dtrmm_("Right", "Lower", transt, "Non-unit", n, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - V * W**T
|
||||
//
|
||||
if (*m > *k) {
|
||||
//
|
||||
// C1 := C1 - V1 * W**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("No transpose", "Transpose", &i__1, n, k, &c_b25, &
|
||||
v[v_offset], ldv, &work[work_offset], ldwork, &
|
||||
c_b14, &c__[c_offset], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V2**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", "Transpose", "Unit", n, k, &c_b14, &
|
||||
v[*m - *k + 1 + v_dim1], ldv, &work[work_offset],
|
||||
ldwork);
|
||||
//
|
||||
// C2 := C2 - W**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *n;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[*m - *k + j + i__ * c_dim1] -= work[i__ + j *
|
||||
work_dim1];
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else if (lsame_(side, "R")) {
|
||||
//
|
||||
// Form C * H or C * H**T where C = ( C1 C2 )
|
||||
//
|
||||
// W := C * V = (C1*V1 + C2*V2) (stored in WORK)
|
||||
//
|
||||
// W := C2
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(m, &c__[(*n - *k + j) * c_dim1 + 1], &c__1, &work[
|
||||
j * work_dim1 + 1], &c__1);
|
||||
// L100:
|
||||
}
|
||||
//
|
||||
// W := W * V2
|
||||
//
|
||||
dtrmm_("Right", "Upper", "No transpose", "Unit", m, k, &c_b14,
|
||||
&v[*n - *k + 1 + v_dim1], ldv, &work[work_offset],
|
||||
ldwork);
|
||||
if (*n > *k) {
|
||||
//
|
||||
// W := W + C1 * V1
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "No transpose", m, k, &i__1, &
|
||||
c_b14, &c__[c_offset], ldc, &v[v_offset], ldv, &
|
||||
c_b14, &work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T or W * T**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", trans, "Non-unit", m, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - W * V**T
|
||||
//
|
||||
if (*n > *k) {
|
||||
//
|
||||
// C1 := C1 - W * V1**T
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "Transpose", m, &i__1, k, &c_b25, &
|
||||
work[work_offset], ldwork, &v[v_offset], ldv, &
|
||||
c_b14, &c__[c_offset], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V2**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", "Transpose", "Unit", m, k, &c_b14, &
|
||||
v[*n - *k + 1 + v_dim1], ldv, &work[work_offset],
|
||||
ldwork);
|
||||
//
|
||||
// C2 := C2 - W
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + (*n - *k + j) * c_dim1] -= work[i__ + j *
|
||||
work_dim1];
|
||||
// L110:
|
||||
}
|
||||
// L120:
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (lsame_(storev, "R")) {
|
||||
if (lsame_(direct, "F")) {
|
||||
//
|
||||
// Let V = ( V1 V2 ) (V1: first K columns)
|
||||
// where V1 is unit upper triangular.
|
||||
//
|
||||
if (lsame_(side, "L")) {
|
||||
//
|
||||
// Form H * C or H**T * C where C = ( C1 )
|
||||
// ( C2 )
|
||||
//
|
||||
// W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
|
||||
//
|
||||
// W := C1**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(n, &c__[j + c_dim1], ldc, &work[j * work_dim1 + 1],
|
||||
&c__1);
|
||||
// L130:
|
||||
}
|
||||
//
|
||||
// W := W * V1**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", "Transpose", "Unit", n, k, &c_b14, &
|
||||
v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
if (*m > *k) {
|
||||
//
|
||||
// W := W + C2**T * V2**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "Transpose", n, k, &i__1, &c_b14, &
|
||||
c__[*k + 1 + c_dim1], ldc, &v[(*k + 1) * v_dim1 +
|
||||
1], ldv, &c_b14, &work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T**T or W * T
|
||||
//
|
||||
dtrmm_("Right", "Upper", transt, "Non-unit", n, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - V**T * W**T
|
||||
//
|
||||
if (*m > *k) {
|
||||
//
|
||||
// C2 := C2 - V2**T * W**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "Transpose", &i__1, n, k, &c_b25, &v[(
|
||||
*k + 1) * v_dim1 + 1], ldv, &work[work_offset],
|
||||
ldwork, &c_b14, &c__[*k + 1 + c_dim1], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V1
|
||||
//
|
||||
dtrmm_("Right", "Upper", "No transpose", "Unit", n, k, &c_b14,
|
||||
&v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
//
|
||||
// C1 := C1 - W**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *n;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[j + i__ * c_dim1] -= work[i__ + j * work_dim1];
|
||||
// L140:
|
||||
}
|
||||
// L150:
|
||||
}
|
||||
} else if (lsame_(side, "R")) {
|
||||
//
|
||||
// Form C * H or C * H**T where C = ( C1 C2 )
|
||||
//
|
||||
// W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
|
||||
//
|
||||
// W := C1
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(m, &c__[j * c_dim1 + 1], &c__1, &work[j *
|
||||
work_dim1 + 1], &c__1);
|
||||
// L160:
|
||||
}
|
||||
//
|
||||
// W := W * V1**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", "Transpose", "Unit", m, k, &c_b14, &
|
||||
v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
if (*n > *k) {
|
||||
//
|
||||
// W := W + C2 * V2**T
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "Transpose", m, k, &i__1, &c_b14, &
|
||||
c__[(*k + 1) * c_dim1 + 1], ldc, &v[(*k + 1) *
|
||||
v_dim1 + 1], ldv, &c_b14, &work[work_offset],
|
||||
ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T or W * T**T
|
||||
//
|
||||
dtrmm_("Right", "Upper", trans, "Non-unit", m, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - W * V
|
||||
//
|
||||
if (*n > *k) {
|
||||
//
|
||||
// C2 := C2 - W * V2
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "No transpose", m, &i__1, k, &
|
||||
c_b25, &work[work_offset], ldwork, &v[(*k + 1) *
|
||||
v_dim1 + 1], ldv, &c_b14, &c__[(*k + 1) * c_dim1
|
||||
+ 1], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V1
|
||||
//
|
||||
dtrmm_("Right", "Upper", "No transpose", "Unit", m, k, &c_b14,
|
||||
&v[v_offset], ldv, &work[work_offset], ldwork);
|
||||
//
|
||||
// C1 := C1 - W
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] -= work[i__ + j * work_dim1];
|
||||
// L170:
|
||||
}
|
||||
// L180:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Let V = ( V1 V2 ) (V2: last K columns)
|
||||
// where V2 is unit lower triangular.
|
||||
//
|
||||
if (lsame_(side, "L")) {
|
||||
//
|
||||
// Form H * C or H**T * C where C = ( C1 )
|
||||
// ( C2 )
|
||||
//
|
||||
// W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
|
||||
//
|
||||
// W := C2**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(n, &c__[*m - *k + j + c_dim1], ldc, &work[j *
|
||||
work_dim1 + 1], &c__1);
|
||||
// L190:
|
||||
}
|
||||
//
|
||||
// W := W * V2**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", "Transpose", "Unit", n, k, &c_b14, &
|
||||
v[(*m - *k + 1) * v_dim1 + 1], ldv, &work[work_offset]
|
||||
, ldwork);
|
||||
if (*m > *k) {
|
||||
//
|
||||
// W := W + C1**T * V1**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "Transpose", n, k, &i__1, &c_b14, &
|
||||
c__[c_offset], ldc, &v[v_offset], ldv, &c_b14, &
|
||||
work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T**T or W * T
|
||||
//
|
||||
dtrmm_("Right", "Lower", transt, "Non-unit", n, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - V**T * W**T
|
||||
//
|
||||
if (*m > *k) {
|
||||
//
|
||||
// C1 := C1 - V1**T * W**T
|
||||
//
|
||||
i__1 = *m - *k;
|
||||
dgemm_("Transpose", "Transpose", &i__1, n, k, &c_b25, &v[
|
||||
v_offset], ldv, &work[work_offset], ldwork, &
|
||||
c_b14, &c__[c_offset], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V2
|
||||
//
|
||||
dtrmm_("Right", "Lower", "No transpose", "Unit", n, k, &c_b14,
|
||||
&v[(*m - *k + 1) * v_dim1 + 1], ldv, &work[
|
||||
work_offset], ldwork);
|
||||
//
|
||||
// C2 := C2 - W**T
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *n;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[*m - *k + j + i__ * c_dim1] -= work[i__ + j *
|
||||
work_dim1];
|
||||
// L200:
|
||||
}
|
||||
// L210:
|
||||
}
|
||||
} else if (lsame_(side, "R")) {
|
||||
//
|
||||
// Form C * H or C * H' where C = ( C1 C2 )
|
||||
//
|
||||
// W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
|
||||
//
|
||||
// W := C2
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
dcopy_(m, &c__[(*n - *k + j) * c_dim1 + 1], &c__1, &work[
|
||||
j * work_dim1 + 1], &c__1);
|
||||
// L220:
|
||||
}
|
||||
//
|
||||
// W := W * V2**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", "Transpose", "Unit", m, k, &c_b14, &
|
||||
v[(*n - *k + 1) * v_dim1 + 1], ldv, &work[work_offset]
|
||||
, ldwork);
|
||||
if (*n > *k) {
|
||||
//
|
||||
// W := W + C1 * V1**T
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "Transpose", m, k, &i__1, &c_b14, &
|
||||
c__[c_offset], ldc, &v[v_offset], ldv, &c_b14, &
|
||||
work[work_offset], ldwork);
|
||||
}
|
||||
//
|
||||
// W := W * T or W * T**T
|
||||
//
|
||||
dtrmm_("Right", "Lower", trans, "Non-unit", m, k, &c_b14, &t[
|
||||
t_offset], ldt, &work[work_offset], ldwork);
|
||||
//
|
||||
// C := C - W * V
|
||||
//
|
||||
if (*n > *k) {
|
||||
//
|
||||
// C1 := C1 - W * V1
|
||||
//
|
||||
i__1 = *n - *k;
|
||||
dgemm_("No transpose", "No transpose", m, &i__1, k, &
|
||||
c_b25, &work[work_offset], ldwork, &v[v_offset],
|
||||
ldv, &c_b14, &c__[c_offset], ldc);
|
||||
}
|
||||
//
|
||||
// W := W * V2
|
||||
//
|
||||
dtrmm_("Right", "Lower", "No transpose", "Unit", m, k, &c_b14,
|
||||
&v[(*n - *k + 1) * v_dim1 + 1], ldv, &work[
|
||||
work_offset], ldwork);
|
||||
//
|
||||
// C1 := C1 - W
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + (*n - *k + j) * c_dim1] -= work[i__ + j *
|
||||
work_dim1];
|
||||
// L230:
|
||||
}
|
||||
// L240:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLARFB
|
||||
//
|
||||
} // dlarfb_
|
||||
|
||||
Vendored
+216
@@ -0,0 +1,216 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLARFG generates an elementary reflector (Householder matrix).
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLARFG + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarfg.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarfg.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfg.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLARFG( N, ALPHA, X, INCX, TAU )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX, N
|
||||
// DOUBLE PRECISION ALPHA, TAU
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION X( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLARFG generates a real elementary reflector H of order n, such
|
||||
//> that
|
||||
//>
|
||||
//> H * ( alpha ) = ( beta ), H**T * H = I.
|
||||
//> ( x ) ( 0 )
|
||||
//>
|
||||
//> where alpha and beta are scalars, and x is an (n-1)-element real
|
||||
//> vector. H is represented in the form
|
||||
//>
|
||||
//> H = I - tau * ( 1 ) * ( 1 v**T ) ,
|
||||
//> ( v )
|
||||
//>
|
||||
//> where tau is a real scalar and v is a real (n-1)-element
|
||||
//> vector.
|
||||
//>
|
||||
//> If the elements of x are all zero, then tau = 0 and H is taken to be
|
||||
//> the unit matrix.
|
||||
//>
|
||||
//> Otherwise 1 <= tau <= 2.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The order of the elementary reflector.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION
|
||||
//> On entry, the value alpha.
|
||||
//> On exit, it is overwritten with the value beta.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension
|
||||
//> (1+(N-2)*abs(INCX))
|
||||
//> On entry, the vector x.
|
||||
//> On exit, it is overwritten with the vector v.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> The increment between elements of X. INCX > 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION
|
||||
//> The value tau.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup doubleOTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlarfg_(int *n, double *alpha, double *x, int *incx,
|
||||
double *tau)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
double d__1;
|
||||
|
||||
// Local variables
|
||||
int j, knt;
|
||||
double beta;
|
||||
extern double dnrm2_(int *, double *, int *);
|
||||
extern /* Subroutine */ int dscal_(int *, double *, double *, int *);
|
||||
double xnorm;
|
||||
extern double dlapy2_(double *, double *), dlamch_(char *);
|
||||
double safmin, rsafmn;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.8.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
--x;
|
||||
|
||||
// Function Body
|
||||
if (*n <= 1) {
|
||||
*tau = 0.;
|
||||
return 0;
|
||||
}
|
||||
i__1 = *n - 1;
|
||||
xnorm = dnrm2_(&i__1, &x[1], incx);
|
||||
if (xnorm == 0.) {
|
||||
//
|
||||
// H = I
|
||||
//
|
||||
*tau = 0.;
|
||||
} else {
|
||||
//
|
||||
// general case
|
||||
//
|
||||
d__1 = dlapy2_(alpha, &xnorm);
|
||||
beta = -d_sign(&d__1, alpha);
|
||||
safmin = dlamch_("S") / dlamch_("E");
|
||||
knt = 0;
|
||||
if (abs(beta) < safmin) {
|
||||
//
|
||||
// XNORM, BETA may be inaccurate; scale X and recompute them
|
||||
//
|
||||
rsafmn = 1. / safmin;
|
||||
L10:
|
||||
++knt;
|
||||
i__1 = *n - 1;
|
||||
dscal_(&i__1, &rsafmn, &x[1], incx);
|
||||
beta *= rsafmn;
|
||||
*alpha *= rsafmn;
|
||||
if (abs(beta) < safmin && knt < 20) {
|
||||
goto L10;
|
||||
}
|
||||
//
|
||||
// New BETA is at most 1, at least SAFMIN
|
||||
//
|
||||
i__1 = *n - 1;
|
||||
xnorm = dnrm2_(&i__1, &x[1], incx);
|
||||
d__1 = dlapy2_(alpha, &xnorm);
|
||||
beta = -d_sign(&d__1, alpha);
|
||||
}
|
||||
*tau = (beta - *alpha) / beta;
|
||||
i__1 = *n - 1;
|
||||
d__1 = 1. / (*alpha - beta);
|
||||
dscal_(&i__1, &d__1, &x[1], incx);
|
||||
//
|
||||
// If ALPHA is subnormal, it may lose relative accuracy
|
||||
//
|
||||
i__1 = knt;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
beta *= safmin;
|
||||
// L20:
|
||||
}
|
||||
*alpha = beta;
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLARFG
|
||||
//
|
||||
} // dlarfg_
|
||||
|
||||
Vendored
+389
@@ -0,0 +1,389 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLARFT forms the triangular factor T of a block reflector H = I - vtvH
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLARFT + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarft.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarft.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarft.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLARFT( DIRECT, STOREV, N, K, V, LDV, TAU, T, LDT )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER DIRECT, STOREV
|
||||
// INTEGER K, LDT, LDV, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION T( LDT, * ), TAU( * ), V( LDV, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLARFT forms the triangular factor T of a real block reflector H
|
||||
//> of order n, which is defined as a product of k elementary reflectors.
|
||||
//>
|
||||
//> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
|
||||
//>
|
||||
//> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
|
||||
//>
|
||||
//> If STOREV = 'C', the vector which defines the elementary reflector
|
||||
//> H(i) is stored in the i-th column of the array V, and
|
||||
//>
|
||||
//> H = I - V * T * V**T
|
||||
//>
|
||||
//> If STOREV = 'R', the vector which defines the elementary reflector
|
||||
//> H(i) is stored in the i-th row of the array V, and
|
||||
//>
|
||||
//> H = I - V**T * T * V
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] DIRECT
|
||||
//> \verbatim
|
||||
//> DIRECT is CHARACTER*1
|
||||
//> Specifies the order in which the elementary reflectors are
|
||||
//> multiplied to form the block reflector:
|
||||
//> = 'F': H = H(1) H(2) . . . H(k) (Forward)
|
||||
//> = 'B': H = H(k) . . . H(2) H(1) (Backward)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] STOREV
|
||||
//> \verbatim
|
||||
//> STOREV is CHARACTER*1
|
||||
//> Specifies how the vectors which define the elementary
|
||||
//> reflectors are stored (see also Further Details):
|
||||
//> = 'C': columnwise
|
||||
//> = 'R': rowwise
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The order of the block reflector H. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The order of the triangular factor T (= the number of
|
||||
//> elementary reflectors). K >= 1.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] V
|
||||
//> \verbatim
|
||||
//> V is DOUBLE PRECISION array, dimension
|
||||
//> (LDV,K) if STOREV = 'C'
|
||||
//> (LDV,N) if STOREV = 'R'
|
||||
//> The matrix V. See further details.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDV
|
||||
//> \verbatim
|
||||
//> LDV is INTEGER
|
||||
//> The leading dimension of the array V.
|
||||
//> If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION array, dimension (K)
|
||||
//> TAU(i) must contain the scalar factor of the elementary
|
||||
//> reflector H(i).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] T
|
||||
//> \verbatim
|
||||
//> T is DOUBLE PRECISION array, dimension (LDT,K)
|
||||
//> The k by k triangular factor T of the block reflector.
|
||||
//> If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
|
||||
//> lower triangular. The rest of the array is not used.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDT
|
||||
//> \verbatim
|
||||
//> LDT is INTEGER
|
||||
//> The leading dimension of the array T. LDT >= K.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERauxiliary
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> The shape of the matrix V and the storage of the vectors which define
|
||||
//> the H(i) is best illustrated by the following example with n = 5 and
|
||||
//> k = 3. The elements equal to 1 are not stored.
|
||||
//>
|
||||
//> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
|
||||
//>
|
||||
//> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
|
||||
//> ( v1 1 ) ( 1 v2 v2 v2 )
|
||||
//> ( v1 v2 1 ) ( 1 v3 v3 )
|
||||
//> ( v1 v2 v3 )
|
||||
//> ( v1 v2 v3 )
|
||||
//>
|
||||
//> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
|
||||
//>
|
||||
//> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
|
||||
//> ( v1 v2 v3 ) ( v2 v2 v2 1 )
|
||||
//> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
|
||||
//> ( 1 v3 )
|
||||
//> ( 1 )
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlarft_(char *direct, char *storev, int *n, int *k,
|
||||
double *v, int *ldv, double *tau, double *t, int *ldt)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
double c_b7 = 1.;
|
||||
|
||||
// System generated locals
|
||||
int t_dim1, t_offset, v_dim1, v_offset, i__1, i__2, i__3;
|
||||
double d__1;
|
||||
|
||||
// Local variables
|
||||
int i__, j, prevlastv;
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int dgemv_(char *, int *, int *, double *, double
|
||||
*, int *, double *, int *, double *, double *, int *);
|
||||
int lastv;
|
||||
extern /* Subroutine */ int dtrmv_(char *, char *, char *, int *, double *
|
||||
, int *, double *, int *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
// Parameter adjustments
|
||||
v_dim1 = *ldv;
|
||||
v_offset = 1 + v_dim1;
|
||||
v -= v_offset;
|
||||
--tau;
|
||||
t_dim1 = *ldt;
|
||||
t_offset = 1 + t_dim1;
|
||||
t -= t_offset;
|
||||
|
||||
// Function Body
|
||||
if (*n == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lsame_(direct, "F")) {
|
||||
prevlastv = *n;
|
||||
i__1 = *k;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
prevlastv = max(i__,prevlastv);
|
||||
if (tau[i__] == 0.) {
|
||||
//
|
||||
// H(i) = I
|
||||
//
|
||||
i__2 = i__;
|
||||
for (j = 1; j <= i__2; ++j) {
|
||||
t[j + i__ * t_dim1] = 0.;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// general case
|
||||
//
|
||||
if (lsame_(storev, "C")) {
|
||||
// Skip any trailing zeros.
|
||||
i__2 = i__ + 1;
|
||||
for (lastv = *n; lastv >= i__2; --lastv) {
|
||||
if (v[lastv + i__ * v_dim1] != 0.) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i__2 = i__ - 1;
|
||||
for (j = 1; j <= i__2; ++j) {
|
||||
t[j + i__ * t_dim1] = -tau[i__] * v[i__ + j * v_dim1];
|
||||
}
|
||||
j = min(lastv,prevlastv);
|
||||
//
|
||||
// T(1:i-1,i) := - tau(i) * V(i:j,1:i-1)**T * V(i:j,i)
|
||||
//
|
||||
i__2 = j - i__;
|
||||
i__3 = i__ - 1;
|
||||
d__1 = -tau[i__];
|
||||
dgemv_("Transpose", &i__2, &i__3, &d__1, &v[i__ + 1 +
|
||||
v_dim1], ldv, &v[i__ + 1 + i__ * v_dim1], &c__1, &
|
||||
c_b7, &t[i__ * t_dim1 + 1], &c__1);
|
||||
} else {
|
||||
// Skip any trailing zeros.
|
||||
i__2 = i__ + 1;
|
||||
for (lastv = *n; lastv >= i__2; --lastv) {
|
||||
if (v[i__ + lastv * v_dim1] != 0.) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i__2 = i__ - 1;
|
||||
for (j = 1; j <= i__2; ++j) {
|
||||
t[j + i__ * t_dim1] = -tau[i__] * v[j + i__ * v_dim1];
|
||||
}
|
||||
j = min(lastv,prevlastv);
|
||||
//
|
||||
// T(1:i-1,i) := - tau(i) * V(1:i-1,i:j) * V(i,i:j)**T
|
||||
//
|
||||
i__2 = i__ - 1;
|
||||
i__3 = j - i__;
|
||||
d__1 = -tau[i__];
|
||||
dgemv_("No transpose", &i__2, &i__3, &d__1, &v[(i__ + 1) *
|
||||
v_dim1 + 1], ldv, &v[i__ + (i__ + 1) * v_dim1],
|
||||
ldv, &c_b7, &t[i__ * t_dim1 + 1], &c__1);
|
||||
}
|
||||
//
|
||||
// T(1:i-1,i) := T(1:i-1,1:i-1) * T(1:i-1,i)
|
||||
//
|
||||
i__2 = i__ - 1;
|
||||
dtrmv_("Upper", "No transpose", "Non-unit", &i__2, &t[
|
||||
t_offset], ldt, &t[i__ * t_dim1 + 1], &c__1);
|
||||
t[i__ + i__ * t_dim1] = tau[i__];
|
||||
if (i__ > 1) {
|
||||
prevlastv = max(prevlastv,lastv);
|
||||
} else {
|
||||
prevlastv = lastv;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
prevlastv = 1;
|
||||
for (i__ = *k; i__ >= 1; --i__) {
|
||||
if (tau[i__] == 0.) {
|
||||
//
|
||||
// H(i) = I
|
||||
//
|
||||
i__1 = *k;
|
||||
for (j = i__; j <= i__1; ++j) {
|
||||
t[j + i__ * t_dim1] = 0.;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// general case
|
||||
//
|
||||
if (i__ < *k) {
|
||||
if (lsame_(storev, "C")) {
|
||||
// Skip any leading zeros.
|
||||
i__1 = i__ - 1;
|
||||
for (lastv = 1; lastv <= i__1; ++lastv) {
|
||||
if (v[lastv + i__ * v_dim1] != 0.) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i__1 = *k;
|
||||
for (j = i__ + 1; j <= i__1; ++j) {
|
||||
t[j + i__ * t_dim1] = -tau[i__] * v[*n - *k + i__
|
||||
+ j * v_dim1];
|
||||
}
|
||||
j = max(lastv,prevlastv);
|
||||
//
|
||||
// T(i+1:k,i) = -tau(i) * V(j:n-k+i,i+1:k)**T * V(j:n-k+i,i)
|
||||
//
|
||||
i__1 = *n - *k + i__ - j;
|
||||
i__2 = *k - i__;
|
||||
d__1 = -tau[i__];
|
||||
dgemv_("Transpose", &i__1, &i__2, &d__1, &v[j + (i__
|
||||
+ 1) * v_dim1], ldv, &v[j + i__ * v_dim1], &
|
||||
c__1, &c_b7, &t[i__ + 1 + i__ * t_dim1], &
|
||||
c__1);
|
||||
} else {
|
||||
// Skip any leading zeros.
|
||||
i__1 = i__ - 1;
|
||||
for (lastv = 1; lastv <= i__1; ++lastv) {
|
||||
if (v[i__ + lastv * v_dim1] != 0.) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i__1 = *k;
|
||||
for (j = i__ + 1; j <= i__1; ++j) {
|
||||
t[j + i__ * t_dim1] = -tau[i__] * v[j + (*n - *k
|
||||
+ i__) * v_dim1];
|
||||
}
|
||||
j = max(lastv,prevlastv);
|
||||
//
|
||||
// T(i+1:k,i) = -tau(i) * V(i+1:k,j:n-k+i) * V(i,j:n-k+i)**T
|
||||
//
|
||||
i__1 = *k - i__;
|
||||
i__2 = *n - *k + i__ - j;
|
||||
d__1 = -tau[i__];
|
||||
dgemv_("No transpose", &i__1, &i__2, &d__1, &v[i__ +
|
||||
1 + j * v_dim1], ldv, &v[i__ + j * v_dim1],
|
||||
ldv, &c_b7, &t[i__ + 1 + i__ * t_dim1], &c__1)
|
||||
;
|
||||
}
|
||||
//
|
||||
// T(i+1:k,i) := T(i+1:k,i+1:k) * T(i+1:k,i)
|
||||
//
|
||||
i__1 = *k - i__;
|
||||
dtrmv_("Lower", "No transpose", "Non-unit", &i__1, &t[i__
|
||||
+ 1 + (i__ + 1) * t_dim1], ldt, &t[i__ + 1 + i__ *
|
||||
t_dim1], &c__1);
|
||||
if (i__ > 1) {
|
||||
prevlastv = min(prevlastv,lastv);
|
||||
} else {
|
||||
prevlastv = lastv;
|
||||
}
|
||||
}
|
||||
t[i__ + i__ * t_dim1] = tau[i__];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLARFT
|
||||
//
|
||||
} // dlarft_
|
||||
|
||||
Vendored
+236
@@ -0,0 +1,236 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLARTG generates a plane rotation with real cosine and real sine.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLARTG + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlartg.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlartg.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlartg.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLARTG( F, G, CS, SN, R )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION CS, F, G, R, SN
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLARTG generate a plane rotation so that
|
||||
//>
|
||||
//> [ CS SN ] . [ F ] = [ R ] where CS**2 + SN**2 = 1.
|
||||
//> [ -SN CS ] [ G ] [ 0 ]
|
||||
//>
|
||||
//> This is a slower, more accurate version of the BLAS1 routine DROTG,
|
||||
//> with the following other differences:
|
||||
//> F and G are unchanged on return.
|
||||
//> If G=0, then CS=1 and SN=0.
|
||||
//> If F=0 and (G .ne. 0), then CS=0 and SN=1 without doing any
|
||||
//> floating point operations (saves work in DBDSQR when
|
||||
//> there are zeros on the diagonal).
|
||||
//>
|
||||
//> If F exceeds G in magnitude, CS will be positive.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] F
|
||||
//> \verbatim
|
||||
//> F is DOUBLE PRECISION
|
||||
//> The first component of vector to be rotated.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] G
|
||||
//> \verbatim
|
||||
//> G is DOUBLE PRECISION
|
||||
//> The second component of vector to be rotated.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] CS
|
||||
//> \verbatim
|
||||
//> CS is DOUBLE PRECISION
|
||||
//> The cosine of the rotation.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] SN
|
||||
//> \verbatim
|
||||
//> SN is DOUBLE PRECISION
|
||||
//> The sine of the rotation.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] R
|
||||
//> \verbatim
|
||||
//> R is DOUBLE PRECISION
|
||||
//> The nonzero component of the rotated vector.
|
||||
//>
|
||||
//> This version has a few statements commented out for thread safety
|
||||
//> (machine parameters are computed on each entry). 10 feb 03, SJH.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlartg_(double *f, double *g, double *cs, double *sn,
|
||||
double *r__)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
double d__1, d__2;
|
||||
|
||||
// Local variables
|
||||
int i__;
|
||||
double f1, g1, eps, scale;
|
||||
int count;
|
||||
double safmn2, safmx2;
|
||||
extern double dlamch_(char *);
|
||||
double safmin;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// LOGICAL FIRST
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Save statement ..
|
||||
// SAVE FIRST, SAFMX2, SAFMIN, SAFMN2
|
||||
// ..
|
||||
// .. Data statements ..
|
||||
// DATA FIRST / .TRUE. /
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// IF( FIRST ) THEN
|
||||
safmin = dlamch_("S");
|
||||
eps = dlamch_("E");
|
||||
d__1 = dlamch_("B");
|
||||
i__1 = (int) (log(safmin / eps) / log(dlamch_("B")) / 2.);
|
||||
safmn2 = pow_di(&d__1, &i__1);
|
||||
safmx2 = 1. / safmn2;
|
||||
// FIRST = .FALSE.
|
||||
// END IF
|
||||
if (*g == 0.) {
|
||||
*cs = 1.;
|
||||
*sn = 0.;
|
||||
*r__ = *f;
|
||||
} else if (*f == 0.) {
|
||||
*cs = 0.;
|
||||
*sn = 1.;
|
||||
*r__ = *g;
|
||||
} else {
|
||||
f1 = *f;
|
||||
g1 = *g;
|
||||
// Computing MAX
|
||||
d__1 = abs(f1), d__2 = abs(g1);
|
||||
scale = max(d__1,d__2);
|
||||
if (scale >= safmx2) {
|
||||
count = 0;
|
||||
L10:
|
||||
++count;
|
||||
f1 *= safmn2;
|
||||
g1 *= safmn2;
|
||||
// Computing MAX
|
||||
d__1 = abs(f1), d__2 = abs(g1);
|
||||
scale = max(d__1,d__2);
|
||||
if (scale >= safmx2) {
|
||||
goto L10;
|
||||
}
|
||||
// Computing 2nd power
|
||||
d__1 = f1;
|
||||
// Computing 2nd power
|
||||
d__2 = g1;
|
||||
*r__ = sqrt(d__1 * d__1 + d__2 * d__2);
|
||||
*cs = f1 / *r__;
|
||||
*sn = g1 / *r__;
|
||||
i__1 = count;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
*r__ *= safmx2;
|
||||
// L20:
|
||||
}
|
||||
} else if (scale <= safmn2) {
|
||||
count = 0;
|
||||
L30:
|
||||
++count;
|
||||
f1 *= safmx2;
|
||||
g1 *= safmx2;
|
||||
// Computing MAX
|
||||
d__1 = abs(f1), d__2 = abs(g1);
|
||||
scale = max(d__1,d__2);
|
||||
if (scale <= safmn2) {
|
||||
goto L30;
|
||||
}
|
||||
// Computing 2nd power
|
||||
d__1 = f1;
|
||||
// Computing 2nd power
|
||||
d__2 = g1;
|
||||
*r__ = sqrt(d__1 * d__1 + d__2 * d__2);
|
||||
*cs = f1 / *r__;
|
||||
*sn = g1 / *r__;
|
||||
i__1 = count;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
*r__ *= safmn2;
|
||||
// L40:
|
||||
}
|
||||
} else {
|
||||
// Computing 2nd power
|
||||
d__1 = f1;
|
||||
// Computing 2nd power
|
||||
d__2 = g1;
|
||||
*r__ = sqrt(d__1 * d__1 + d__2 * d__2);
|
||||
*cs = f1 / *r__;
|
||||
*sn = g1 / *r__;
|
||||
}
|
||||
if (abs(*f) > abs(*g) && *cs < 0.) {
|
||||
*cs = -(*cs);
|
||||
*sn = -(*sn);
|
||||
*r__ = -(*r__);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLARTG
|
||||
//
|
||||
} // dlartg_
|
||||
|
||||
Vendored
+413
@@ -0,0 +1,413 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLASCL + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlascl.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlascl.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlascl.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLASCL( TYPE, KL, KU, CFROM, CTO, M, N, A, LDA, INFO )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER TYPE
|
||||
// INTEGER INFO, KL, KU, LDA, M, N
|
||||
// DOUBLE PRECISION CFROM, CTO
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLASCL multiplies the M by N real matrix A by the real scalar
|
||||
//> CTO/CFROM. This is done without over/underflow as long as the final
|
||||
//> result CTO*A(I,J)/CFROM does not over/underflow. TYPE specifies that
|
||||
//> A may be full, upper triangular, lower triangular, upper Hessenberg,
|
||||
//> or banded.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TYPE
|
||||
//> \verbatim
|
||||
//> TYPE is CHARACTER*1
|
||||
//> TYPE indices the storage type of the input matrix.
|
||||
//> = 'G': A is a full matrix.
|
||||
//> = 'L': A is a lower triangular matrix.
|
||||
//> = 'U': A is an upper triangular matrix.
|
||||
//> = 'H': A is an upper Hessenberg matrix.
|
||||
//> = 'B': A is a symmetric band matrix with lower bandwidth KL
|
||||
//> and upper bandwidth KU and with the only the lower
|
||||
//> half stored.
|
||||
//> = 'Q': A is a symmetric band matrix with lower bandwidth KL
|
||||
//> and upper bandwidth KU and with the only the upper
|
||||
//> half stored.
|
||||
//> = 'Z': A is a band matrix with lower bandwidth KL and upper
|
||||
//> bandwidth KU. See DGBTRF for storage details.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] KL
|
||||
//> \verbatim
|
||||
//> KL is INTEGER
|
||||
//> The lower bandwidth of A. Referenced only if TYPE = 'B',
|
||||
//> 'Q' or 'Z'.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] KU
|
||||
//> \verbatim
|
||||
//> KU is INTEGER
|
||||
//> The upper bandwidth of A. Referenced only if TYPE = 'B',
|
||||
//> 'Q' or 'Z'.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] CFROM
|
||||
//> \verbatim
|
||||
//> CFROM is DOUBLE PRECISION
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] CTO
|
||||
//> \verbatim
|
||||
//> CTO is DOUBLE PRECISION
|
||||
//>
|
||||
//> The matrix A is multiplied by CTO/CFROM. A(I,J) is computed
|
||||
//> without over/underflow if the final result CTO*A(I,J)/CFROM
|
||||
//> can be represented without over/underflow. CFROM must be
|
||||
//> nonzero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> The matrix to be multiplied by CTO/CFROM. See TYPE for the
|
||||
//> storage type.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A.
|
||||
//> If TYPE = 'G', 'L', 'U', 'H', LDA >= max(1,M);
|
||||
//> TYPE = 'B', LDA >= KL+1;
|
||||
//> TYPE = 'Q', LDA >= KU+1;
|
||||
//> TYPE = 'Z', LDA >= 2*KL+KU+1.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] INFO
|
||||
//> \verbatim
|
||||
//> INFO is INTEGER
|
||||
//> 0 - successful exit
|
||||
//> <0 - if INFO = -i, the i-th argument had an illegal value.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date June 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlascl_(char *type__, int *kl, int *ku, double *cfrom,
|
||||
double *cto, int *m, int *n, double *a, int *lda, int *info)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5;
|
||||
|
||||
// Local variables
|
||||
int i__, j, k1, k2, k3, k4;
|
||||
double mul, cto1;
|
||||
int done;
|
||||
double ctoc;
|
||||
extern int lsame_(char *, char *);
|
||||
int itype;
|
||||
double cfrom1;
|
||||
extern double dlamch_(char *);
|
||||
double cfromc;
|
||||
extern int disnan_(double *);
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
double bignum, smlnum;
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// June 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Test the input arguments
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
|
||||
// Function Body
|
||||
*info = 0;
|
||||
if (lsame_(type__, "G")) {
|
||||
itype = 0;
|
||||
} else if (lsame_(type__, "L")) {
|
||||
itype = 1;
|
||||
} else if (lsame_(type__, "U")) {
|
||||
itype = 2;
|
||||
} else if (lsame_(type__, "H")) {
|
||||
itype = 3;
|
||||
} else if (lsame_(type__, "B")) {
|
||||
itype = 4;
|
||||
} else if (lsame_(type__, "Q")) {
|
||||
itype = 5;
|
||||
} else if (lsame_(type__, "Z")) {
|
||||
itype = 6;
|
||||
} else {
|
||||
itype = -1;
|
||||
}
|
||||
if (itype == -1) {
|
||||
*info = -1;
|
||||
} else if (*cfrom == 0. || disnan_(cfrom)) {
|
||||
*info = -4;
|
||||
} else if (disnan_(cto)) {
|
||||
*info = -5;
|
||||
} else if (*m < 0) {
|
||||
*info = -6;
|
||||
} else if (*n < 0 || itype == 4 && *n != *m || itype == 5 && *n != *m) {
|
||||
*info = -7;
|
||||
} else if (itype <= 3 && *lda < max(1,*m)) {
|
||||
*info = -9;
|
||||
} else if (itype >= 4) {
|
||||
// Computing MAX
|
||||
i__1 = *m - 1;
|
||||
if (*kl < 0 || *kl > max(i__1,0)) {
|
||||
*info = -2;
|
||||
} else /* if(complicated condition) */ {
|
||||
// Computing MAX
|
||||
i__1 = *n - 1;
|
||||
if (*ku < 0 || *ku > max(i__1,0) || (itype == 4 || itype == 5) &&
|
||||
*kl != *ku) {
|
||||
*info = -3;
|
||||
} else if (itype == 4 && *lda < *kl + 1 || itype == 5 && *lda < *
|
||||
ku + 1 || itype == 6 && *lda < (*kl << 1) + *ku + 1) {
|
||||
*info = -9;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*info != 0) {
|
||||
i__1 = -(*info);
|
||||
xerbla_("DLASCL", &i__1);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
if (*n == 0 || *m == 0) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Get machine parameters
|
||||
//
|
||||
smlnum = dlamch_("S");
|
||||
bignum = 1. / smlnum;
|
||||
cfromc = *cfrom;
|
||||
ctoc = *cto;
|
||||
L10:
|
||||
cfrom1 = cfromc * smlnum;
|
||||
if (cfrom1 == cfromc) {
|
||||
// CFROMC is an inf. Multiply by a correctly signed zero for
|
||||
// finite CTOC, or a NaN if CTOC is infinite.
|
||||
mul = ctoc / cfromc;
|
||||
done = TRUE_;
|
||||
cto1 = ctoc;
|
||||
} else {
|
||||
cto1 = ctoc / bignum;
|
||||
if (cto1 == ctoc) {
|
||||
// CTOC is either 0 or an inf. In both cases, CTOC itself
|
||||
// serves as the correct multiplication factor.
|
||||
mul = ctoc;
|
||||
done = TRUE_;
|
||||
cfromc = 1.;
|
||||
} else if (abs(cfrom1) > abs(ctoc) && ctoc != 0.) {
|
||||
mul = smlnum;
|
||||
done = FALSE_;
|
||||
cfromc = cfrom1;
|
||||
} else if (abs(cto1) > abs(cfromc)) {
|
||||
mul = bignum;
|
||||
done = FALSE_;
|
||||
ctoc = cto1;
|
||||
} else {
|
||||
mul = ctoc / cfromc;
|
||||
done = TRUE_;
|
||||
}
|
||||
}
|
||||
if (itype == 0) {
|
||||
//
|
||||
// Full matrix
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L20:
|
||||
}
|
||||
// L30:
|
||||
}
|
||||
} else if (itype == 1) {
|
||||
//
|
||||
// Lower triangular matrix
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = j; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L40:
|
||||
}
|
||||
// L50:
|
||||
}
|
||||
} else if (itype == 2) {
|
||||
//
|
||||
// Upper triangular matrix
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = min(j,*m);
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L60:
|
||||
}
|
||||
// L70:
|
||||
}
|
||||
} else if (itype == 3) {
|
||||
//
|
||||
// Upper Hessenberg matrix
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
// Computing MIN
|
||||
i__3 = j + 1;
|
||||
i__2 = min(i__3,*m);
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else if (itype == 4) {
|
||||
//
|
||||
// Lower half of a symmetric band matrix
|
||||
//
|
||||
k3 = *kl + 1;
|
||||
k4 = *n + 1;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
// Computing MIN
|
||||
i__3 = k3, i__4 = k4 - j;
|
||||
i__2 = min(i__3,i__4);
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L100:
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
} else if (itype == 5) {
|
||||
//
|
||||
// Upper half of a symmetric band matrix
|
||||
//
|
||||
k1 = *ku + 2;
|
||||
k3 = *ku + 1;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
// Computing MAX
|
||||
i__2 = k1 - j;
|
||||
i__3 = k3;
|
||||
for (i__ = max(i__2,1); i__ <= i__3; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L120:
|
||||
}
|
||||
// L130:
|
||||
}
|
||||
} else if (itype == 6) {
|
||||
//
|
||||
// Band matrix
|
||||
//
|
||||
k1 = *kl + *ku + 2;
|
||||
k2 = *kl + 1;
|
||||
k3 = (*kl << 1) + *ku + 1;
|
||||
k4 = *kl + *ku + 1 + *m;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
// Computing MAX
|
||||
i__3 = k1 - j;
|
||||
// Computing MIN
|
||||
i__4 = k3, i__5 = k4 - j;
|
||||
i__2 = min(i__4,i__5);
|
||||
for (i__ = max(i__3,k2); i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] *= mul;
|
||||
// L140:
|
||||
}
|
||||
// L150:
|
||||
}
|
||||
}
|
||||
if (! done) {
|
||||
goto L10;
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLASCL
|
||||
//
|
||||
} // dlascl_
|
||||
|
||||
Vendored
+209
@@ -0,0 +1,209 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLASET + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlaset.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlaset.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlaset.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLASET( UPLO, M, N, ALPHA, BETA, A, LDA )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER UPLO
|
||||
// INTEGER LDA, M, N
|
||||
// DOUBLE PRECISION ALPHA, BETA
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLASET initializes an m-by-n matrix A to BETA on the diagonal and
|
||||
//> ALPHA on the offdiagonals.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] UPLO
|
||||
//> \verbatim
|
||||
//> UPLO is CHARACTER*1
|
||||
//> Specifies the part of the matrix A to be set.
|
||||
//> = 'U': Upper triangular part is set; the strictly lower
|
||||
//> triangular part of A is not changed.
|
||||
//> = 'L': Lower triangular part is set; the strictly upper
|
||||
//> triangular part of A is not changed.
|
||||
//> Otherwise: All of the matrix A is set.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix A. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix A. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION
|
||||
//> The constant to which the offdiagonal elements are to be set.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is DOUBLE PRECISION
|
||||
//> The constant to which the diagonal elements are to be set.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> On exit, the leading m-by-n submatrix of A is set as follows:
|
||||
//>
|
||||
//> if UPLO = 'U', A(i,j) = ALPHA, 1<=i<=j-1, 1<=j<=n,
|
||||
//> if UPLO = 'L', A(i,j) = ALPHA, j+1<=i<=m, 1<=j<=n,
|
||||
//> otherwise, A(i,j) = ALPHA, 1<=i<=m, 1<=j<=n, i.ne.j,
|
||||
//>
|
||||
//> and, for all UPLO, A(i,i) = BETA, 1<=i<=min(m,n).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlaset_(char *uplo, int *m, int *n, double *alpha,
|
||||
double *beta, double *a, int *lda)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2, i__3;
|
||||
|
||||
// Local variables
|
||||
int i__, j;
|
||||
extern int lsame_(char *, char *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
//=====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
|
||||
// Function Body
|
||||
if (lsame_(uplo, "U")) {
|
||||
//
|
||||
// Set the strictly upper triangular or trapezoidal part of the
|
||||
// array to ALPHA.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 2; j <= i__1; ++j) {
|
||||
// Computing MIN
|
||||
i__3 = j - 1;
|
||||
i__2 = min(i__3,*m);
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] = *alpha;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else if (lsame_(uplo, "L")) {
|
||||
//
|
||||
// Set the strictly lower triangular or trapezoidal part of the
|
||||
// array to ALPHA.
|
||||
//
|
||||
i__1 = min(*m,*n);
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = j + 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] = *alpha;
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Set the leading m-by-n submatrix to ALPHA.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] = *alpha;
|
||||
// L50:
|
||||
}
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
//
|
||||
// Set the first min(M,N) diagonal elements to BETA.
|
||||
//
|
||||
i__1 = min(*m,*n);
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
a[i__ + i__ * a_dim1] = *beta;
|
||||
// L70:
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLASET
|
||||
//
|
||||
} // dlaset_
|
||||
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DLASSQ updates a sum of squares represented in scaled form.
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DLASSQ + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlassq.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlassq.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlassq.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DLASSQ( N, X, INCX, SCALE, SUMSQ )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX, N
|
||||
// DOUBLE PRECISION SCALE, SUMSQ
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION X( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DLASSQ returns the values scl and smsq such that
|
||||
//>
|
||||
//> ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq,
|
||||
//>
|
||||
//> where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is
|
||||
//> assumed to be non-negative and scl returns the value
|
||||
//>
|
||||
//> scl = max( scale, abs( x( i ) ) ).
|
||||
//>
|
||||
//> scale and sumsq must be supplied in SCALE and SUMSQ and
|
||||
//> scl and smsq are overwritten on SCALE and SUMSQ respectively.
|
||||
//>
|
||||
//> The routine makes only one pass through the vector x.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of elements to be used from the vector X.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension (1+(N-1)*INCX)
|
||||
//> The vector for which a scaled sum of squares is computed.
|
||||
//> x( i ) = X( 1 + ( i - 1 )*INCX ), 1 <= i <= n.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> The increment between successive values of the vector X.
|
||||
//> INCX > 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] SCALE
|
||||
//> \verbatim
|
||||
//> SCALE is DOUBLE PRECISION
|
||||
//> On entry, the value scale in the equation above.
|
||||
//> On exit, SCALE is overwritten with scl , the scaling factor
|
||||
//> for the sum of squares.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] SUMSQ
|
||||
//> \verbatim
|
||||
//> SUMSQ is DOUBLE PRECISION
|
||||
//> On entry, the value sumsq in the equation above.
|
||||
//> On exit, SUMSQ is overwritten with smsq , the basic sum of
|
||||
//> squares from which scl has been factored out.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup OTHERauxiliary
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dlassq_(int *n, double *x, int *incx, double *scale,
|
||||
double *sumsq)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1, i__2;
|
||||
double d__1;
|
||||
|
||||
// Local variables
|
||||
int ix;
|
||||
double absxi;
|
||||
extern int disnan_(double *);
|
||||
|
||||
//
|
||||
// -- LAPACK auxiliary routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
//=====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Parameter adjustments
|
||||
--x;
|
||||
|
||||
// Function Body
|
||||
if (*n > 0) {
|
||||
i__1 = (*n - 1) * *incx + 1;
|
||||
i__2 = *incx;
|
||||
for (ix = 1; i__2 < 0 ? ix >= i__1 : ix <= i__1; ix += i__2) {
|
||||
absxi = (d__1 = x[ix], abs(d__1));
|
||||
if (absxi > 0. || disnan_(&absxi)) {
|
||||
if (*scale < absxi) {
|
||||
// Computing 2nd power
|
||||
d__1 = *scale / absxi;
|
||||
*sumsq = *sumsq * (d__1 * d__1) + 1;
|
||||
*scale = absxi;
|
||||
} else {
|
||||
// Computing 2nd power
|
||||
d__1 = absxi / *scale;
|
||||
*sumsq += d__1 * d__1;
|
||||
}
|
||||
}
|
||||
// L10:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DLASSQ
|
||||
//
|
||||
} // dlassq_
|
||||
|
||||
Vendored
+149
@@ -0,0 +1,149 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DNRM2
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// DOUBLE PRECISION FUNCTION DNRM2(N,X,INCX)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION X(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DNRM2 returns the euclidean norm of a vector via the function
|
||||
//> name, so that
|
||||
//>
|
||||
//> DNRM2 := sqrt( x'*x )
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> -- This version written on 25-October-1982.
|
||||
//> Modified on 14-October-1993 to inline the call to DLASSQ.
|
||||
//> Sven Hammarling, Nag Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
double dnrm2_(int *n, double *x, int *incx)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1, i__2;
|
||||
double ret_val, d__1;
|
||||
|
||||
// Local variables
|
||||
int ix;
|
||||
double ssq, norm, scale, absxi;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--x;
|
||||
|
||||
// Function Body
|
||||
if (*n < 1 || *incx < 1) {
|
||||
norm = 0.;
|
||||
} else if (*n == 1) {
|
||||
norm = abs(x[1]);
|
||||
} else {
|
||||
scale = 0.;
|
||||
ssq = 1.;
|
||||
// The following loop is equivalent to this call to the LAPACK
|
||||
// auxiliary routine:
|
||||
// CALL DLASSQ( N, X, INCX, SCALE, SSQ )
|
||||
//
|
||||
i__1 = (*n - 1) * *incx + 1;
|
||||
i__2 = *incx;
|
||||
for (ix = 1; i__2 < 0 ? ix >= i__1 : ix <= i__1; ix += i__2) {
|
||||
if (x[ix] != 0.) {
|
||||
absxi = (d__1 = x[ix], abs(d__1));
|
||||
if (scale < absxi) {
|
||||
// Computing 2nd power
|
||||
d__1 = scale / absxi;
|
||||
ssq = ssq * (d__1 * d__1) + 1.;
|
||||
scale = absxi;
|
||||
} else {
|
||||
// Computing 2nd power
|
||||
d__1 = absxi / scale;
|
||||
ssq += d__1 * d__1;
|
||||
}
|
||||
}
|
||||
// L10:
|
||||
}
|
||||
norm = scale * sqrt(ssq);
|
||||
}
|
||||
ret_val = norm;
|
||||
return ret_val;
|
||||
//
|
||||
// End of DNRM2.
|
||||
//
|
||||
} // dnrm2_
|
||||
|
||||
Vendored
+571
@@ -0,0 +1,571 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DORG2R generates all or part of the orthogonal matrix Q from a QR factorization determined by sgeqrf (unblocked algorithm).
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DORG2R + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dorg2r.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dorg2r.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorg2r.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DORG2R( M, N, K, A, LDA, TAU, WORK, INFO )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INFO, K, LDA, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DORG2R generates an m by n real matrix Q with orthonormal columns,
|
||||
//> which is defined as the first n columns of a product of k elementary
|
||||
//> reflectors of order m
|
||||
//>
|
||||
//> Q = H(1) H(2) . . . H(k)
|
||||
//>
|
||||
//> as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix Q. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix Q. M >= N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The number of elementary reflectors whose product defines the
|
||||
//> matrix Q. N >= K >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> On entry, the i-th column must contain the vector which
|
||||
//> defines the elementary reflector H(i), for i = 1,2,...,k, as
|
||||
//> returned by DGEQRF in the first k columns of its array
|
||||
//> argument A.
|
||||
//> On exit, the m-by-n matrix Q.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The first dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION array, dimension (K)
|
||||
//> TAU(i) must contain the scalar factor of the elementary
|
||||
//> reflector H(i), as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension (N)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] INFO
|
||||
//> \verbatim
|
||||
//> INFO is INTEGER
|
||||
//> = 0: successful exit
|
||||
//> < 0: if INFO = -i, the i-th argument has an illegal value
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERcomputational
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dorg2r_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *info)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2;
|
||||
double d__1;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l;
|
||||
extern /* Subroutine */ int dscal_(int *, double *, double *, int *),
|
||||
dlarf_(char *, int *, int *, double *, int *, double *, double *,
|
||||
int *, double *), xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- LAPACK computational routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Test the input arguments
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--tau;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
*info = 0;
|
||||
if (*m < 0) {
|
||||
*info = -1;
|
||||
} else if (*n < 0 || *n > *m) {
|
||||
*info = -2;
|
||||
} else if (*k < 0 || *k > *n) {
|
||||
*info = -3;
|
||||
} else if (*lda < max(1,*m)) {
|
||||
*info = -5;
|
||||
}
|
||||
if (*info != 0) {
|
||||
i__1 = -(*info);
|
||||
xerbla_("DORG2R", &i__1);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
if (*n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Initialise columns k+1:n to columns of the unit matrix
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = *k + 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
a[l + j * a_dim1] = 0.;
|
||||
// L10:
|
||||
}
|
||||
a[j + j * a_dim1] = 1.;
|
||||
// L20:
|
||||
}
|
||||
for (i__ = *k; i__ >= 1; --i__) {
|
||||
//
|
||||
// Apply H(i) to A(i:m,i:n) from the left
|
||||
//
|
||||
if (i__ < *n) {
|
||||
a[i__ + i__ * a_dim1] = 1.;
|
||||
i__1 = *m - i__ + 1;
|
||||
i__2 = *n - i__;
|
||||
dlarf_("Left", &i__1, &i__2, &a[i__ + i__ * a_dim1], &c__1, &tau[
|
||||
i__], &a[i__ + (i__ + 1) * a_dim1], lda, &work[1]);
|
||||
}
|
||||
if (i__ < *m) {
|
||||
i__1 = *m - i__;
|
||||
d__1 = -tau[i__];
|
||||
dscal_(&i__1, &d__1, &a[i__ + 1 + i__ * a_dim1], &c__1);
|
||||
}
|
||||
a[i__ + i__ * a_dim1] = 1. - tau[i__];
|
||||
//
|
||||
// Set A(1:i-1,i) to zero
|
||||
//
|
||||
i__1 = i__ - 1;
|
||||
for (l = 1; l <= i__1; ++l) {
|
||||
a[l + i__ * a_dim1] = 0.;
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DORG2R
|
||||
//
|
||||
} // dorg2r_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b DORGQR
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DORGQR + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dorgqr.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dorgqr.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorgqr.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DORGQR( M, N, K, A, LDA, TAU, WORK, LWORK, INFO )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INFO, K, LDA, LWORK, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), TAU( * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DORGQR generates an M-by-N real matrix Q with orthonormal columns,
|
||||
//> which is defined as the first N columns of a product of K elementary
|
||||
//> reflectors of order M
|
||||
//>
|
||||
//> Q = H(1) H(2) . . . H(k)
|
||||
//>
|
||||
//> as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix Q. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix Q. M >= N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The number of elementary reflectors whose product defines the
|
||||
//> matrix Q. N >= K >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,N)
|
||||
//> On entry, the i-th column must contain the vector which
|
||||
//> defines the elementary reflector H(i), for i = 1,2,...,k, as
|
||||
//> returned by DGEQRF in the first k columns of its array
|
||||
//> argument A.
|
||||
//> On exit, the M-by-N matrix Q.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The first dimension of the array A. LDA >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION array, dimension (K)
|
||||
//> TAU(i) must contain the scalar factor of the elementary
|
||||
//> reflector H(i), as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
||||
//> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LWORK
|
||||
//> \verbatim
|
||||
//> LWORK is INTEGER
|
||||
//> The dimension of the array WORK. LWORK >= max(1,N).
|
||||
//> For optimum performance LWORK >= N*NB, where NB is the
|
||||
//> optimal blocksize.
|
||||
//>
|
||||
//> If LWORK = -1, then a workspace query is assumed; the routine
|
||||
//> only calculates the optimal size of the WORK array, returns
|
||||
//> this value as the first entry of the WORK array, and no error
|
||||
//> message related to LWORK is issued by XERBLA.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] INFO
|
||||
//> \verbatim
|
||||
//> INFO is INTEGER
|
||||
//> = 0: successful exit
|
||||
//> < 0: if INFO = -i, the i-th argument has an illegal value
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERcomputational
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dorgqr_(int *m, int *n, int *k, double *a, int *lda,
|
||||
double *tau, double *work, int *lwork, int *info)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
int c_n1 = -1;
|
||||
int c__3 = 3;
|
||||
int c__2 = 2;
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2, i__3;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l, ib, nb, ki, kk, nx, iws, nbmin, iinfo;
|
||||
extern /* Subroutine */ int dorg2r_(int *, int *, int *, double *, int *,
|
||||
double *, double *, int *), dlarfb_(char *, char *, char *, char *
|
||||
, int *, int *, int *, double *, int *, double *, int *, double *,
|
||||
int *, double *, int *), dlarft_(char *, char *, int *, int *,
|
||||
double *, int *, double *, double *, int *), xerbla_(char *, int *
|
||||
);
|
||||
extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *);
|
||||
int ldwork, lwkopt;
|
||||
int lquery;
|
||||
|
||||
//
|
||||
// -- LAPACK computational routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Test the input arguments
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--tau;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
*info = 0;
|
||||
nb = ilaenv_(&c__1, "DORGQR", " ", m, n, k, &c_n1);
|
||||
lwkopt = max(1,*n) * nb;
|
||||
work[1] = (double) lwkopt;
|
||||
lquery = *lwork == -1;
|
||||
if (*m < 0) {
|
||||
*info = -1;
|
||||
} else if (*n < 0 || *n > *m) {
|
||||
*info = -2;
|
||||
} else if (*k < 0 || *k > *n) {
|
||||
*info = -3;
|
||||
} else if (*lda < max(1,*m)) {
|
||||
*info = -5;
|
||||
} else if (*lwork < max(1,*n) && ! lquery) {
|
||||
*info = -8;
|
||||
}
|
||||
if (*info != 0) {
|
||||
i__1 = -(*info);
|
||||
xerbla_("DORGQR", &i__1);
|
||||
return 0;
|
||||
} else if (lquery) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
if (*n <= 0) {
|
||||
work[1] = 1.;
|
||||
return 0;
|
||||
}
|
||||
nbmin = 2;
|
||||
nx = 0;
|
||||
iws = *n;
|
||||
if (nb > 1 && nb < *k) {
|
||||
//
|
||||
// Determine when to cross over from blocked to unblocked code.
|
||||
//
|
||||
// Computing MAX
|
||||
i__1 = 0, i__2 = ilaenv_(&c__3, "DORGQR", " ", m, n, k, &c_n1);
|
||||
nx = max(i__1,i__2);
|
||||
if (nx < *k) {
|
||||
//
|
||||
// Determine if workspace is large enough for blocked code.
|
||||
//
|
||||
ldwork = *n;
|
||||
iws = ldwork * nb;
|
||||
if (*lwork < iws) {
|
||||
//
|
||||
// Not enough workspace to use optimal NB: reduce NB and
|
||||
// determine the minimum value of NB.
|
||||
//
|
||||
nb = *lwork / ldwork;
|
||||
// Computing MAX
|
||||
i__1 = 2, i__2 = ilaenv_(&c__2, "DORGQR", " ", m, n, k, &c_n1)
|
||||
;
|
||||
nbmin = max(i__1,i__2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nb >= nbmin && nb < *k && nx < *k) {
|
||||
//
|
||||
// Use blocked code after the last block.
|
||||
// The first kk columns are handled by the block method.
|
||||
//
|
||||
ki = (*k - nx - 1) / nb * nb;
|
||||
// Computing MIN
|
||||
i__1 = *k, i__2 = ki + nb;
|
||||
kk = min(i__1,i__2);
|
||||
//
|
||||
// Set A(1:kk,kk+1:n) to zero.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = kk + 1; j <= i__1; ++j) {
|
||||
i__2 = kk;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
a[i__ + j * a_dim1] = 0.;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
kk = 0;
|
||||
}
|
||||
//
|
||||
// Use unblocked code for the last or only block.
|
||||
//
|
||||
if (kk < *n) {
|
||||
i__1 = *m - kk;
|
||||
i__2 = *n - kk;
|
||||
i__3 = *k - kk;
|
||||
dorg2r_(&i__1, &i__2, &i__3, &a[kk + 1 + (kk + 1) * a_dim1], lda, &
|
||||
tau[kk + 1], &work[1], &iinfo);
|
||||
}
|
||||
if (kk > 0) {
|
||||
//
|
||||
// Use blocked code
|
||||
//
|
||||
i__1 = -nb;
|
||||
for (i__ = ki + 1; i__1 < 0 ? i__ >= 1 : i__ <= 1; i__ += i__1) {
|
||||
// Computing MIN
|
||||
i__2 = nb, i__3 = *k - i__ + 1;
|
||||
ib = min(i__2,i__3);
|
||||
if (i__ + ib <= *n) {
|
||||
//
|
||||
// Form the triangular factor of the block reflector
|
||||
// H = H(i) H(i+1) . . . H(i+ib-1)
|
||||
//
|
||||
i__2 = *m - i__ + 1;
|
||||
dlarft_("Forward", "Columnwise", &i__2, &ib, &a[i__ + i__ *
|
||||
a_dim1], lda, &tau[i__], &work[1], &ldwork);
|
||||
//
|
||||
// Apply H to A(i:m,i+ib:n) from the left
|
||||
//
|
||||
i__2 = *m - i__ + 1;
|
||||
i__3 = *n - i__ - ib + 1;
|
||||
dlarfb_("Left", "No transpose", "Forward", "Columnwise", &
|
||||
i__2, &i__3, &ib, &a[i__ + i__ * a_dim1], lda, &work[
|
||||
1], &ldwork, &a[i__ + (i__ + ib) * a_dim1], lda, &
|
||||
work[ib + 1], &ldwork);
|
||||
}
|
||||
//
|
||||
// Apply H to rows i:m of current block
|
||||
//
|
||||
i__2 = *m - i__ + 1;
|
||||
dorg2r_(&i__2, &ib, &ib, &a[i__ + i__ * a_dim1], lda, &tau[i__], &
|
||||
work[1], &iinfo);
|
||||
//
|
||||
// Set rows 1:i-1 of current block to zero
|
||||
//
|
||||
i__2 = i__ + ib - 1;
|
||||
for (j = i__; j <= i__2; ++j) {
|
||||
i__3 = i__ - 1;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
a[l + j * a_dim1] = 0.;
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
// L50:
|
||||
}
|
||||
}
|
||||
work[1] = (double) iws;
|
||||
return 0;
|
||||
//
|
||||
// End of DORGQR
|
||||
//
|
||||
} // dorgqr_
|
||||
|
||||
Vendored
+684
@@ -0,0 +1,684 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DORM2R multiplies a general matrix by the orthogonal matrix from a QR factorization determined by sgeqrf (unblocked algorithm).
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DORM2R + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dorm2r.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dorm2r.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dorm2r.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DORM2R( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
|
||||
// WORK, INFO )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER SIDE, TRANS
|
||||
// INTEGER INFO, K, LDA, LDC, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DORM2R overwrites the general real m by n matrix C with
|
||||
//>
|
||||
//> Q * C if SIDE = 'L' and TRANS = 'N', or
|
||||
//>
|
||||
//> Q**T* C if SIDE = 'L' and TRANS = 'T', or
|
||||
//>
|
||||
//> C * Q if SIDE = 'R' and TRANS = 'N', or
|
||||
//>
|
||||
//> C * Q**T if SIDE = 'R' and TRANS = 'T',
|
||||
//>
|
||||
//> where Q is a real orthogonal matrix defined as the product of k
|
||||
//> elementary reflectors
|
||||
//>
|
||||
//> Q = H(1) H(2) . . . H(k)
|
||||
//>
|
||||
//> as returned by DGEQRF. Q is of order m if SIDE = 'L' and of order n
|
||||
//> if SIDE = 'R'.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] SIDE
|
||||
//> \verbatim
|
||||
//> SIDE is CHARACTER*1
|
||||
//> = 'L': apply Q or Q**T from the Left
|
||||
//> = 'R': apply Q or Q**T from the Right
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANS
|
||||
//> \verbatim
|
||||
//> TRANS is CHARACTER*1
|
||||
//> = 'N': apply Q (No transpose)
|
||||
//> = 'T': apply Q**T (Transpose)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix C. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix C. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The number of elementary reflectors whose product defines
|
||||
//> the matrix Q.
|
||||
//> If SIDE = 'L', M >= K >= 0;
|
||||
//> if SIDE = 'R', N >= K >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,K)
|
||||
//> The i-th column must contain the vector which defines the
|
||||
//> elementary reflector H(i), for i = 1,2,...,k, as returned by
|
||||
//> DGEQRF in the first k columns of its array argument A.
|
||||
//> A is modified by the routine but restored on exit.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A.
|
||||
//> If SIDE = 'L', LDA >= max(1,M);
|
||||
//> if SIDE = 'R', LDA >= max(1,N).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION array, dimension (K)
|
||||
//> TAU(i) must contain the scalar factor of the elementary
|
||||
//> reflector H(i), as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION array, dimension (LDC,N)
|
||||
//> On entry, the m by n matrix C.
|
||||
//> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> The leading dimension of the array C. LDC >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension
|
||||
//> (N) if SIDE = 'L',
|
||||
//> (M) if SIDE = 'R'
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] INFO
|
||||
//> \verbatim
|
||||
//> INFO is INTEGER
|
||||
//> = 0: successful exit
|
||||
//> < 0: if INFO = -i, the i-th argument had an illegal value
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERcomputational
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dorm2r_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *info)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, c_dim1, c_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, i1, i2, i3, ic, jc, mi, ni, nq;
|
||||
double aii;
|
||||
int left;
|
||||
extern /* Subroutine */ int dlarf_(char *, int *, int *, double *, int *,
|
||||
double *, double *, int *, double *);
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
int notran;
|
||||
|
||||
//
|
||||
// -- LAPACK computational routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Test the input arguments
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--tau;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
*info = 0;
|
||||
left = lsame_(side, "L");
|
||||
notran = lsame_(trans, "N");
|
||||
//
|
||||
// NQ is the order of Q
|
||||
//
|
||||
if (left) {
|
||||
nq = *m;
|
||||
} else {
|
||||
nq = *n;
|
||||
}
|
||||
if (! left && ! lsame_(side, "R")) {
|
||||
*info = -1;
|
||||
} else if (! notran && ! lsame_(trans, "T")) {
|
||||
*info = -2;
|
||||
} else if (*m < 0) {
|
||||
*info = -3;
|
||||
} else if (*n < 0) {
|
||||
*info = -4;
|
||||
} else if (*k < 0 || *k > nq) {
|
||||
*info = -5;
|
||||
} else if (*lda < max(1,nq)) {
|
||||
*info = -7;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
*info = -10;
|
||||
}
|
||||
if (*info != 0) {
|
||||
i__1 = -(*info);
|
||||
xerbla_("DORM2R", &i__1);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
if (*m == 0 || *n == 0 || *k == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (left && ! notran || ! left && notran) {
|
||||
i1 = 1;
|
||||
i2 = *k;
|
||||
i3 = 1;
|
||||
} else {
|
||||
i1 = *k;
|
||||
i2 = 1;
|
||||
i3 = -1;
|
||||
}
|
||||
if (left) {
|
||||
ni = *n;
|
||||
jc = 1;
|
||||
} else {
|
||||
mi = *m;
|
||||
ic = 1;
|
||||
}
|
||||
i__1 = i2;
|
||||
i__2 = i3;
|
||||
for (i__ = i1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
|
||||
if (left) {
|
||||
//
|
||||
// H(i) is applied to C(i:m,1:n)
|
||||
//
|
||||
mi = *m - i__ + 1;
|
||||
ic = i__;
|
||||
} else {
|
||||
//
|
||||
// H(i) is applied to C(1:m,i:n)
|
||||
//
|
||||
ni = *n - i__ + 1;
|
||||
jc = i__;
|
||||
}
|
||||
//
|
||||
// Apply H(i)
|
||||
//
|
||||
aii = a[i__ + i__ * a_dim1];
|
||||
a[i__ + i__ * a_dim1] = 1.;
|
||||
dlarf_(side, &mi, &ni, &a[i__ + i__ * a_dim1], &c__1, &tau[i__], &c__[
|
||||
ic + jc * c_dim1], ldc, &work[1]);
|
||||
a[i__ + i__ * a_dim1] = aii;
|
||||
// L10:
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DORM2R
|
||||
//
|
||||
} // dorm2r_
|
||||
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
//> \brief \b DORMQR
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
//> \htmlonly
|
||||
//> Download DORMQR + dependencies
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dormqr.f">
|
||||
//> [TGZ]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dormqr.f">
|
||||
//> [ZIP]</a>
|
||||
//> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dormqr.f">
|
||||
//> [TXT]</a>
|
||||
//> \endhtmlonly
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DORMQR( SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC,
|
||||
// WORK, LWORK, INFO )
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// CHARACTER SIDE, TRANS
|
||||
// INTEGER INFO, K, LDA, LDC, LWORK, M, N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A( LDA, * ), C( LDC, * ), TAU( * ), WORK( * )
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DORMQR overwrites the general real M-by-N matrix C with
|
||||
//>
|
||||
//> SIDE = 'L' SIDE = 'R'
|
||||
//> TRANS = 'N': Q * C C * Q
|
||||
//> TRANS = 'T': Q**T * C C * Q**T
|
||||
//>
|
||||
//> where Q is a real orthogonal matrix defined as the product of k
|
||||
//> elementary reflectors
|
||||
//>
|
||||
//> Q = H(1) H(2) . . . H(k)
|
||||
//>
|
||||
//> as returned by DGEQRF. Q is of order M if SIDE = 'L' and of order N
|
||||
//> if SIDE = 'R'.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] SIDE
|
||||
//> \verbatim
|
||||
//> SIDE is CHARACTER*1
|
||||
//> = 'L': apply Q or Q**T from the Left;
|
||||
//> = 'R': apply Q or Q**T from the Right.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANS
|
||||
//> \verbatim
|
||||
//> TRANS is CHARACTER*1
|
||||
//> = 'N': No transpose, apply Q;
|
||||
//> = 'T': Transpose, apply Q**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> The number of rows of the matrix C. M >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> The number of columns of the matrix C. N >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> The number of elementary reflectors whose product defines
|
||||
//> the matrix Q.
|
||||
//> If SIDE = 'L', M >= K >= 0;
|
||||
//> if SIDE = 'R', N >= K >= 0.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension (LDA,K)
|
||||
//> The i-th column must contain the vector which defines the
|
||||
//> elementary reflector H(i), for i = 1,2,...,k, as returned by
|
||||
//> DGEQRF in the first k columns of its array argument A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> The leading dimension of the array A.
|
||||
//> If SIDE = 'L', LDA >= max(1,M);
|
||||
//> if SIDE = 'R', LDA >= max(1,N).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TAU
|
||||
//> \verbatim
|
||||
//> TAU is DOUBLE PRECISION array, dimension (K)
|
||||
//> TAU(i) must contain the scalar factor of the elementary
|
||||
//> reflector H(i), as returned by DGEQRF.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION array, dimension (LDC,N)
|
||||
//> On entry, the M-by-N matrix C.
|
||||
//> On exit, C is overwritten by Q*C or Q**T*C or C*Q**T or C*Q.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> The leading dimension of the array C. LDC >= max(1,M).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] WORK
|
||||
//> \verbatim
|
||||
//> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
|
||||
//> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LWORK
|
||||
//> \verbatim
|
||||
//> LWORK is INTEGER
|
||||
//> The dimension of the array WORK.
|
||||
//> If SIDE = 'L', LWORK >= max(1,N);
|
||||
//> if SIDE = 'R', LWORK >= max(1,M).
|
||||
//> For good performance, LWORK should generally be larger.
|
||||
//>
|
||||
//> If LWORK = -1, then a workspace query is assumed; the routine
|
||||
//> only calculates the optimal size of the WORK array, returns
|
||||
//> this value as the first entry of the WORK array, and no error
|
||||
//> message related to LWORK is issued by XERBLA.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[out] INFO
|
||||
//> \verbatim
|
||||
//> INFO is INTEGER
|
||||
//> = 0: successful exit
|
||||
//> < 0: if INFO = -i, the i-th argument had an illegal value
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup doubleOTHERcomputational
|
||||
//
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dormqr_(char *side, char *trans, int *m, int *n, int *k,
|
||||
double *a, int *lda, double *tau, double *c__, int *ldc, double *work,
|
||||
int *lwork, int *info)
|
||||
{
|
||||
// Table of constant values
|
||||
int c__1 = 1;
|
||||
int c_n1 = -1;
|
||||
int c__2 = 2;
|
||||
int c__65 = 65;
|
||||
|
||||
// System generated locals
|
||||
address a__1[2];
|
||||
int a_dim1, a_offset, c_dim1, c_offset, i__1, i__2, i__3[2], i__4, i__5;
|
||||
char ch__1[2+1]={'\0'};
|
||||
|
||||
// Local variables
|
||||
int i__, i1, i2, i3, ib, ic, jc, nb, mi, ni, nq, nw, iwt;
|
||||
int left;
|
||||
extern int lsame_(char *, char *);
|
||||
int nbmin, iinfo;
|
||||
extern /* Subroutine */ int dorm2r_(char *, char *, int *, int *, int *,
|
||||
double *, int *, double *, double *, int *, double *, int *),
|
||||
dlarfb_(char *, char *, char *, char *, int *, int *, int *,
|
||||
double *, int *, double *, int *, double *, int *, double *, int *
|
||||
), dlarft_(char *, char *, int *, int *, double *, int *, double *
|
||||
, double *, int *), xerbla_(char *, int *);
|
||||
extern int ilaenv_(int *, char *, char *, int *, int *, int *, int *);
|
||||
int notran;
|
||||
int ldwork, lwkopt;
|
||||
int lquery;
|
||||
|
||||
//
|
||||
// -- LAPACK computational routine (version 3.7.0) --
|
||||
// -- LAPACK is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Executable Statements ..
|
||||
//
|
||||
// Test the input arguments
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--tau;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
--work;
|
||||
|
||||
// Function Body
|
||||
*info = 0;
|
||||
left = lsame_(side, "L");
|
||||
notran = lsame_(trans, "N");
|
||||
lquery = *lwork == -1;
|
||||
//
|
||||
// NQ is the order of Q and NW is the minimum dimension of WORK
|
||||
//
|
||||
if (left) {
|
||||
nq = *m;
|
||||
nw = *n;
|
||||
} else {
|
||||
nq = *n;
|
||||
nw = *m;
|
||||
}
|
||||
if (! left && ! lsame_(side, "R")) {
|
||||
*info = -1;
|
||||
} else if (! notran && ! lsame_(trans, "T")) {
|
||||
*info = -2;
|
||||
} else if (*m < 0) {
|
||||
*info = -3;
|
||||
} else if (*n < 0) {
|
||||
*info = -4;
|
||||
} else if (*k < 0 || *k > nq) {
|
||||
*info = -5;
|
||||
} else if (*lda < max(1,nq)) {
|
||||
*info = -7;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
*info = -10;
|
||||
} else if (*lwork < max(1,nw) && ! lquery) {
|
||||
*info = -12;
|
||||
}
|
||||
if (*info == 0) {
|
||||
//
|
||||
// Compute the workspace requirements
|
||||
//
|
||||
// Computing MIN
|
||||
// Writing concatenation
|
||||
i__3[0] = 1, a__1[0] = side;
|
||||
i__3[1] = 1, a__1[1] = trans;
|
||||
s_cat(ch__1, a__1, i__3, &c__2);
|
||||
i__1 = 64, i__2 = ilaenv_(&c__1, "DORMQR", ch__1, m, n, k, &c_n1);
|
||||
nb = min(i__1,i__2);
|
||||
lwkopt = max(1,nw) * nb + 4160;
|
||||
work[1] = (double) lwkopt;
|
||||
}
|
||||
if (*info != 0) {
|
||||
i__1 = -(*info);
|
||||
xerbla_("DORMQR", &i__1);
|
||||
return 0;
|
||||
} else if (lquery) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible
|
||||
//
|
||||
if (*m == 0 || *n == 0 || *k == 0) {
|
||||
work[1] = 1.;
|
||||
return 0;
|
||||
}
|
||||
nbmin = 2;
|
||||
ldwork = nw;
|
||||
if (nb > 1 && nb < *k) {
|
||||
if (*lwork < nw * nb + 4160) {
|
||||
nb = (*lwork - 4160) / ldwork;
|
||||
// Computing MAX
|
||||
// Writing concatenation
|
||||
i__3[0] = 1, a__1[0] = side;
|
||||
i__3[1] = 1, a__1[1] = trans;
|
||||
s_cat(ch__1, a__1, i__3, &c__2);
|
||||
i__1 = 2, i__2 = ilaenv_(&c__2, "DORMQR", ch__1, m, n, k, &c_n1);
|
||||
nbmin = max(i__1,i__2);
|
||||
}
|
||||
}
|
||||
if (nb < nbmin || nb >= *k) {
|
||||
//
|
||||
// Use unblocked code
|
||||
//
|
||||
dorm2r_(side, trans, m, n, k, &a[a_offset], lda, &tau[1], &c__[
|
||||
c_offset], ldc, &work[1], &iinfo);
|
||||
} else {
|
||||
//
|
||||
// Use blocked code
|
||||
//
|
||||
iwt = nw * nb + 1;
|
||||
if (left && ! notran || ! left && notran) {
|
||||
i1 = 1;
|
||||
i2 = *k;
|
||||
i3 = nb;
|
||||
} else {
|
||||
i1 = (*k - 1) / nb * nb + 1;
|
||||
i2 = 1;
|
||||
i3 = -nb;
|
||||
}
|
||||
if (left) {
|
||||
ni = *n;
|
||||
jc = 1;
|
||||
} else {
|
||||
mi = *m;
|
||||
ic = 1;
|
||||
}
|
||||
i__1 = i2;
|
||||
i__2 = i3;
|
||||
for (i__ = i1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
|
||||
// Computing MIN
|
||||
i__4 = nb, i__5 = *k - i__ + 1;
|
||||
ib = min(i__4,i__5);
|
||||
//
|
||||
// Form the triangular factor of the block reflector
|
||||
// H = H(i) H(i+1) . . . H(i+ib-1)
|
||||
//
|
||||
i__4 = nq - i__ + 1;
|
||||
dlarft_("Forward", "Columnwise", &i__4, &ib, &a[i__ + i__ *
|
||||
a_dim1], lda, &tau[i__], &work[iwt], &c__65);
|
||||
if (left) {
|
||||
//
|
||||
// H or H**T is applied to C(i:m,1:n)
|
||||
//
|
||||
mi = *m - i__ + 1;
|
||||
ic = i__;
|
||||
} else {
|
||||
//
|
||||
// H or H**T is applied to C(1:m,i:n)
|
||||
//
|
||||
ni = *n - i__ + 1;
|
||||
jc = i__;
|
||||
}
|
||||
//
|
||||
// Apply H or H**T
|
||||
//
|
||||
dlarfb_(side, trans, "Forward", "Columnwise", &mi, &ni, &ib, &a[
|
||||
i__ + i__ * a_dim1], lda, &work[iwt], &c__65, &c__[ic +
|
||||
jc * c_dim1], ldc, &work[1], &ldwork);
|
||||
// L10:
|
||||
}
|
||||
}
|
||||
work[1] = (double) lwkopt;
|
||||
return 0;
|
||||
//
|
||||
// End of DORMQR
|
||||
//
|
||||
} // dormqr_
|
||||
|
||||
Vendored
+164
@@ -0,0 +1,164 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DROT
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DROT(N,DX,INCX,DY,INCY,C,S)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION C,S
|
||||
// INTEGER INCX,INCY,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION DX(*),DY(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DROT applies a plane rotation.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] DX
|
||||
//> \verbatim
|
||||
//> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] DY
|
||||
//> \verbatim
|
||||
//> DY is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> storage spacing between elements of DY
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] C
|
||||
//> \verbatim
|
||||
//> C is DOUBLE PRECISION
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] S
|
||||
//> \verbatim
|
||||
//> S is DOUBLE PRECISION
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> jack dongarra, linpack, 3/11/78.
|
||||
//> modified 12/3/93, array(1) declarations changed to array(*)
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int drot_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy, double *c__, double *s)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
|
||||
// Local variables
|
||||
int i__, ix, iy;
|
||||
double dtemp;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--dy;
|
||||
--dx;
|
||||
|
||||
// Function Body
|
||||
if (*n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (*incx == 1 && *incy == 1) {
|
||||
//
|
||||
// code for both increments equal to 1
|
||||
//
|
||||
i__1 = *n;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp = *c__ * dx[i__] + *s * dy[i__];
|
||||
dy[i__] = *c__ * dy[i__] - *s * dx[i__];
|
||||
dx[i__] = dtemp;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// code for unequal increments or equal increments not equal
|
||||
// to 1
|
||||
//
|
||||
ix = 1;
|
||||
iy = 1;
|
||||
if (*incx < 0) {
|
||||
ix = (-(*n) + 1) * *incx + 1;
|
||||
}
|
||||
if (*incy < 0) {
|
||||
iy = (-(*n) + 1) * *incy + 1;
|
||||
}
|
||||
i__1 = *n;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp = *c__ * dx[ix] + *s * dy[iy];
|
||||
dy[iy] = *c__ * dy[iy] - *s * dx[ix];
|
||||
dx[ix] = dtemp;
|
||||
ix += *incx;
|
||||
iy += *incy;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // drot_
|
||||
|
||||
Vendored
+155
@@ -0,0 +1,155 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DSCAL
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DSCAL(N,DA,DX,INCX)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION DA
|
||||
// INTEGER INCX,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION DX(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DSCAL scales a vector by a constant.
|
||||
//> uses unrolled loops for increment equal to 1.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DA
|
||||
//> \verbatim
|
||||
//> DA is DOUBLE PRECISION
|
||||
//> On entry, DA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] DX
|
||||
//> \verbatim
|
||||
//> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> jack dongarra, linpack, 3/11/78.
|
||||
//> modified 3/93 to return if incx .le. 0.
|
||||
//> modified 12/3/93, array(1) declarations changed to array(*)
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dscal_(int *n, double *da, double *dx, int *incx)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, m, mp1, nincx;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--dx;
|
||||
|
||||
// Function Body
|
||||
if (*n <= 0 || *incx <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (*incx == 1) {
|
||||
//
|
||||
// code for increment equal to 1
|
||||
//
|
||||
//
|
||||
// clean-up loop
|
||||
//
|
||||
m = *n % 5;
|
||||
if (m != 0) {
|
||||
i__1 = m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dx[i__] = *da * dx[i__];
|
||||
}
|
||||
if (*n < 5) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
mp1 = m + 1;
|
||||
i__1 = *n;
|
||||
for (i__ = mp1; i__ <= i__1; i__ += 5) {
|
||||
dx[i__] = *da * dx[i__];
|
||||
dx[i__ + 1] = *da * dx[i__ + 1];
|
||||
dx[i__ + 2] = *da * dx[i__ + 2];
|
||||
dx[i__ + 3] = *da * dx[i__ + 3];
|
||||
dx[i__ + 4] = *da * dx[i__ + 4];
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// code for increment not equal to 1
|
||||
//
|
||||
nincx = *n * *incx;
|
||||
i__1 = nincx;
|
||||
i__2 = *incx;
|
||||
for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
|
||||
dx[i__] = *da * dx[i__];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // dscal_
|
||||
|
||||
Vendored
+178
@@ -0,0 +1,178 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DSWAP
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DSWAP(N,DX,INCX,DY,INCY)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX,INCY,N
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION DX(*),DY(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DSWAP interchanges two vectors.
|
||||
//> uses unrolled loops for increments equal to 1.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> number of elements in input vector(s)
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] DX
|
||||
//> \verbatim
|
||||
//> DX is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCX ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> storage spacing between elements of DX
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] DY
|
||||
//> \verbatim
|
||||
//> DY is DOUBLE PRECISION array, dimension ( 1 + ( N - 1 )*abs( INCY ) )
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCY
|
||||
//> \verbatim
|
||||
//> INCY is INTEGER
|
||||
//> storage spacing between elements of DY
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date November 2017
|
||||
//
|
||||
//> \ingroup double_blas_level1
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> jack dongarra, linpack, 3/11/78.
|
||||
//> modified 12/3/93, array(1) declarations changed to array(*)
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dswap_(int *n, double *dx, int *incx, double *dy, int *
|
||||
incy)
|
||||
{
|
||||
// System generated locals
|
||||
int i__1;
|
||||
|
||||
// Local variables
|
||||
int i__, m, ix, iy, mp1;
|
||||
double dtemp;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level1 routine (version 3.8.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// November 2017
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// Parameter adjustments
|
||||
--dy;
|
||||
--dx;
|
||||
|
||||
// Function Body
|
||||
if (*n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (*incx == 1 && *incy == 1) {
|
||||
//
|
||||
// code for both increments equal to 1
|
||||
//
|
||||
//
|
||||
// clean-up loop
|
||||
//
|
||||
m = *n % 3;
|
||||
if (m != 0) {
|
||||
i__1 = m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp = dx[i__];
|
||||
dx[i__] = dy[i__];
|
||||
dy[i__] = dtemp;
|
||||
}
|
||||
if (*n < 3) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
mp1 = m + 1;
|
||||
i__1 = *n;
|
||||
for (i__ = mp1; i__ <= i__1; i__ += 3) {
|
||||
dtemp = dx[i__];
|
||||
dx[i__] = dy[i__];
|
||||
dy[i__] = dtemp;
|
||||
dtemp = dx[i__ + 1];
|
||||
dx[i__ + 1] = dy[i__ + 1];
|
||||
dy[i__ + 1] = dtemp;
|
||||
dtemp = dx[i__ + 2];
|
||||
dx[i__ + 2] = dy[i__ + 2];
|
||||
dy[i__ + 2] = dtemp;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// code for unequal increments or equal increments not equal
|
||||
// to 1
|
||||
//
|
||||
ix = 1;
|
||||
iy = 1;
|
||||
if (*incx < 0) {
|
||||
ix = (-(*n) + 1) * *incx + 1;
|
||||
}
|
||||
if (*incy < 0) {
|
||||
iy = (-(*n) + 1) * *incy + 1;
|
||||
}
|
||||
i__1 = *n;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
dtemp = dx[ix];
|
||||
dx[ix] = dy[iy];
|
||||
dy[iy] = dtemp;
|
||||
ix += *incx;
|
||||
iy += *incy;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} // dswap_
|
||||
|
||||
Vendored
+509
@@ -0,0 +1,509 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DTRMM
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DTRMM(SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// DOUBLE PRECISION ALPHA
|
||||
// INTEGER LDA,LDB,M,N
|
||||
// CHARACTER DIAG,SIDE,TRANSA,UPLO
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A(LDA,*),B(LDB,*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DTRMM performs one of the matrix-matrix operations
|
||||
//>
|
||||
//> B := alpha*op( A )*B, or B := alpha*B*op( A ),
|
||||
//>
|
||||
//> where alpha is a scalar, B is an m by n matrix, A is a unit, or
|
||||
//> non-unit, upper or lower triangular matrix and op( A ) is one of
|
||||
//>
|
||||
//> op( A ) = A or op( A ) = A**T.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] SIDE
|
||||
//> \verbatim
|
||||
//> SIDE is CHARACTER*1
|
||||
//> On entry, SIDE specifies whether op( A ) multiplies B from
|
||||
//> the left or right as follows:
|
||||
//>
|
||||
//> SIDE = 'L' or 'l' B := alpha*op( A )*B.
|
||||
//>
|
||||
//> SIDE = 'R' or 'r' B := alpha*B*op( A ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] UPLO
|
||||
//> \verbatim
|
||||
//> UPLO is CHARACTER*1
|
||||
//> On entry, UPLO specifies whether the matrix A is an upper or
|
||||
//> lower triangular matrix as follows:
|
||||
//>
|
||||
//> UPLO = 'U' or 'u' A is an upper triangular matrix.
|
||||
//>
|
||||
//> UPLO = 'L' or 'l' A is a lower triangular matrix.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANSA
|
||||
//> \verbatim
|
||||
//> TRANSA is CHARACTER*1
|
||||
//> On entry, TRANSA specifies the form of op( A ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSA = 'N' or 'n' op( A ) = A.
|
||||
//>
|
||||
//> TRANSA = 'T' or 't' op( A ) = A**T.
|
||||
//>
|
||||
//> TRANSA = 'C' or 'c' op( A ) = A**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DIAG
|
||||
//> \verbatim
|
||||
//> DIAG is CHARACTER*1
|
||||
//> On entry, DIAG specifies whether or not A is unit triangular
|
||||
//> as follows:
|
||||
//>
|
||||
//> DIAG = 'U' or 'u' A is assumed to be unit triangular.
|
||||
//>
|
||||
//> DIAG = 'N' or 'n' A is not assumed to be unit
|
||||
//> triangular.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of B. M must be at
|
||||
//> least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of B. N must be
|
||||
//> at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is DOUBLE PRECISION.
|
||||
//> On entry, ALPHA specifies the scalar alpha. When alpha is
|
||||
//> zero then A is not referenced and B need not be set before
|
||||
//> entry.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension ( LDA, k ), where k is m
|
||||
//> when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'.
|
||||
//> Before entry with UPLO = 'U' or 'u', the leading k by k
|
||||
//> upper triangular part of the array A must contain the upper
|
||||
//> triangular matrix and the strictly lower triangular part of
|
||||
//> A is not referenced.
|
||||
//> Before entry with UPLO = 'L' or 'l', the leading k by k
|
||||
//> lower triangular part of the array A must contain the lower
|
||||
//> triangular matrix and the strictly upper triangular part of
|
||||
//> A is not referenced.
|
||||
//> Note that when DIAG = 'U' or 'u', the diagonal elements of
|
||||
//> A are not referenced either, but are assumed to be unity.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. When SIDE = 'L' or 'l' then
|
||||
//> LDA must be at least max( 1, m ), when SIDE = 'R' or 'r'
|
||||
//> then LDA must be at least max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] B
|
||||
//> \verbatim
|
||||
//> B is DOUBLE PRECISION array, dimension ( LDB, N )
|
||||
//> Before entry, the leading m by n part of the array B must
|
||||
//> contain the matrix B, and on exit is overwritten by the
|
||||
//> transformed matrix.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> On entry, LDB specifies the first dimension of B as declared
|
||||
//> in the calling (sub) program. LDB must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup double_blas_level3
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 3 Blas routine.
|
||||
//>
|
||||
//> -- Written on 8-February-1989.
|
||||
//> Jack Dongarra, Argonne National Laboratory.
|
||||
//> Iain Duff, AERE Harwell.
|
||||
//> Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
||||
//> Sven Hammarling, Numerical Algorithms Group Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dtrmm_(char *side, char *uplo, char *transa, char *diag,
|
||||
int *m, int *n, double *alpha, double *a, int *lda, double *b, int *
|
||||
ldb)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3;
|
||||
|
||||
// Local variables
|
||||
int i__, j, k, info;
|
||||
double temp;
|
||||
int lside;
|
||||
extern int lsame_(char *, char *);
|
||||
int nrowa;
|
||||
int upper;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
int nounit;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level3 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
|
||||
// Function Body
|
||||
lside = lsame_(side, "L");
|
||||
if (lside) {
|
||||
nrowa = *m;
|
||||
} else {
|
||||
nrowa = *n;
|
||||
}
|
||||
nounit = lsame_(diag, "N");
|
||||
upper = lsame_(uplo, "U");
|
||||
info = 0;
|
||||
if (! lside && ! lsame_(side, "R")) {
|
||||
info = 1;
|
||||
} else if (! upper && ! lsame_(uplo, "L")) {
|
||||
info = 2;
|
||||
} else if (! lsame_(transa, "N") && ! lsame_(transa, "T") && ! lsame_(
|
||||
transa, "C")) {
|
||||
info = 3;
|
||||
} else if (! lsame_(diag, "U") && ! lsame_(diag, "N")) {
|
||||
info = 4;
|
||||
} else if (*m < 0) {
|
||||
info = 5;
|
||||
} else if (*n < 0) {
|
||||
info = 6;
|
||||
} else if (*lda < max(1,nrowa)) {
|
||||
info = 9;
|
||||
} else if (*ldb < max(1,*m)) {
|
||||
info = 11;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("DTRMM ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// And when alpha.eq.zero.
|
||||
//
|
||||
if (*alpha == 0.) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] = 0.;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations.
|
||||
//
|
||||
if (lside) {
|
||||
if (lsame_(transa, "N")) {
|
||||
//
|
||||
// Form B := alpha*A*B.
|
||||
//
|
||||
if (upper) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (k = 1; k <= i__2; ++k) {
|
||||
if (b[k + j * b_dim1] != 0.) {
|
||||
temp = *alpha * b[k + j * b_dim1];
|
||||
i__3 = k - 1;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * a[i__ + k *
|
||||
a_dim1];
|
||||
// L30:
|
||||
}
|
||||
if (nounit) {
|
||||
temp *= a[k + k * a_dim1];
|
||||
}
|
||||
b[k + j * b_dim1] = temp;
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
// L50:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
for (k = *m; k >= 1; --k) {
|
||||
if (b[k + j * b_dim1] != 0.) {
|
||||
temp = *alpha * b[k + j * b_dim1];
|
||||
b[k + j * b_dim1] = temp;
|
||||
if (nounit) {
|
||||
b[k + j * b_dim1] *= a[k + k * a_dim1];
|
||||
}
|
||||
i__2 = *m;
|
||||
for (i__ = k + 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * a[i__ + k *
|
||||
a_dim1];
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
// L70:
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form B := alpha*A**T*B.
|
||||
//
|
||||
if (upper) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
for (i__ = *m; i__ >= 1; --i__) {
|
||||
temp = b[i__ + j * b_dim1];
|
||||
if (nounit) {
|
||||
temp *= a[i__ + i__ * a_dim1];
|
||||
}
|
||||
i__2 = i__ - 1;
|
||||
for (k = 1; k <= i__2; ++k) {
|
||||
temp += a[k + i__ * a_dim1] * b[k + j * b_dim1];
|
||||
// L90:
|
||||
}
|
||||
b[i__ + j * b_dim1] = *alpha * temp;
|
||||
// L100:
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = b[i__ + j * b_dim1];
|
||||
if (nounit) {
|
||||
temp *= a[i__ + i__ * a_dim1];
|
||||
}
|
||||
i__3 = *m;
|
||||
for (k = i__ + 1; k <= i__3; ++k) {
|
||||
temp += a[k + i__ * a_dim1] * b[k + j * b_dim1];
|
||||
// L120:
|
||||
}
|
||||
b[i__ + j * b_dim1] = *alpha * temp;
|
||||
// L130:
|
||||
}
|
||||
// L140:
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (lsame_(transa, "N")) {
|
||||
//
|
||||
// Form B := alpha*B*A.
|
||||
//
|
||||
if (upper) {
|
||||
for (j = *n; j >= 1; --j) {
|
||||
temp = *alpha;
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
i__1 = *m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1];
|
||||
// L150:
|
||||
}
|
||||
i__1 = j - 1;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
if (a[k + j * a_dim1] != 0.) {
|
||||
temp = *alpha * a[k + j * a_dim1];
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * b[i__ + k *
|
||||
b_dim1];
|
||||
// L160:
|
||||
}
|
||||
}
|
||||
// L170:
|
||||
}
|
||||
// L180:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = *alpha;
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] = temp * b[i__ + j * b_dim1];
|
||||
// L190:
|
||||
}
|
||||
i__2 = *n;
|
||||
for (k = j + 1; k <= i__2; ++k) {
|
||||
if (a[k + j * a_dim1] != 0.) {
|
||||
temp = *alpha * a[k + j * a_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * b[i__ + k *
|
||||
b_dim1];
|
||||
// L200:
|
||||
}
|
||||
}
|
||||
// L210:
|
||||
}
|
||||
// L220:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form B := alpha*B*A**T.
|
||||
//
|
||||
if (upper) {
|
||||
i__1 = *n;
|
||||
for (k = 1; k <= i__1; ++k) {
|
||||
i__2 = k - 1;
|
||||
for (j = 1; j <= i__2; ++j) {
|
||||
if (a[j + k * a_dim1] != 0.) {
|
||||
temp = *alpha * a[j + k * a_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * b[i__ + k *
|
||||
b_dim1];
|
||||
// L230:
|
||||
}
|
||||
}
|
||||
// L240:
|
||||
}
|
||||
temp = *alpha;
|
||||
if (nounit) {
|
||||
temp *= a[k + k * a_dim1];
|
||||
}
|
||||
if (temp != 1.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1];
|
||||
// L250:
|
||||
}
|
||||
}
|
||||
// L260:
|
||||
}
|
||||
} else {
|
||||
for (k = *n; k >= 1; --k) {
|
||||
i__1 = *n;
|
||||
for (j = k + 1; j <= i__1; ++j) {
|
||||
if (a[j + k * a_dim1] != 0.) {
|
||||
temp = *alpha * a[j + k * a_dim1];
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
b[i__ + j * b_dim1] += temp * b[i__ + k *
|
||||
b_dim1];
|
||||
// L270:
|
||||
}
|
||||
}
|
||||
// L280:
|
||||
}
|
||||
temp = *alpha;
|
||||
if (nounit) {
|
||||
temp *= a[k + k * a_dim1];
|
||||
}
|
||||
if (temp != 1.) {
|
||||
i__1 = *m;
|
||||
for (i__ = 1; i__ <= i__1; ++i__) {
|
||||
b[i__ + k * b_dim1] = temp * b[i__ + k * b_dim1];
|
||||
// L290:
|
||||
}
|
||||
}
|
||||
// L300:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DTRMM .
|
||||
//
|
||||
} // dtrmm_
|
||||
|
||||
Vendored
+396
@@ -0,0 +1,396 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b DTRMV
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE DTRMV(UPLO,TRANS,DIAG,N,A,LDA,X,INCX)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// INTEGER INCX,LDA,N
|
||||
// CHARACTER DIAG,TRANS,UPLO
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// DOUBLE PRECISION A(LDA,*),X(*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> DTRMV performs one of the matrix-vector operations
|
||||
//>
|
||||
//> x := A*x, or x := A**T*x,
|
||||
//>
|
||||
//> where x is an n element vector and A is an n by n unit, or non-unit,
|
||||
//> upper or lower triangular matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] UPLO
|
||||
//> \verbatim
|
||||
//> UPLO is CHARACTER*1
|
||||
//> On entry, UPLO specifies whether the matrix is an upper or
|
||||
//> lower triangular matrix as follows:
|
||||
//>
|
||||
//> UPLO = 'U' or 'u' A is an upper triangular matrix.
|
||||
//>
|
||||
//> UPLO = 'L' or 'l' A is a lower triangular matrix.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANS
|
||||
//> \verbatim
|
||||
//> TRANS is CHARACTER*1
|
||||
//> On entry, TRANS specifies the operation to be performed as
|
||||
//> follows:
|
||||
//>
|
||||
//> TRANS = 'N' or 'n' x := A*x.
|
||||
//>
|
||||
//> TRANS = 'T' or 't' x := A**T*x.
|
||||
//>
|
||||
//> TRANS = 'C' or 'c' x := A**T*x.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] DIAG
|
||||
//> \verbatim
|
||||
//> DIAG is CHARACTER*1
|
||||
//> On entry, DIAG specifies whether or not A is unit
|
||||
//> triangular as follows:
|
||||
//>
|
||||
//> DIAG = 'U' or 'u' A is assumed to be unit triangular.
|
||||
//>
|
||||
//> DIAG = 'N' or 'n' A is not assumed to be unit
|
||||
//> triangular.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the order of the matrix A.
|
||||
//> N must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is DOUBLE PRECISION array, dimension ( LDA, N )
|
||||
//> Before entry with UPLO = 'U' or 'u', the leading n by n
|
||||
//> upper triangular part of the array A must contain the upper
|
||||
//> triangular matrix and the strictly lower triangular part of
|
||||
//> A is not referenced.
|
||||
//> Before entry with UPLO = 'L' or 'l', the leading n by n
|
||||
//> lower triangular part of the array A must contain the lower
|
||||
//> triangular matrix and the strictly upper triangular part of
|
||||
//> A is not referenced.
|
||||
//> Note that when DIAG = 'U' or 'u', the diagonal elements of
|
||||
//> A are not referenced either, but are assumed to be unity.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. LDA must be at least
|
||||
//> max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] X
|
||||
//> \verbatim
|
||||
//> X is DOUBLE PRECISION array, dimension at least
|
||||
//> ( 1 + ( n - 1 )*abs( INCX ) ).
|
||||
//> Before entry, the incremented array X must contain the n
|
||||
//> element vector x. On exit, X is overwritten with the
|
||||
//> transformed vector x.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] INCX
|
||||
//> \verbatim
|
||||
//> INCX is INTEGER
|
||||
//> On entry, INCX specifies the increment for the elements of
|
||||
//> X. INCX must not be zero.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup double_blas_level2
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 2 Blas routine.
|
||||
//> The vector and matrix arguments are not referenced when N = 0, or M = 0
|
||||
//>
|
||||
//> -- Written on 22-October-1986.
|
||||
//> Jack Dongarra, Argonne National Lab.
|
||||
//> Jeremy Du Croz, Nag Central Office.
|
||||
//> Sven Hammarling, Nag Central Office.
|
||||
//> Richard Hanson, Sandia National Labs.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int dtrmv_(char *uplo, char *trans, char *diag, int *n,
|
||||
double *a, int *lda, double *x, int *incx)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, i__1, i__2;
|
||||
|
||||
// Local variables
|
||||
int i__, j, ix, jx, kx, info;
|
||||
double temp;
|
||||
extern int lsame_(char *, char *);
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
int nounit;
|
||||
|
||||
//
|
||||
// -- Reference BLAS level2 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
--x;
|
||||
|
||||
// Function Body
|
||||
info = 0;
|
||||
if (! lsame_(uplo, "U") && ! lsame_(uplo, "L")) {
|
||||
info = 1;
|
||||
} else if (! lsame_(trans, "N") && ! lsame_(trans, "T") && ! lsame_(trans,
|
||||
"C")) {
|
||||
info = 2;
|
||||
} else if (! lsame_(diag, "U") && ! lsame_(diag, "N")) {
|
||||
info = 3;
|
||||
} else if (*n < 0) {
|
||||
info = 4;
|
||||
} else if (*lda < max(1,*n)) {
|
||||
info = 6;
|
||||
} else if (*incx == 0) {
|
||||
info = 8;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("DTRMV ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*n == 0) {
|
||||
return 0;
|
||||
}
|
||||
nounit = lsame_(diag, "N");
|
||||
//
|
||||
// Set up the start point in X if the increment is not unity. This
|
||||
// will be ( N - 1 )*INCX too small for descending loops.
|
||||
//
|
||||
if (*incx <= 0) {
|
||||
kx = 1 - (*n - 1) * *incx;
|
||||
} else if (*incx != 1) {
|
||||
kx = 1;
|
||||
}
|
||||
//
|
||||
// Start the operations. In this version the elements of A are
|
||||
// accessed sequentially with one pass through A.
|
||||
//
|
||||
if (lsame_(trans, "N")) {
|
||||
//
|
||||
// Form x := A*x.
|
||||
//
|
||||
if (lsame_(uplo, "U")) {
|
||||
if (*incx == 1) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (x[j] != 0.) {
|
||||
temp = x[j];
|
||||
i__2 = j - 1;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
x[i__] += temp * a[i__ + j * a_dim1];
|
||||
// L10:
|
||||
}
|
||||
if (nounit) {
|
||||
x[j] *= a[j + j * a_dim1];
|
||||
}
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
jx = kx;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (x[jx] != 0.) {
|
||||
temp = x[jx];
|
||||
ix = kx;
|
||||
i__2 = j - 1;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
x[ix] += temp * a[i__ + j * a_dim1];
|
||||
ix += *incx;
|
||||
// L30:
|
||||
}
|
||||
if (nounit) {
|
||||
x[jx] *= a[j + j * a_dim1];
|
||||
}
|
||||
}
|
||||
jx += *incx;
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (*incx == 1) {
|
||||
for (j = *n; j >= 1; --j) {
|
||||
if (x[j] != 0.) {
|
||||
temp = x[j];
|
||||
i__1 = j + 1;
|
||||
for (i__ = *n; i__ >= i__1; --i__) {
|
||||
x[i__] += temp * a[i__ + j * a_dim1];
|
||||
// L50:
|
||||
}
|
||||
if (nounit) {
|
||||
x[j] *= a[j + j * a_dim1];
|
||||
}
|
||||
}
|
||||
// L60:
|
||||
}
|
||||
} else {
|
||||
kx += (*n - 1) * *incx;
|
||||
jx = kx;
|
||||
for (j = *n; j >= 1; --j) {
|
||||
if (x[jx] != 0.) {
|
||||
temp = x[jx];
|
||||
ix = kx;
|
||||
i__1 = j + 1;
|
||||
for (i__ = *n; i__ >= i__1; --i__) {
|
||||
x[ix] += temp * a[i__ + j * a_dim1];
|
||||
ix -= *incx;
|
||||
// L70:
|
||||
}
|
||||
if (nounit) {
|
||||
x[jx] *= a[j + j * a_dim1];
|
||||
}
|
||||
}
|
||||
jx -= *incx;
|
||||
// L80:
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form x := A**T*x.
|
||||
//
|
||||
if (lsame_(uplo, "U")) {
|
||||
if (*incx == 1) {
|
||||
for (j = *n; j >= 1; --j) {
|
||||
temp = x[j];
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
for (i__ = j - 1; i__ >= 1; --i__) {
|
||||
temp += a[i__ + j * a_dim1] * x[i__];
|
||||
// L90:
|
||||
}
|
||||
x[j] = temp;
|
||||
// L100:
|
||||
}
|
||||
} else {
|
||||
jx = kx + (*n - 1) * *incx;
|
||||
for (j = *n; j >= 1; --j) {
|
||||
temp = x[jx];
|
||||
ix = jx;
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
for (i__ = j - 1; i__ >= 1; --i__) {
|
||||
ix -= *incx;
|
||||
temp += a[i__ + j * a_dim1] * x[ix];
|
||||
// L110:
|
||||
}
|
||||
x[jx] = temp;
|
||||
jx -= *incx;
|
||||
// L120:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (*incx == 1) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = x[j];
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
i__2 = *n;
|
||||
for (i__ = j + 1; i__ <= i__2; ++i__) {
|
||||
temp += a[i__ + j * a_dim1] * x[i__];
|
||||
// L130:
|
||||
}
|
||||
x[j] = temp;
|
||||
// L140:
|
||||
}
|
||||
} else {
|
||||
jx = kx;
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
temp = x[jx];
|
||||
ix = jx;
|
||||
if (nounit) {
|
||||
temp *= a[j + j * a_dim1];
|
||||
}
|
||||
i__2 = *n;
|
||||
for (i__ = j + 1; i__ <= i__2; ++i__) {
|
||||
ix += *incx;
|
||||
temp += a[i__ + j * a_dim1] * x[ix];
|
||||
// L150:
|
||||
}
|
||||
x[jx] = temp;
|
||||
jx += *incx;
|
||||
// L160:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of DTRMV .
|
||||
//
|
||||
} // dtrmv_
|
||||
|
||||
Vendored
+1334
File diff suppressed because it is too large
Load Diff
Vendored
+444
@@ -0,0 +1,444 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b SGEMM
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE SGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// REAL ALPHA,BETA
|
||||
// INTEGER K,LDA,LDB,LDC,M,N
|
||||
// CHARACTER TRANSA,TRANSB
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// REAL A(LDA,*),B(LDB,*),C(LDC,*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> SGEMM performs one of the matrix-matrix operations
|
||||
//>
|
||||
//> C := alpha*op( A )*op( B ) + beta*C,
|
||||
//>
|
||||
//> where op( X ) is one of
|
||||
//>
|
||||
//> op( X ) = X or op( X ) = X**T,
|
||||
//>
|
||||
//> alpha and beta are scalars, and A, B and C are matrices, with op( A )
|
||||
//> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TRANSA
|
||||
//> \verbatim
|
||||
//> TRANSA is CHARACTER*1
|
||||
//> On entry, TRANSA specifies the form of op( A ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSA = 'N' or 'n', op( A ) = A.
|
||||
//>
|
||||
//> TRANSA = 'T' or 't', op( A ) = A**T.
|
||||
//>
|
||||
//> TRANSA = 'C' or 'c', op( A ) = A**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANSB
|
||||
//> \verbatim
|
||||
//> TRANSB is CHARACTER*1
|
||||
//> On entry, TRANSB specifies the form of op( B ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSB = 'N' or 'n', op( B ) = B.
|
||||
//>
|
||||
//> TRANSB = 'T' or 't', op( B ) = B**T.
|
||||
//>
|
||||
//> TRANSB = 'C' or 'c', op( B ) = B**T.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix
|
||||
//> op( A ) and of the matrix C. M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix
|
||||
//> op( B ) and the number of columns of the matrix C. N must be
|
||||
//> at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> On entry, K specifies the number of columns of the matrix
|
||||
//> op( A ) and the number of rows of the matrix op( B ). K must
|
||||
//> be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is REAL
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is REAL array, dimension ( LDA, ka ), where ka is
|
||||
//> k when TRANSA = 'N' or 'n', and is m otherwise.
|
||||
//> Before entry with TRANSA = 'N' or 'n', the leading m by k
|
||||
//> part of the array A must contain the matrix A, otherwise
|
||||
//> the leading k by m part of the array A must contain the
|
||||
//> matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. When TRANSA = 'N' or 'n' then
|
||||
//> LDA must be at least max( 1, m ), otherwise LDA must be at
|
||||
//> least max( 1, k ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] B
|
||||
//> \verbatim
|
||||
//> B is REAL array, dimension ( LDB, kb ), where kb is
|
||||
//> n when TRANSB = 'N' or 'n', and is k otherwise.
|
||||
//> Before entry with TRANSB = 'N' or 'n', the leading k by n
|
||||
//> part of the array B must contain the matrix B, otherwise
|
||||
//> the leading n by k part of the array B must contain the
|
||||
//> matrix B.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> On entry, LDB specifies the first dimension of B as declared
|
||||
//> in the calling (sub) program. When TRANSB = 'N' or 'n' then
|
||||
//> LDB must be at least max( 1, k ), otherwise LDB must be at
|
||||
//> least max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is REAL
|
||||
//> On entry, BETA specifies the scalar beta. When BETA is
|
||||
//> supplied as zero then C need not be set on input.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is REAL array, dimension ( LDC, N )
|
||||
//> Before entry, the leading m by n part of the array C must
|
||||
//> contain the matrix C, except when beta is zero, in which
|
||||
//> case C need not be set on entry.
|
||||
//> On exit, the array C is overwritten by the m by n matrix
|
||||
//> ( alpha*op( A )*op( B ) + beta*C ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> On entry, LDC specifies the first dimension of C as declared
|
||||
//> in the calling (sub) program. LDC must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup single_blas_level3
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 3 Blas routine.
|
||||
//>
|
||||
//> -- Written on 8-February-1989.
|
||||
//> Jack Dongarra, Argonne National Laboratory.
|
||||
//> Iain Duff, AERE Harwell.
|
||||
//> Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
||||
//> Sven Hammarling, Numerical Algorithms Group Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int sgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, float *alpha, float *a, int *lda, float *b, int *ldb, float *beta,
|
||||
float *c__, int *ldc)
|
||||
{
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2,
|
||||
i__3;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l, info;
|
||||
int nota, notb;
|
||||
float temp;
|
||||
int ncola;
|
||||
extern int lsame_(char *, char *);
|
||||
int nrowa, nrowb;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level3 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
//
|
||||
// Set NOTA and NOTB as true if A and B respectively are not
|
||||
// transposed and set NROWA, NCOLA and NROWB as the number of rows
|
||||
// and columns of A and the number of rows of B respectively.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
|
||||
// Function Body
|
||||
nota = lsame_(transa, "N");
|
||||
notb = lsame_(transb, "N");
|
||||
if (nota) {
|
||||
nrowa = *m;
|
||||
ncola = *k;
|
||||
} else {
|
||||
nrowa = *k;
|
||||
ncola = *m;
|
||||
}
|
||||
if (notb) {
|
||||
nrowb = *k;
|
||||
} else {
|
||||
nrowb = *n;
|
||||
}
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
info = 0;
|
||||
if (! nota && ! lsame_(transa, "C") && ! lsame_(transa, "T")) {
|
||||
info = 1;
|
||||
} else if (! notb && ! lsame_(transb, "C") && ! lsame_(transb, "T")) {
|
||||
info = 2;
|
||||
} else if (*m < 0) {
|
||||
info = 3;
|
||||
} else if (*n < 0) {
|
||||
info = 4;
|
||||
} else if (*k < 0) {
|
||||
info = 5;
|
||||
} else if (*lda < max(1,nrowa)) {
|
||||
info = 8;
|
||||
} else if (*ldb < max(1,nrowb)) {
|
||||
info = 10;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
info = 13;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("SGEMM ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || (*alpha == 0.f || *k == 0) && *beta == 1.f) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// And if alpha.eq.zero.
|
||||
//
|
||||
if (*alpha == 0.f) {
|
||||
if (*beta == 0.f) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.f;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations.
|
||||
//
|
||||
if (notb) {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (*beta == 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.f;
|
||||
// L50:
|
||||
}
|
||||
} else if (*beta != 1.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
temp = *alpha * b[l + j * b_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
c__[i__ + j * c_dim1] += temp * a[i__ + l * a_dim1];
|
||||
// L70:
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
temp += a[l + i__ * a_dim1] * b[l + j * b_dim1];
|
||||
// L100:
|
||||
}
|
||||
if (*beta == 0.f) {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp;
|
||||
} else {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp + *beta * c__[
|
||||
i__ + j * c_dim1];
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
// L120:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (*beta == 0.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = 0.f;
|
||||
// L130:
|
||||
}
|
||||
} else if (*beta != 1.f) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
c__[i__ + j * c_dim1] = *beta * c__[i__ + j * c_dim1];
|
||||
// L140:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
temp = *alpha * b[j + l * b_dim1];
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
c__[i__ + j * c_dim1] += temp * a[i__ + l * a_dim1];
|
||||
// L150:
|
||||
}
|
||||
// L160:
|
||||
}
|
||||
// L170:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp = 0.f;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
temp += a[l + i__ * a_dim1] * b[j + l * b_dim1];
|
||||
// L180:
|
||||
}
|
||||
if (*beta == 0.f) {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp;
|
||||
} else {
|
||||
c__[i__ + j * c_dim1] = *alpha * temp + *beta * c__[
|
||||
i__ + j * c_dim1];
|
||||
}
|
||||
// L190:
|
||||
}
|
||||
// L200:
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of SGEMM .
|
||||
//
|
||||
} // sgemm_
|
||||
|
||||
Vendored
+752
@@ -0,0 +1,752 @@
|
||||
/* -- translated by f2c (version 20201020 (for_lapack)). -- */
|
||||
|
||||
#include "f2c.h"
|
||||
|
||||
//> \brief \b ZGEMM
|
||||
//
|
||||
// =========== DOCUMENTATION ===========
|
||||
//
|
||||
// Online html documentation available at
|
||||
// http://www.netlib.org/lapack/explore-html/
|
||||
//
|
||||
// Definition:
|
||||
// ===========
|
||||
//
|
||||
// SUBROUTINE ZGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// COMPLEX*16 ALPHA,BETA
|
||||
// INTEGER K,LDA,LDB,LDC,M,N
|
||||
// CHARACTER TRANSA,TRANSB
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// COMPLEX*16 A(LDA,*),B(LDB,*),C(LDC,*)
|
||||
// ..
|
||||
//
|
||||
//
|
||||
//> \par Purpose:
|
||||
// =============
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> ZGEMM performs one of the matrix-matrix operations
|
||||
//>
|
||||
//> C := alpha*op( A )*op( B ) + beta*C,
|
||||
//>
|
||||
//> where op( X ) is one of
|
||||
//>
|
||||
//> op( X ) = X or op( X ) = X**T or op( X ) = X**H,
|
||||
//>
|
||||
//> alpha and beta are scalars, and A, B and C are matrices, with op( A )
|
||||
//> an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
|
||||
//> \endverbatim
|
||||
//
|
||||
// Arguments:
|
||||
// ==========
|
||||
//
|
||||
//> \param[in] TRANSA
|
||||
//> \verbatim
|
||||
//> TRANSA is CHARACTER*1
|
||||
//> On entry, TRANSA specifies the form of op( A ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSA = 'N' or 'n', op( A ) = A.
|
||||
//>
|
||||
//> TRANSA = 'T' or 't', op( A ) = A**T.
|
||||
//>
|
||||
//> TRANSA = 'C' or 'c', op( A ) = A**H.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] TRANSB
|
||||
//> \verbatim
|
||||
//> TRANSB is CHARACTER*1
|
||||
//> On entry, TRANSB specifies the form of op( B ) to be used in
|
||||
//> the matrix multiplication as follows:
|
||||
//>
|
||||
//> TRANSB = 'N' or 'n', op( B ) = B.
|
||||
//>
|
||||
//> TRANSB = 'T' or 't', op( B ) = B**T.
|
||||
//>
|
||||
//> TRANSB = 'C' or 'c', op( B ) = B**H.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] M
|
||||
//> \verbatim
|
||||
//> M is INTEGER
|
||||
//> On entry, M specifies the number of rows of the matrix
|
||||
//> op( A ) and of the matrix C. M must be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] N
|
||||
//> \verbatim
|
||||
//> N is INTEGER
|
||||
//> On entry, N specifies the number of columns of the matrix
|
||||
//> op( B ) and the number of columns of the matrix C. N must be
|
||||
//> at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] K
|
||||
//> \verbatim
|
||||
//> K is INTEGER
|
||||
//> On entry, K specifies the number of columns of the matrix
|
||||
//> op( A ) and the number of rows of the matrix op( B ). K must
|
||||
//> be at least zero.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] ALPHA
|
||||
//> \verbatim
|
||||
//> ALPHA is COMPLEX*16
|
||||
//> On entry, ALPHA specifies the scalar alpha.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] A
|
||||
//> \verbatim
|
||||
//> A is COMPLEX*16 array, dimension ( LDA, ka ), where ka is
|
||||
//> k when TRANSA = 'N' or 'n', and is m otherwise.
|
||||
//> Before entry with TRANSA = 'N' or 'n', the leading m by k
|
||||
//> part of the array A must contain the matrix A, otherwise
|
||||
//> the leading k by m part of the array A must contain the
|
||||
//> matrix A.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDA
|
||||
//> \verbatim
|
||||
//> LDA is INTEGER
|
||||
//> On entry, LDA specifies the first dimension of A as declared
|
||||
//> in the calling (sub) program. When TRANSA = 'N' or 'n' then
|
||||
//> LDA must be at least max( 1, m ), otherwise LDA must be at
|
||||
//> least max( 1, k ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] B
|
||||
//> \verbatim
|
||||
//> B is COMPLEX*16 array, dimension ( LDB, kb ), where kb is
|
||||
//> n when TRANSB = 'N' or 'n', and is k otherwise.
|
||||
//> Before entry with TRANSB = 'N' or 'n', the leading k by n
|
||||
//> part of the array B must contain the matrix B, otherwise
|
||||
//> the leading n by k part of the array B must contain the
|
||||
//> matrix B.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDB
|
||||
//> \verbatim
|
||||
//> LDB is INTEGER
|
||||
//> On entry, LDB specifies the first dimension of B as declared
|
||||
//> in the calling (sub) program. When TRANSB = 'N' or 'n' then
|
||||
//> LDB must be at least max( 1, k ), otherwise LDB must be at
|
||||
//> least max( 1, n ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] BETA
|
||||
//> \verbatim
|
||||
//> BETA is COMPLEX*16
|
||||
//> On entry, BETA specifies the scalar beta. When BETA is
|
||||
//> supplied as zero then C need not be set on input.
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in,out] C
|
||||
//> \verbatim
|
||||
//> C is COMPLEX*16 array, dimension ( LDC, N )
|
||||
//> Before entry, the leading m by n part of the array C must
|
||||
//> contain the matrix C, except when beta is zero, in which
|
||||
//> case C need not be set on entry.
|
||||
//> On exit, the array C is overwritten by the m by n matrix
|
||||
//> ( alpha*op( A )*op( B ) + beta*C ).
|
||||
//> \endverbatim
|
||||
//>
|
||||
//> \param[in] LDC
|
||||
//> \verbatim
|
||||
//> LDC is INTEGER
|
||||
//> On entry, LDC specifies the first dimension of C as declared
|
||||
//> in the calling (sub) program. LDC must be at least
|
||||
//> max( 1, m ).
|
||||
//> \endverbatim
|
||||
//
|
||||
// Authors:
|
||||
// ========
|
||||
//
|
||||
//> \author Univ. of Tennessee
|
||||
//> \author Univ. of California Berkeley
|
||||
//> \author Univ. of Colorado Denver
|
||||
//> \author NAG Ltd.
|
||||
//
|
||||
//> \date December 2016
|
||||
//
|
||||
//> \ingroup complex16_blas_level3
|
||||
//
|
||||
//> \par Further Details:
|
||||
// =====================
|
||||
//>
|
||||
//> \verbatim
|
||||
//>
|
||||
//> Level 3 Blas routine.
|
||||
//>
|
||||
//> -- Written on 8-February-1989.
|
||||
//> Jack Dongarra, Argonne National Laboratory.
|
||||
//> Iain Duff, AERE Harwell.
|
||||
//> Jeremy Du Croz, Numerical Algorithms Group Ltd.
|
||||
//> Sven Hammarling, Numerical Algorithms Group Ltd.
|
||||
//> \endverbatim
|
||||
//>
|
||||
// =====================================================================
|
||||
/* Subroutine */ int zgemm_(char *transa, char *transb, int *m, int *n, int *
|
||||
k, doublecomplex *alpha, doublecomplex *a, int *lda, doublecomplex *b,
|
||||
int *ldb, doublecomplex *beta, doublecomplex *c__, int *ldc)
|
||||
{
|
||||
// Table of constant values
|
||||
doublecomplex c_b1 = {1.,0.};
|
||||
doublecomplex c_b2 = {0.,0.};
|
||||
|
||||
// System generated locals
|
||||
int a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2,
|
||||
i__3, i__4, i__5, i__6;
|
||||
doublecomplex z__1, z__2, z__3, z__4;
|
||||
|
||||
// Local variables
|
||||
int i__, j, l, info;
|
||||
int nota, notb;
|
||||
doublecomplex temp;
|
||||
int conja, conjb;
|
||||
int ncola;
|
||||
extern int lsame_(char *, char *);
|
||||
int nrowa, nrowb;
|
||||
extern /* Subroutine */ int xerbla_(char *, int *);
|
||||
|
||||
//
|
||||
// -- Reference BLAS level3 routine (version 3.7.0) --
|
||||
// -- Reference BLAS is a software package provided by Univ. of Tennessee, --
|
||||
// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
|
||||
// December 2016
|
||||
//
|
||||
// .. Scalar Arguments ..
|
||||
// ..
|
||||
// .. Array Arguments ..
|
||||
// ..
|
||||
//
|
||||
// =====================================================================
|
||||
//
|
||||
// .. External Functions ..
|
||||
// ..
|
||||
// .. External Subroutines ..
|
||||
// ..
|
||||
// .. Intrinsic Functions ..
|
||||
// ..
|
||||
// .. Local Scalars ..
|
||||
// ..
|
||||
// .. Parameters ..
|
||||
// ..
|
||||
//
|
||||
// Set NOTA and NOTB as true if A and B respectively are not
|
||||
// conjugated or transposed, set CONJA and CONJB as true if A and
|
||||
// B respectively are to be transposed but not conjugated and set
|
||||
// NROWA, NCOLA and NROWB as the number of rows and columns of A
|
||||
// and the number of rows of B respectively.
|
||||
//
|
||||
// Parameter adjustments
|
||||
a_dim1 = *lda;
|
||||
a_offset = 1 + a_dim1;
|
||||
a -= a_offset;
|
||||
b_dim1 = *ldb;
|
||||
b_offset = 1 + b_dim1;
|
||||
b -= b_offset;
|
||||
c_dim1 = *ldc;
|
||||
c_offset = 1 + c_dim1;
|
||||
c__ -= c_offset;
|
||||
|
||||
// Function Body
|
||||
nota = lsame_(transa, "N");
|
||||
notb = lsame_(transb, "N");
|
||||
conja = lsame_(transa, "C");
|
||||
conjb = lsame_(transb, "C");
|
||||
if (nota) {
|
||||
nrowa = *m;
|
||||
ncola = *k;
|
||||
} else {
|
||||
nrowa = *k;
|
||||
ncola = *m;
|
||||
}
|
||||
if (notb) {
|
||||
nrowb = *k;
|
||||
} else {
|
||||
nrowb = *n;
|
||||
}
|
||||
//
|
||||
// Test the input parameters.
|
||||
//
|
||||
info = 0;
|
||||
if (! nota && ! conja && ! lsame_(transa, "T")) {
|
||||
info = 1;
|
||||
} else if (! notb && ! conjb && ! lsame_(transb, "T")) {
|
||||
info = 2;
|
||||
} else if (*m < 0) {
|
||||
info = 3;
|
||||
} else if (*n < 0) {
|
||||
info = 4;
|
||||
} else if (*k < 0) {
|
||||
info = 5;
|
||||
} else if (*lda < max(1,nrowa)) {
|
||||
info = 8;
|
||||
} else if (*ldb < max(1,nrowb)) {
|
||||
info = 10;
|
||||
} else if (*ldc < max(1,*m)) {
|
||||
info = 13;
|
||||
}
|
||||
if (info != 0) {
|
||||
xerbla_("ZGEMM ", &info);
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Quick return if possible.
|
||||
//
|
||||
if (*m == 0 || *n == 0 || (alpha->r == 0. && alpha->i == 0. || *k == 0) &&
|
||||
(beta->r == 1. && beta->i == 0.)) {
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// And when alpha.eq.zero.
|
||||
//
|
||||
if (alpha->r == 0. && alpha->i == 0.) {
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0., c__[i__3].i = 0.;
|
||||
// L10:
|
||||
}
|
||||
// L20:
|
||||
}
|
||||
} else {
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4].i,
|
||||
z__1.i = beta->r * c__[i__4].i + beta->i * c__[
|
||||
i__4].r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
// L30:
|
||||
}
|
||||
// L40:
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// Start the operations.
|
||||
//
|
||||
if (notb) {
|
||||
if (nota) {
|
||||
//
|
||||
// Form C := alpha*A*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0., c__[i__3].i = 0.;
|
||||
// L50:
|
||||
}
|
||||
} else if (beta->r != 1. || beta->i != 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
// L60:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
i__3 = l + j * b_dim1;
|
||||
z__1.r = alpha->r * b[i__3].r - alpha->i * b[i__3].i,
|
||||
z__1.i = alpha->r * b[i__3].i + alpha->i * b[i__3]
|
||||
.r;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
z__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
z__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
z__1.r = c__[i__5].r + z__2.r, z__1.i = c__[i__5].i +
|
||||
z__2.i;
|
||||
c__[i__4].r = z__1.r, c__[i__4].i = z__1.i;
|
||||
// L70:
|
||||
}
|
||||
// L80:
|
||||
}
|
||||
// L90:
|
||||
}
|
||||
} else if (conja) {
|
||||
//
|
||||
// Form C := alpha*A**H*B + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
d_cnjg(&z__3, &a[l + i__ * a_dim1]);
|
||||
i__4 = l + j * b_dim1;
|
||||
z__2.r = z__3.r * b[i__4].r - z__3.i * b[i__4].i,
|
||||
z__2.i = z__3.r * b[i__4].i + z__3.i * b[i__4]
|
||||
.r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L100:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L110:
|
||||
}
|
||||
// L120:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
i__5 = l + j * b_dim1;
|
||||
z__2.r = a[i__4].r * b[i__5].r - a[i__4].i * b[i__5]
|
||||
.i, z__2.i = a[i__4].r * b[i__5].i + a[i__4]
|
||||
.i * b[i__5].r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L130:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L140:
|
||||
}
|
||||
// L150:
|
||||
}
|
||||
}
|
||||
} else if (nota) {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A*B**H + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0., c__[i__3].i = 0.;
|
||||
// L160:
|
||||
}
|
||||
} else if (beta->r != 1. || beta->i != 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
// L170:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
d_cnjg(&z__2, &b[j + l * b_dim1]);
|
||||
z__1.r = alpha->r * z__2.r - alpha->i * z__2.i, z__1.i =
|
||||
alpha->r * z__2.i + alpha->i * z__2.r;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
z__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
z__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
z__1.r = c__[i__5].r + z__2.r, z__1.i = c__[i__5].i +
|
||||
z__2.i;
|
||||
c__[i__4].r = z__1.r, c__[i__4].i = z__1.i;
|
||||
// L180:
|
||||
}
|
||||
// L190:
|
||||
}
|
||||
// L200:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
c__[i__3].r = 0., c__[i__3].i = 0.;
|
||||
// L210:
|
||||
}
|
||||
} else if (beta->r != 1. || beta->i != 0.) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__1.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__1.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
// L220:
|
||||
}
|
||||
}
|
||||
i__2 = *k;
|
||||
for (l = 1; l <= i__2; ++l) {
|
||||
i__3 = j + l * b_dim1;
|
||||
z__1.r = alpha->r * b[i__3].r - alpha->i * b[i__3].i,
|
||||
z__1.i = alpha->r * b[i__3].i + alpha->i * b[i__3]
|
||||
.r;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
i__3 = *m;
|
||||
for (i__ = 1; i__ <= i__3; ++i__) {
|
||||
i__4 = i__ + j * c_dim1;
|
||||
i__5 = i__ + j * c_dim1;
|
||||
i__6 = i__ + l * a_dim1;
|
||||
z__2.r = temp.r * a[i__6].r - temp.i * a[i__6].i,
|
||||
z__2.i = temp.r * a[i__6].i + temp.i * a[i__6]
|
||||
.r;
|
||||
z__1.r = c__[i__5].r + z__2.r, z__1.i = c__[i__5].i +
|
||||
z__2.i;
|
||||
c__[i__4].r = z__1.r, c__[i__4].i = z__1.i;
|
||||
// L230:
|
||||
}
|
||||
// L240:
|
||||
}
|
||||
// L250:
|
||||
}
|
||||
}
|
||||
} else if (conja) {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A**H*B**H + beta*C.
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
d_cnjg(&z__3, &a[l + i__ * a_dim1]);
|
||||
d_cnjg(&z__4, &b[j + l * b_dim1]);
|
||||
z__2.r = z__3.r * z__4.r - z__3.i * z__4.i, z__2.i =
|
||||
z__3.r * z__4.i + z__3.i * z__4.r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L260:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L270:
|
||||
}
|
||||
// L280:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**H*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
d_cnjg(&z__3, &a[l + i__ * a_dim1]);
|
||||
i__4 = j + l * b_dim1;
|
||||
z__2.r = z__3.r * b[i__4].r - z__3.i * b[i__4].i,
|
||||
z__2.i = z__3.r * b[i__4].i + z__3.i * b[i__4]
|
||||
.r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L290:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L300:
|
||||
}
|
||||
// L310:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (conjb) {
|
||||
//
|
||||
// Form C := alpha*A**T*B**H + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
d_cnjg(&z__3, &b[j + l * b_dim1]);
|
||||
z__2.r = a[i__4].r * z__3.r - a[i__4].i * z__3.i,
|
||||
z__2.i = a[i__4].r * z__3.i + a[i__4].i *
|
||||
z__3.r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L320:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L330:
|
||||
}
|
||||
// L340:
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Form C := alpha*A**T*B**T + beta*C
|
||||
//
|
||||
i__1 = *n;
|
||||
for (j = 1; j <= i__1; ++j) {
|
||||
i__2 = *m;
|
||||
for (i__ = 1; i__ <= i__2; ++i__) {
|
||||
temp.r = 0., temp.i = 0.;
|
||||
i__3 = *k;
|
||||
for (l = 1; l <= i__3; ++l) {
|
||||
i__4 = l + i__ * a_dim1;
|
||||
i__5 = j + l * b_dim1;
|
||||
z__2.r = a[i__4].r * b[i__5].r - a[i__4].i * b[i__5]
|
||||
.i, z__2.i = a[i__4].r * b[i__5].i + a[i__4]
|
||||
.i * b[i__5].r;
|
||||
z__1.r = temp.r + z__2.r, z__1.i = temp.i + z__2.i;
|
||||
temp.r = z__1.r, temp.i = z__1.i;
|
||||
// L350:
|
||||
}
|
||||
if (beta->r == 0. && beta->i == 0.) {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__1.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__1.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
} else {
|
||||
i__3 = i__ + j * c_dim1;
|
||||
z__2.r = alpha->r * temp.r - alpha->i * temp.i,
|
||||
z__2.i = alpha->r * temp.i + alpha->i *
|
||||
temp.r;
|
||||
i__4 = i__ + j * c_dim1;
|
||||
z__3.r = beta->r * c__[i__4].r - beta->i * c__[i__4]
|
||||
.i, z__3.i = beta->r * c__[i__4].i + beta->i *
|
||||
c__[i__4].r;
|
||||
z__1.r = z__2.r + z__3.r, z__1.i = z__2.i + z__3.i;
|
||||
c__[i__3].r = z__1.r, c__[i__3].i = z__1.i;
|
||||
}
|
||||
// L360:
|
||||
}
|
||||
// L370:
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
//
|
||||
// End of ZGEMM .
|
||||
//
|
||||
} // zgemm_
|
||||
|
||||
Vendored
+5
-5
@@ -1,8 +1,8 @@
|
||||
# Binaries branch name: ffmpeg/4.x_20260715
|
||||
# Binaries were created for OpenCV: 6b640b424c516d27217700392a7ed6a362e040a5
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "bd9418020a5c342be979c56d6e6434261959d3af")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "31968b434799d3dd56969b15aac3efa8")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "84757ed0f16ddedce99227529d3165e9")
|
||||
# Binaries branch name: ffmpeg/5.x_20260602
|
||||
# Binaries were created for OpenCV: a0a660fcb1e58a295e6caa6aee64ed4d369b0181
|
||||
ocv_update(FFMPEG_BINARIES_COMMIT "06dc20cad65dc7fcf784f70c95d46750520889a7")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN32 "9cef7a78b6f7ec8cf1a3935c058cfac5")
|
||||
ocv_update(FFMPEG_FILE_HASH_BIN64 "a821a1135251859655090c795af05789")
|
||||
ocv_update(FFMPEG_FILE_HASH_CMAKE "e09efc33312d1173be8a9446f3b088fe")
|
||||
|
||||
function(download_win_ffmpeg script_var)
|
||||
|
||||
Vendored
+70
@@ -0,0 +1,70 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
# CMake file for the bundled HarfBuzz text-shaping library. See root CMakeLists.txt
|
||||
#
|
||||
# OpenCV vendors a minimal subset of HarfBuzz (core + HB_HAS_RASTER) as a
|
||||
# normal static library: each .cc is a separate translation unit. The subset
|
||||
# is produced by hb_extract.py (see that script to update HarfBuzz).
|
||||
# ----------------------------------------------------------------------------
|
||||
project(${HARFBUZZ_LIBRARY} CXX)
|
||||
|
||||
ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
|
||||
# Every .cc copied by hb_extract.py is a real translation unit (the script
|
||||
# never copies non-TU .cc files), so a plain recursive glob is exactly right.
|
||||
file(GLOB_RECURSE lib_srcs src/*.cc)
|
||||
file(GLOB_RECURSE lib_hdrs src/*.h src/*.hh)
|
||||
|
||||
# HarfBuzz is built with HB_TINY for minimum footprint. Because we request the
|
||||
# software rasterizer (HB_HAS_RASTER, defined below), HB_TINY does NOT disable
|
||||
# the draw/paint/color APIs nor CFF (PostScript/.otf
|
||||
# outlines) -- see hb-config.hh: HB_NO_DRAW/COLOR/PAINT and the TINY->HB_NO_CFF
|
||||
# rule only trigger when no HB_HAS_* backend is requested. So CFF (CJK/Indic),
|
||||
# COLR/CPAL color and our rasterizer all survive HB_TINY.
|
||||
#
|
||||
# Two features HB_TINY (via HB_LEAN) would otherwise drop are restored through
|
||||
# HarfBuzz's config-override hook (hb-opencv-config.hh): thread-safety (HB_NO_MT)
|
||||
# and variable fonts (HB_NO_VAR). No platform backends (CoreText/DirectWrite/...).
|
||||
|
||||
add_library(${HARFBUZZ_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs} ${lib_hdrs})
|
||||
|
||||
target_compile_definitions(${HARFBUZZ_LIBRARY} PRIVATE
|
||||
HB_TINY
|
||||
HB_HAS_RASTER # request the software rasterizer: keeps draw/paint/color + CFF under HB_TINY
|
||||
"HB_CONFIG_OVERRIDE_H=\"hb-opencv-config.hh\"")
|
||||
|
||||
set_target_properties(${HARFBUZZ_LIBRARY} PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS
|
||||
-Wunused-variable -Wunused-function -Wunused-parameter
|
||||
-Wunused-but-set-variable # clang15/gcc
|
||||
-Wshadow
|
||||
-Wmissing-declarations # gcc
|
||||
-Wmissing-prototypes # clang
|
||||
-Wimplicit-fallthrough
|
||||
-Wextra-semi # clang
|
||||
-Wdeprecated-copy # gcc/clang
|
||||
-Wsuggest-override
|
||||
-Wcast-function-type
|
||||
-Wclass-memaccess # gcc
|
||||
-Wexpansion-to-defined
|
||||
)
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244 /wd4267 /wd4127 /wd4146 /wd4456 /wd4459) # MSVC
|
||||
|
||||
set_target_properties(${HARFBUZZ_LIBRARY}
|
||||
PROPERTIES OUTPUT_NAME ${HARFBUZZ_LIBRARY}
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
COMPILE_PDB_NAME ${HARFBUZZ_LIBRARY}
|
||||
COMPILE_PDB_NAME_DEBUG "${HARFBUZZ_LIBRARY}${OPENCV_DEBUG_POSTFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH}
|
||||
)
|
||||
|
||||
if(ENABLE_SOLUTION_FOLDERS)
|
||||
set_target_properties(${HARFBUZZ_LIBRARY} PROPERTIES FOLDER "3rdparty")
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
ocv_install_target(${HARFBUZZ_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev OPTIONAL)
|
||||
endif()
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
||||
For parts of HarfBuzz that are licensed under different licenses see individual
|
||||
files names COPYING in subdirectories where applicable.
|
||||
|
||||
Copyright © 2010-2022 Google, Inc.
|
||||
Copyright © 2015-2020 Ebrahim Byagowi
|
||||
Copyright © 2019,2020 Facebook, Inc.
|
||||
Copyright © 2012,2015 Mozilla Foundation
|
||||
Copyright © 2011 Codethink Limited
|
||||
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
||||
Copyright © 2009 Keith Stribley
|
||||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
|
||||
For full copyright notices consult the individual files in the package.
|
||||
|
||||
|
||||
Permission is hereby granted, without written agreement and without
|
||||
license or royalty fees, to use, copy, modify, and distribute this
|
||||
software and its documentation for any purpose, provided that the
|
||||
above copyright notice and the following two paragraphs appear in
|
||||
all copies of this software.
|
||||
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
Vendored
+220
@@ -0,0 +1,220 @@
|
||||
# HarfBuzz
|
||||
|
||||
<div align="center">
|
||||
|
||||
<p><img src="HarfBuzz.png" alt="HarfBuzz Logo" width="256"/></p>
|
||||
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/linux.yml)
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/macos.yml)
|
||||
[](https://github.com/harfbuzz/harfbuzz/actions/workflows/msvc.yml)
|
||||
[](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#harfbuzz)
|
||||
[](https://scan.coverity.com/projects/harfbuzz)
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/harfbuzz/harfbuzz)
|
||||
|
||||
</div>
|
||||
|
||||
HarfBuzz started as a text shaping engine but has grown into a
|
||||
full font platform — the `ffmpeg` of text shaping. It primarily
|
||||
supports [OpenType][1], but also [Apple Advanced Typography][2].
|
||||
|
||||
HarfBuzz shapes the majority of text on modern screens.
|
||||
|
||||
HarfBuzz is optimized for robustness, correctness, and performance
|
||||
— in that order. Achieve all.
|
||||
|
||||
**[Try it live at harfbuzz-world.cc](https://harfbuzz-world.cc/)** — an interactive playground for shaping, subsetting, rasterization, vector output, and GPU rendering, all running in your browser.
|
||||
|
||||
Here is a quick map of its components:
|
||||
|
||||
### Core libraries
|
||||
|
||||
| Library | Description |
|
||||
|---------|-------------|
|
||||
| **libharfbuzz** | Text shaping, draw API, paint API. Highly configurable (see [CONFIG.md](CONFIG.md)). Optional integration backends compiled in: hb-ft (FreeType), hb-coretext (macOS), hb-uniscribe (Windows), hb-directwrite (Windows), hb-gdi (Windows), hb-glib, hb-graphite2. |
|
||||
| **libharfbuzz-subset** | Font subsetting and variable-font instancing. |
|
||||
|
||||
### Auxiliary libraries
|
||||
|
||||
| Library | Description |
|
||||
|---------|-------------|
|
||||
| **libharfbuzz-icu** | ICU Unicode integration. |
|
||||
| **libharfbuzz-cairo** | Cairo rendering integration. |
|
||||
| **libharfbuzz-gobject** | GObject/GI bindings. |
|
||||
|
||||
### Experimental libraries
|
||||
|
||||
| Library | Description |
|
||||
|---------|-------------|
|
||||
| **libharfbuzz-raster** | Glyph rasterization to bitmaps, including color fonts. Uses hb-draw and hb-paint. |
|
||||
| **libharfbuzz-vector** | Glyph output to vector formats (currently SVG), including color fonts. Uses hb-draw and hb-paint. |
|
||||
| **libharfbuzz-gpu** | Encodes glyph outlines for GPU rasterization (Slug algorithm). Provides shader sources in GLSL, WGSL, MSL, and HLSL. [Live demo.](https://harfbuzz.github.io/hb-gpu-demo/) |
|
||||
|
||||
Notable missing feature: font hinting (including autohinting)
|
||||
is not implemented. For hinted rasterization, use FreeType or
|
||||
Skrifa.
|
||||
|
||||
For simplified builds, amalgamated sources are available:
|
||||
`harfbuzz.cc` (just libharfbuzz), `harfbuzz-subset.cc` (just
|
||||
libharfbuzz-subset), or `harfbuzz-world.cc` (everything, driven
|
||||
by a custom `hb-features.h`). For a live in-browser playground
|
||||
plus a worked example of the world.cc single-file build, see
|
||||
[harfbuzz-world.cc][26].
|
||||
|
||||
### Command-line tools
|
||||
|
||||
| Tool | Description |
|
||||
|------|-------------|
|
||||
| **hb-shape** | Shape text and display glyph output. |
|
||||
| **hb-view** | Render shaped text to an image. |
|
||||
| **hb-subset** | Subset and optimize fonts. |
|
||||
| **hb-info** | Display font metadata. |
|
||||
| **hb-raster** | Render glyphs to bitmap images. |
|
||||
| **hb-vector** | Render glyphs to vector formats (SVG). |
|
||||
| **hb-gpu** | Interactive GPU text rendering. |
|
||||
|
||||
The canonical source tree and bug trackers are available on [github][4].
|
||||
Both development and user support discussion around HarfBuzz happen on
|
||||
[github][4] as well.
|
||||
|
||||
For license information, see [COPYING](COPYING).
|
||||
|
||||
## API stability
|
||||
|
||||
The API that comes with `hb.h` will not change incompatibly. Other, peripheral,
|
||||
headers are more likely to go through minor modifications, but again, we do our
|
||||
best to never change API in an incompatible way. We will never break the ABI.
|
||||
|
||||
The API and ABI are stable even across major version number jumps. In fact,
|
||||
current HarfBuzz is API/ABI compatible all the way back to the 0.9.x series.
|
||||
If one day we need to break the API/ABI, that would be called a new library.
|
||||
|
||||
As such, we bump the major version number only when we add major new features,
|
||||
the minor version when there is new API, and the micro version when there
|
||||
are bug fixes.
|
||||
|
||||
## Documentation
|
||||
|
||||
For user manual as well as API documentation, check: https://harfbuzz.github.io
|
||||
|
||||
## Download
|
||||
|
||||
Tarball releases and Win32/Win64 binary bundles are available on the
|
||||
[github releases][3] page.
|
||||
|
||||
## Development
|
||||
|
||||
For build information, see [BUILD.md](BUILD.md).
|
||||
|
||||
For custom configurations, see [CONFIG.md](CONFIG.md).
|
||||
|
||||
For testing and profiling, see [TESTING.md](TESTING.md).
|
||||
|
||||
For using with Python, see [README.python.md](README.python.md). There is also [uharfbuzz](https://github.com/harfbuzz/uharfbuzz).
|
||||
|
||||
For cross-compiling to Windows from Linux or macOS, see [README.mingw.md](README.mingw.md).
|
||||
|
||||
To report bugs or submit patches please use [github][4] issues and pull-requests.
|
||||
|
||||
### Developer documents
|
||||
|
||||
To get a better idea of where HarfBuzz stands in the text rendering stack you
|
||||
may want to read [State of Text Rendering 2024][6].
|
||||
Here are a few presentation slides about HarfBuzz over the years:
|
||||
|
||||
- 2026 – [HarfBuzz at 20!][25]
|
||||
- 2016 – [Ten Years of HarfBuzz][20]
|
||||
- 2014 – [Unicode, OpenType, and HarfBuzz: Closing the Circle][7]
|
||||
- 2012 – [HarfBuzz, The Free and Open Text Shaping Engine][8]
|
||||
- 2009 – [HarfBuzz: the Free and Open Shaping Engine][9]
|
||||
|
||||
More presentations and papers are available on [behdad][11]'s website.
|
||||
In particular, the following _studies_ are relevant to HarfBuzz development:
|
||||
|
||||
- 2025 – [AAT layout caches][24]
|
||||
- 2025 – [OpenType Layout lookup caches][23]
|
||||
- 2025 – [Introducing HarfRust][22]
|
||||
- 2025 – [Subsetting][21]
|
||||
- 2025 – [Caching][12]
|
||||
- 2025 – [`hb-decycler`][13]
|
||||
- 2022 – [`hb-iter`][14]
|
||||
- 2022 – [A C library written in C++][15]
|
||||
- 2022 – [The case of the slow `hb-ft` `>h_advance` function][18]
|
||||
- 2022 – [PackTab: A static integer table packer][16]
|
||||
- 2020 – [HarfBuzz OT+AAT "Unishaper"][19]
|
||||
- 2014 – [Building the Indic Shaper][17]
|
||||
- 2012 – [Memory Consumption][10]
|
||||
|
||||
|
||||
## Name
|
||||
|
||||
HarfBuzz /hærfˈbɒːz/
|
||||
|
||||
From Persian حرف (*Harf*: letter) and باز (*Buzz*: open).
|
||||
Transliteration of the Persian calque for *OpenType*.
|
||||
|
||||
As a noun: *The* Open Source *text shaping* engine.
|
||||
|
||||
As an adjective: Insincerely talkative; glib. A nod to the
|
||||
GNOME project where HarfBuzz originates from.
|
||||
|
||||
The logo shows حرفباز in the IranNastaliq font, on a Damascus
|
||||
steel background.
|
||||
|
||||
> Background: Originally there was this font format called TrueType. People and
|
||||
> companies started calling their type engines all things ending in Type:
|
||||
> FreeType, CoolType, ClearType, etc. And then came OpenType, which is the
|
||||
> successor of TrueType. So, for my OpenType implementation, I decided to stick
|
||||
> with the concept but use the Persian translation. Which is fitting given that
|
||||
> Persian is written in the Arabic script, and OpenType is an extension of
|
||||
> TrueType that adds support for complex script rendering, and HarfBuzz is an
|
||||
> implementation of OpenType text shaping.
|
||||
|
||||
## Users
|
||||
|
||||
HarfBuzz is used in Android, Chrome, ChromeOS, Firefox, Flutter, GNOME, GTK+, KDE,
|
||||
Qt, LibreOffice, OpenJDK, XeTeX, Adobe Photoshop, Illustrator, InDesign,
|
||||
Microsoft Edge, Amazon Kindle, PlayStation, Godot Engine, Unreal Engine,
|
||||
Figma, Canva, QuarkXPress, Scribus, smart TVs,
|
||||
car displays, and many other places.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://xkcd.com/2347/" rel="nofollow">
|
||||
<img src="xkcd.png" width="256" alt="xkcd-derived image">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## Distribution
|
||||
|
||||
<details>
|
||||
<summary>Packaging status of HarfBuzz</summary>
|
||||
|
||||
[](https://repology.org/project/harfbuzz/versions)
|
||||
|
||||
</details>
|
||||
|
||||
[1]: https://docs.microsoft.com/en-us/typography/opentype/spec/
|
||||
[2]: https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html
|
||||
[3]: https://github.com/harfbuzz/harfbuzz/releases
|
||||
[4]: https://github.com/harfbuzz/harfbuzz
|
||||
[6]: https://behdad.org/text2024
|
||||
[7]: https://docs.google.com/presentation/d/1x97pfbB1gbD53Yhz6-_yBUozQMVJ_5yMqqR_D-R7b7I/preview
|
||||
[8]: https://docs.google.com/presentation/d/1ySTZaXP5XKFg0OpmHZM00v5b17GSr3ojnzJekl4U8qI/preview
|
||||
[9]: https://behdad.org/doc/harfbuzz2009-slides.pdf
|
||||
[10]: https://docs.google.com/document/d/12jfNpQJzeVIAxoUSpk7KziyINAa1msbGliyXqguS86M/preview
|
||||
[11]: https://behdad.org/
|
||||
[12]: https://docs.google.com/document/d/1_VgObf6Je0J8byMLsi7HCQHnKo2emGnx_ib_sHo-bt4/preview
|
||||
[13]: https://docs.google.com/document/d/1Y-u08l9YhObRVObETZt1k8f_5lQdOix9TRH3zEXaoAw/preview
|
||||
[14]: https://docs.google.com/document/d/1o-xvxCbgMe9JYFHLVnPjk01ZY_8Cj0vB9-KTI1d0nyk/preview
|
||||
[15]: https://docs.google.com/document/d/18hI56KJpvXtwWbc9QSaz9zzhJwIMnrJ-zkAaKS-W-8k/preview
|
||||
[16]: https://docs.google.com/document/d/1Xq3owVt61HVkJqbLFHl73il6pcTy6PdPJJ7bSouQiQw/preview
|
||||
[17]: https://docs.google.com/document/d/1wMPwVNBvsIriamcyBO5aNs7Cdr8lmbwLJ8GmZBAswF4/preview
|
||||
[18]: https://docs.google.com/document/d/1wskYbA-czBt57oH9gEuGf3sWbTx7bfOiEIcDs36-heo/preview
|
||||
[19]: https://prezi.com/view/THNPJGFVDUCWoM20syev/
|
||||
[20]: https://behdad.org/doc/harfbuzz10years-slides.pdf
|
||||
[21]: https://docs.google.com/document/d/1_vZrt97OorJ0jA1YzJ29LRcGr3YGrNJANdOABjVZGEs/preview
|
||||
[22]: https://docs.google.com/document/d/1aH_waagdEM5UhslQxCeFEb82ECBhPlZjy5_MwLNLBYo/preview
|
||||
[23]: https://docs.google.com/document/d/1hRd5oYQJLrt0JuwWhEJWi7wh_9rbaIJkX6IR9DW7rZQ/preview
|
||||
[24]: https://docs.google.com/document/d/1a3K6fHjsiWW36vSzwJwCwEBOgznunKs80PSpBbpfHiA/preview
|
||||
[25]: https://docs.google.com/presentation/d/1o9Exz1c-Lr-dJjA8dcBn_Vl_Y37cupmFzmclMjBE_Bc/view
|
||||
[26]: https://harfbuzz-world.cc/
|
||||
Vendored
+386
@@ -0,0 +1,386 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
hb_extract.py -- copy the minimal subset of HarfBuzz sources used by OpenCV.
|
||||
|
||||
OpenCV vendors HarfBuzz as a normal static library: every .cc is a separate
|
||||
translation unit (no unity / amalgamation build). This script reproduces the
|
||||
exact src/ tree that OpenCV ships, from a pristine HarfBuzz checkout.
|
||||
|
||||
It does three things beyond a naive copy, all to keep the vendored tree small
|
||||
and buildable with OpenCV's configuration (HB_TINY + HB_HAS_RASTER, see
|
||||
CMakeLists.txt):
|
||||
|
||||
1. Copies the translation units that upstream `harfbuzz-world.cc` would
|
||||
compile for the requested HB_HAS_* sections -- EXCEPT the ones that build
|
||||
to an empty object under our config (see EMPTY_TUS). It never emits
|
||||
`harfbuzz-world.cc` itself (we compile each .cc directly), and never
|
||||
copies non-TU .cc files found under src/OT|graph (only real TUs from the
|
||||
parsed world.cc lists are copied), so CMake's file(GLOB_RECURSE src/*.cc)
|
||||
picks up exactly the right set.
|
||||
|
||||
2. Prunes headers down to the set actually reachable by #include from the
|
||||
copied TUs (+ the public headers OpenCV includes). This automatically
|
||||
drops the large amount of HarfBuzz src/ that we never compile -- GPU and
|
||||
WASM backends, the subset/repacker graph, platform backends (CoreText/
|
||||
DirectWrite/GDI/Uniscribe/Graphite2/GObject/Cairo), the vector-paint
|
||||
backend, and headers used only by the skipped empty TUs -- without a
|
||||
hardcoded blocklist.
|
||||
|
||||
3. Generates `hb-opencv-config.hh`, the config-override header CMakeLists.txt
|
||||
points HB_CONFIG_OVERRIDE_H at. It re-enables thread-safety (HB_NO_MT) and
|
||||
variable fonts (HB_NO_VAR) that HB_TINY would otherwise switch off. (It
|
||||
does NOT generate upstream's hb-features.h: nothing we compile includes
|
||||
it.)
|
||||
|
||||
Usage (to refresh this very directory, just point it at a harfbuzz checkout):
|
||||
python hb_extract.py path/to/harfbuzz
|
||||
|
||||
The defaults already produce the OpenCV subset: output '.', features
|
||||
HB_HAS_RASTER, and it also copies README.md + COPYING. Override only if needed:
|
||||
-o DIR output root (default '.')
|
||||
-f FLAGS comma-separated HB_HAS_* (default HB_HAS_RASTER)
|
||||
-a FILES extra files (default README.md,COPYING)
|
||||
--list-flags print available HB_HAS_* flags and exit
|
||||
|
||||
-a paths are relative to the harfbuzz repo root (parent of src/):
|
||||
-a README.md -> copied to <out>/README.md
|
||||
-a COPYING -> copied to <out>/COPYING
|
||||
-a src/hb-raster.h -> copied to <out>/src/hb-raster.h
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import posixpath
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Translation units that compile to an EMPTY object (libtool: "has no symbols")
|
||||
# under OpenCV's HarfBuzz configuration (HB_TINY + HB_HAS_RASTER => AAT, legacy
|
||||
# fallback shaping, math, meta, name, buffer (de)serialize/verify and the style
|
||||
# API are all compiled out). They contribute nothing, so we do not vendor them.
|
||||
# Re-derive this list (from the libtool warnings of a clean libharfbuzz build)
|
||||
# if the HarfBuzz configuration in CMakeLists.txt changes.
|
||||
EMPTY_TUS = {
|
||||
"hb-aat-layout.cc",
|
||||
"hb-aat-map.cc",
|
||||
"hb-buffer-serialize.cc",
|
||||
"hb-buffer-verify.cc",
|
||||
"hb-fallback-shape.cc",
|
||||
"hb-ot-math.cc",
|
||||
"hb-ot-meta.cc",
|
||||
"hb-ot-name.cc",
|
||||
"hb-raster.cc",
|
||||
"hb-style.cc",
|
||||
}
|
||||
|
||||
# Public headers OpenCV's text engine (drawing_text.cpp) includes directly.
|
||||
# Used together with the copied TUs as the roots of the header-reachability
|
||||
# prune.
|
||||
SEED_PUBLIC_HEADERS = ("hb.h", "hb-ot.h", "hb-raster.h")
|
||||
|
||||
# Generated config-override header. CMakeLists.txt builds HarfBuzz with HB_TINY
|
||||
# and HB_CONFIG_OVERRIDE_H="hb-opencv-config.hh"; this file is included by
|
||||
# hb-config.hh after HB_TINY/HB_LEAN expand (so the #undef takes effect) but
|
||||
# before the option-closure derives dependent macros.
|
||||
OPENCV_CONFIG_HH = '''\
|
||||
/*
|
||||
* OpenCV-specific HarfBuzz configuration override. GENERATED by hb_extract.py.
|
||||
*
|
||||
* HarfBuzz is built with HB_TINY (see 3rdparty/harfbuzz/CMakeLists.txt) for the
|
||||
* smallest possible footprint. HB_TINY pulls in HB_LEAN + HB_MINI, which would
|
||||
* disable two features that OpenCV's text engine relies on. We restore them
|
||||
* here.
|
||||
*
|
||||
* This file is included by hb-config.hh via HB_CONFIG_OVERRIDE_H, i.e. AFTER
|
||||
* HB_TINY/HB_LEAN/HB_MINI have expanded their macros (so the #undef below takes
|
||||
* effect) but BEFORE the "closure of options" derives dependent macros (e.g.
|
||||
* HB_NO_VAR_COMPOSITES from HB_NO_VAR). That ordering is what makes a plain
|
||||
* #undef sufficient.
|
||||
*
|
||||
* HB_NO_MT - keep thread-safety. hb_font_t instances live inside cv::FontFace
|
||||
* objects, NOT in the thread_local FontRenderEngine, so a single
|
||||
* FontFace (and its hb_font_t) can be shared across threads; its
|
||||
* reference counting must stay atomic.
|
||||
*
|
||||
* HB_NO_VAR - keep variable-font support: the 'wght' axis used for synthetic
|
||||
* weights and named-instance/axis queries (hb_font_set_variations,
|
||||
* hb_ot_var_*). Variable fonts are a primary reason OpenCV adopted
|
||||
* HarfBuzz, so this must remain enabled.
|
||||
*/
|
||||
|
||||
#undef HB_NO_MT
|
||||
#undef HB_NO_VAR
|
||||
'''
|
||||
|
||||
OPENCV_CONFIG_NAME = "hb-opencv-config.hh"
|
||||
|
||||
|
||||
def parse_world_cc(path):
|
||||
"""Return (core_files, sections) parsed from harfbuzz-world.cc.
|
||||
|
||||
core_files -- list of .cc paths (relative to src/) in the unconditional
|
||||
"Core library" section.
|
||||
sections -- dict HB_HAS_XXX -> list of .cc paths from that #ifdef block.
|
||||
"""
|
||||
lines = path.read_text(encoding="utf-8").splitlines()
|
||||
include_re = re.compile(r'^\s*#include\s+"([^"]+\.cc)"')
|
||||
|
||||
core_files = []
|
||||
sections = {}
|
||||
|
||||
STATE_PREAMBLE, STATE_CORE, STATE_IFDEF = "preamble", "core", "ifdef"
|
||||
state = STATE_PREAMBLE
|
||||
current_flag = None
|
||||
ifdef_depth = 0
|
||||
|
||||
for line in lines:
|
||||
if state == STATE_PREAMBLE:
|
||||
if "/* Core library." in line:
|
||||
state = STATE_CORE
|
||||
|
||||
elif state == STATE_CORE:
|
||||
m = include_re.match(line)
|
||||
if m:
|
||||
core_files.append(m.group(1))
|
||||
else:
|
||||
m = re.match(r"^\s*#ifdef\s+(HB_HAS_\w+)", line)
|
||||
if m:
|
||||
current_flag = m.group(1)
|
||||
sections[current_flag] = []
|
||||
state = STATE_IFDEF
|
||||
ifdef_depth = 1
|
||||
|
||||
elif state == STATE_IFDEF:
|
||||
if re.match(r"^\s*#if", line):
|
||||
ifdef_depth += 1
|
||||
elif re.match(r"^\s*#endif", line):
|
||||
ifdef_depth -= 1
|
||||
if ifdef_depth == 0:
|
||||
state = STATE_CORE
|
||||
current_flag = None
|
||||
else:
|
||||
m = include_re.match(line)
|
||||
if m and current_flag is not None:
|
||||
sections[current_flag].append(m.group(1))
|
||||
|
||||
return core_files, sections
|
||||
|
||||
|
||||
def copy_files(file_list, src_dir, out_src_dir, label=""):
|
||||
skipped = []
|
||||
for rel in file_list:
|
||||
if Path(rel).name in EMPTY_TUS:
|
||||
skipped.append(rel)
|
||||
continue
|
||||
src = src_dir / rel
|
||||
dst = out_src_dir / rel
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not src.exists():
|
||||
print(f" [WARN] not found: {src}", file=sys.stderr)
|
||||
continue
|
||||
shutil.copy2(src, dst)
|
||||
print(f" [{label or 'core'}] src/{rel}")
|
||||
for rel in skipped:
|
||||
print(f" [skip-empty] src/{rel}")
|
||||
|
||||
|
||||
def copy_headers(src_dir, out_src_dir, public_h=True):
|
||||
"""Copy all candidate headers: src/*.hh, src/*.h (public API), and *.h/*.hh
|
||||
from src/OT/** and src/graph/**. The unreferenced ones are removed later by
|
||||
prune_unreferenced_headers().
|
||||
|
||||
NOTE: .cc files under OT/ and graph/ are intentionally NOT copied here --
|
||||
the only ones we need are real translation units, copied via the parsed
|
||||
world.cc lists. Copying e.g. src/graph/test-classdef-graph.cc would make
|
||||
CMake's file(GLOB_RECURSE src/*.cc) try to compile a non-TU file.
|
||||
"""
|
||||
count = 0
|
||||
|
||||
def _copy(p):
|
||||
nonlocal count
|
||||
dst = out_src_dir / p.relative_to(src_dir)
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(p, dst)
|
||||
count += 1
|
||||
|
||||
for hdr in src_dir.glob("*.hh"):
|
||||
_copy(hdr)
|
||||
|
||||
for subdir in ("OT", "graph"):
|
||||
d = src_dir / subdir
|
||||
if not d.exists():
|
||||
continue
|
||||
for hdr in d.rglob("*"):
|
||||
if hdr.is_file() and hdr.suffix in (".h", ".hh"):
|
||||
_copy(hdr)
|
||||
|
||||
if public_h:
|
||||
for hdr in src_dir.glob("*.h"):
|
||||
_copy(hdr)
|
||||
|
||||
return count
|
||||
|
||||
|
||||
def prune_unreferenced_headers(out_src_dir):
|
||||
"""Delete every header not reachable by #include from the copied TUs and the
|
||||
public seed headers, then drop any directory left empty.
|
||||
|
||||
HarfBuzz's amalgamated src/ ships many headers we never compile (GPU/WASM
|
||||
backends, subset/repacker graph, platform backends, vector-paint, and the
|
||||
headers used only by the empty TUs we skip). Reachability removes them all
|
||||
without a hardcoded list. The edge regex also treats any quoted "...h"/
|
||||
"...hh" literal as an include, which covers the `#include HB_STRING_ARRAY_LIST`
|
||||
macro-indirection trick (e.g. hb-ot-cff1-std-str.hh, hb-ot-post-macroman.hh).
|
||||
"""
|
||||
files = {p.relative_to(out_src_dir).as_posix()
|
||||
for p in out_src_dir.rglob("*") if p.is_file()}
|
||||
headers = {f for f in files if f.endswith((".h", ".hh"))}
|
||||
edge_re = re.compile(r'#\s*include\s+["<]([^">]+)[">]|"([^"]+\.hh?)"')
|
||||
|
||||
def resolve(inc, including):
|
||||
for cand in (posixpath.normpath(posixpath.join(posixpath.dirname(including), inc)),
|
||||
posixpath.normpath(inc)):
|
||||
if cand in files:
|
||||
return cand
|
||||
return None
|
||||
|
||||
seeds = {f for f in files if f.endswith(".cc")}
|
||||
seeds |= {h for h in SEED_PUBLIC_HEADERS if h in files}
|
||||
|
||||
seen, stack = set(), list(seeds)
|
||||
while stack:
|
||||
cur = stack.pop()
|
||||
if cur in seen:
|
||||
continue
|
||||
seen.add(cur)
|
||||
try:
|
||||
txt = (out_src_dir / cur).read_text(encoding="utf-8", errors="ignore")
|
||||
except OSError:
|
||||
continue
|
||||
for m in edge_re.finditer(txt):
|
||||
inc = m.group(1) or m.group(2)
|
||||
r = resolve(inc, cur)
|
||||
if r and r not in seen:
|
||||
stack.append(r)
|
||||
|
||||
needed = {f for f in seen if f.endswith((".h", ".hh"))}
|
||||
for h in sorted(headers - needed):
|
||||
(out_src_dir / h).unlink()
|
||||
print(f" [prune] src/{h}")
|
||||
|
||||
# remove directories left empty by pruning (deepest first)
|
||||
for d in sorted((p for p in out_src_dir.rglob("*") if p.is_dir()),
|
||||
key=lambda p: len(p.parts), reverse=True):
|
||||
try:
|
||||
d.rmdir()
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
return len(headers - needed), len(needed)
|
||||
|
||||
|
||||
def write_opencv_config_h(out_src_dir):
|
||||
"""Generate hb-opencv-config.hh (the HB_CONFIG_OVERRIDE_H header)."""
|
||||
(out_src_dir / OPENCV_CONFIG_NAME).write_text(OPENCV_CONFIG_HH, encoding="utf-8")
|
||||
print(f" [gen] src/{OPENCV_CONFIG_NAME}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Copy the OpenCV subset of HarfBuzz sources.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
examples:
|
||||
python hb_extract.py ~/work/harfbuzz -o . -f HB_HAS_RASTER -a README.md,COPYING
|
||||
python hb_extract.py ~/work/harfbuzz --list-flags
|
||||
""",
|
||||
)
|
||||
parser.add_argument("harfbuzz_dir", metavar="harfbuzz-dir",
|
||||
help="path to the harfbuzz repo root (contains src/)")
|
||||
parser.add_argument("-o", "--output", metavar="DIR", default=".",
|
||||
help="output root directory; sources go into DIR/src/ "
|
||||
"(default: current directory)")
|
||||
parser.add_argument("-f", "--features", metavar="FLAGS", default="HB_HAS_RASTER",
|
||||
help="comma-separated HB_HAS_* flags (default: HB_HAS_RASTER)")
|
||||
parser.add_argument("-a", "--add", metavar="FILES", default="README.md,COPYING",
|
||||
help="comma-separated files relative to the harfbuzz repo "
|
||||
"root (default: README.md,COPYING)")
|
||||
parser.add_argument("--no-public-headers", action="store_true",
|
||||
help="skip copying public src/*.h API headers "
|
||||
"(OT/, graph/, *.hh are always copied)")
|
||||
parser.add_argument("--list-flags", action="store_true",
|
||||
help="list available HB_HAS_* flags and exit")
|
||||
args = parser.parse_args()
|
||||
|
||||
repo_dir = Path(args.harfbuzz_dir).resolve()
|
||||
world_cc_path = repo_dir / "src" / "harfbuzz-world.cc"
|
||||
if not world_cc_path.exists():
|
||||
print(f"error: {world_cc_path} not found", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
src_dir = world_cc_path.parent
|
||||
core_files, sections = parse_world_cc(world_cc_path)
|
||||
|
||||
if args.list_flags:
|
||||
for flag, files in sorted(sections.items()):
|
||||
print(f" {flag:<22} ({len(files)} .cc files)")
|
||||
return
|
||||
|
||||
enabled_flags = [f.strip() for f in args.features.split(",") if f.strip()]
|
||||
extra_files = [f.strip() for f in args.add.split(",") if f.strip()]
|
||||
|
||||
out_dir = Path(args.output).resolve()
|
||||
out_src_dir = out_dir / "src"
|
||||
|
||||
# Start from a clean src/ so removed-upstream files do not linger.
|
||||
if out_src_dir.exists():
|
||||
shutil.rmtree(out_src_dir)
|
||||
out_src_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"\nsource : {repo_dir}")
|
||||
print(f"output : {out_dir}")
|
||||
print(f"flags : {enabled_flags}\n")
|
||||
|
||||
print("core:")
|
||||
copy_files(core_files, src_dir, out_src_dir)
|
||||
|
||||
for flag in enabled_flags:
|
||||
flag_files = sections.get(flag)
|
||||
if not flag_files:
|
||||
print(f"\n[{flag}]: no .cc files (flag not found in harfbuzz-world.cc)")
|
||||
continue
|
||||
print(f"\n[{flag}]:")
|
||||
copy_files(flag_files, src_dir, out_src_dir, label=flag)
|
||||
|
||||
if extra_files:
|
||||
print("\nextra:")
|
||||
for rel in extra_files:
|
||||
src = repo_dir / rel
|
||||
dst = out_dir / rel
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
if not src.exists():
|
||||
print(f" [WARN] not found: {src}", file=sys.stderr)
|
||||
continue
|
||||
shutil.copy2(src, dst)
|
||||
print(f" [add] {rel}")
|
||||
|
||||
n = copy_headers(src_dir, out_src_dir,
|
||||
public_h=not args.no_public_headers)
|
||||
print(f"\nheaders: {n} files copied")
|
||||
|
||||
print("\nprune (unreferenced headers):")
|
||||
removed, kept = prune_unreferenced_headers(out_src_dir)
|
||||
print(f" removed {removed}, kept {kept}")
|
||||
|
||||
print("\ngenerated:")
|
||||
write_opencv_config_h(out_src_dir)
|
||||
|
||||
all_cc = sorted(out_src_dir.rglob("*.cc"))
|
||||
all_h = list(out_src_dir.rglob("*.h")) + list(out_src_dir.rglob("*.hh"))
|
||||
print(f"\ndone: {len(all_cc)} .cc | {len(all_h)} headers -> {out_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
+1033
File diff suppressed because it is too large
Load Diff
+2861
File diff suppressed because it is too large
Load Diff
+367
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* Copyright © 2016 Google, Inc.
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Sascha Brawer
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_CPAL_CPAL_HH
|
||||
#define OT_COLOR_CPAL_CPAL_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-ot-color.h"
|
||||
#include "../../../hb-ot-name.h"
|
||||
|
||||
|
||||
/*
|
||||
* CPAL -- Color Palette
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
|
||||
*/
|
||||
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct CPALV1Tail
|
||||
{
|
||||
friend struct CPAL;
|
||||
|
||||
private:
|
||||
hb_ot_color_palette_flags_t get_palette_flags (const void *base,
|
||||
unsigned int palette_index,
|
||||
unsigned int palette_count) const
|
||||
{
|
||||
if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
|
||||
return (hb_ot_color_palette_flags_t) (uint32_t)
|
||||
(base+paletteFlagsZ).as_array (palette_count)[palette_index];
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_palette_name_id (const void *base,
|
||||
unsigned int palette_index,
|
||||
unsigned int palette_count) const
|
||||
{
|
||||
if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
|
||||
return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_color_name_id (const void *base,
|
||||
unsigned int color_index,
|
||||
unsigned int color_count) const
|
||||
{
|
||||
if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
|
||||
return (base+colorLabelsZ).as_array (color_count)[color_index];
|
||||
}
|
||||
|
||||
public:
|
||||
void collect_name_ids (const void *base,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (paletteLabelsZ)
|
||||
{
|
||||
+ (base+paletteLabelsZ).as_array (palette_count)
|
||||
| hb_sink (nameids_to_retain)
|
||||
;
|
||||
}
|
||||
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
nameids_to_retain->add (colorLabels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const void *base,
|
||||
const hb_map_t *color_index_map) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->allocate_size<CPALV1Tail> (static_size);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->paletteFlagsZ = 0;
|
||||
if (paletteFlagsZ)
|
||||
out->paletteFlagsZ.serialize_copy (c, paletteFlagsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
out->paletteLabelsZ = 0;
|
||||
if (paletteLabelsZ)
|
||||
out->paletteLabelsZ.serialize_copy (c, paletteLabelsZ, base, 0, hb_serialize_context_t::Head, palette_count);
|
||||
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
c->push ();
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
if (!c->copy<NameID> (colorLabels[i]))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
c->add_link (out->colorLabelsZ, c->pop_pack ());
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c,
|
||||
const void *base,
|
||||
unsigned int palette_count,
|
||||
unsigned int color_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
(!paletteFlagsZ || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
|
||||
(!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
|
||||
(!colorLabelsZ || (base+colorLabelsZ).sanitize (c, color_count)));
|
||||
}
|
||||
|
||||
protected:
|
||||
// TODO(garretrieger): these offsets can hold nulls so we should not be using non-null offsets
|
||||
// here. Currently they are needed since UnsizedArrayOf doesn't define null_size
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT32>>
|
||||
paletteFlagsZ; /* Offset from the beginning of CPAL table to
|
||||
* the Palette Type Array. Set to 0 if no array
|
||||
* is provided. */
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
paletteLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the palette labels array. Set to 0 if no
|
||||
* array is provided. */
|
||||
NNOffset32To<UnsizedArrayOf<NameID>>
|
||||
colorLabelsZ; /* Offset from the beginning of CPAL table to
|
||||
* the color labels array. Set to 0
|
||||
* if no array is provided. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
typedef HBUINT32 BGRAColor;
|
||||
|
||||
struct CPAL
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
|
||||
|
||||
bool has_data () const { return numPalettes; }
|
||||
|
||||
size_t get_size () const
|
||||
{ return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
|
||||
|
||||
unsigned int get_palette_count () const { return numPalettes; }
|
||||
unsigned int get_color_count () const { return numColors; }
|
||||
|
||||
hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
|
||||
{ return v1 ().get_palette_flags (this, palette_index, numPalettes); }
|
||||
|
||||
hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
|
||||
{ return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
|
||||
|
||||
hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
|
||||
{ return v1 ().get_color_name_id (this, color_index, numColors); }
|
||||
|
||||
hb_array_t<const BGRAColor> get_palette_colors (unsigned int palette_index) const
|
||||
{
|
||||
if (unlikely (palette_index >= numPalettes))
|
||||
return hb_array_t<const BGRAColor> ();
|
||||
unsigned int start_index = colorRecordIndicesZ[palette_index];
|
||||
hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
|
||||
return all_colors.sub_array (start_index, numColors);
|
||||
}
|
||||
unsigned int get_palette_colors (unsigned int palette_index,
|
||||
unsigned int start_offset,
|
||||
unsigned int *color_count, /* IN/OUT. May be NULL. */
|
||||
hb_color_t *colors /* OUT. May be NULL. */) const
|
||||
{
|
||||
if (unlikely (palette_index >= numPalettes))
|
||||
{
|
||||
if (color_count) *color_count = 0;
|
||||
return 0;
|
||||
}
|
||||
unsigned int start_index = colorRecordIndicesZ[palette_index];
|
||||
hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
|
||||
hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
|
||||
numColors);
|
||||
if (color_count)
|
||||
{
|
||||
+ palette_colors.sub_array (start_offset, color_count)
|
||||
| hb_sink (hb_array (colors, *color_count))
|
||||
;
|
||||
}
|
||||
return numColors;
|
||||
}
|
||||
|
||||
void collect_name_ids (const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (version == 1)
|
||||
{
|
||||
hb_barrier ();
|
||||
v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const CPALV1Tail& v1 () const
|
||||
{
|
||||
if (version == 0) return Null (CPALV1Tail);
|
||||
hb_barrier ();
|
||||
return StructAfter<CPALV1Tail> (*this);
|
||||
}
|
||||
|
||||
public:
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
const hb_array_t<const HBUINT16> &color_record_indices,
|
||||
const hb_array_t<const BGRAColor> &color_records,
|
||||
const hb_vector_t<unsigned>& first_color_index_for_layer,
|
||||
const hb_map_t& first_color_to_layer_index,
|
||||
const hb_set_t &retained_color_indices) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
// TODO(grieger): limit total final size.
|
||||
|
||||
for (const auto idx : color_record_indices)
|
||||
{
|
||||
hb_codepoint_t layer_index = first_color_to_layer_index[idx];
|
||||
|
||||
HBUINT16 new_idx;
|
||||
new_idx = layer_index * retained_color_indices.get_population ();
|
||||
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
|
||||
}
|
||||
|
||||
c->push ();
|
||||
for (unsigned first_color_index : first_color_index_for_layer)
|
||||
{
|
||||
for (hb_codepoint_t color_index : retained_color_indices)
|
||||
{
|
||||
if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c->add_link (colorRecordsZ, c->pop_pack ());
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (!numPalettes) return_trace (false);
|
||||
|
||||
const hb_map_t *color_index_map = &c->plan->colr_palettes;
|
||||
if (color_index_map->is_empty ()) return_trace (false);
|
||||
|
||||
hb_set_t retained_color_indices;
|
||||
for (const auto _ : color_index_map->keys ())
|
||||
{
|
||||
if (_ == 0xFFFF) continue;
|
||||
retained_color_indices.add (_);
|
||||
}
|
||||
if (retained_color_indices.is_empty ()) return_trace (false);
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
|
||||
out->version = version;
|
||||
out->numColors = retained_color_indices.get_population ();
|
||||
out->numPalettes = numPalettes;
|
||||
|
||||
hb_vector_t<unsigned> first_color_index_for_layer;
|
||||
hb_map_t first_color_to_layer_index;
|
||||
|
||||
const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
|
||||
for (const auto first_color_record_idx : colorRecordIndices)
|
||||
{
|
||||
if (first_color_to_layer_index.has (first_color_record_idx)) continue;
|
||||
|
||||
first_color_index_for_layer.push (first_color_record_idx);
|
||||
if (unlikely (!c->serializer->propagate_error (first_color_index_for_layer))) return_trace (false);
|
||||
first_color_to_layer_index.set (first_color_record_idx,
|
||||
first_color_index_for_layer.length - 1);
|
||||
}
|
||||
|
||||
out->numColorRecords = first_color_index_for_layer.length
|
||||
* retained_color_indices.get_population ();
|
||||
|
||||
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
|
||||
if (!out->serialize (c->serializer,
|
||||
colorRecordIndices,
|
||||
color_records,
|
||||
first_color_index_for_layer,
|
||||
first_color_to_layer_index,
|
||||
retained_color_indices))
|
||||
return_trace (false);
|
||||
|
||||
if (version == 1)
|
||||
{
|
||||
hb_barrier ();
|
||||
return_trace (v1 ().serialize (c->serializer, numPalettes, numColors, this, color_index_map));
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
hb_barrier () &&
|
||||
(this+colorRecordsZ).sanitize (c, numColorRecords) &&
|
||||
colorRecordIndicesZ.sanitize (c, numPalettes) &&
|
||||
(version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number */
|
||||
/* Version 0 */
|
||||
HBUINT16 numColors; /* Number of colors in each palette. */
|
||||
HBUINT16 numPalettes; /* Number of palettes in the table. */
|
||||
HBUINT16 numColorRecords; /* Total number of color records, combined for
|
||||
* all palettes. */
|
||||
NNOffset32To<UnsizedArrayOf<BGRAColor>>
|
||||
colorRecordsZ; /* Offset from the beginning of CPAL table to
|
||||
* the first ColorRecord. */
|
||||
UnsizedArrayOf<HBUINT16>
|
||||
colorRecordIndicesZ; /* Index of each palette’s first color record in
|
||||
* the combined color record array. */
|
||||
/*CPALV1Tail v1;*/
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* OT_COLOR_CPAL_CPAL_HH */
|
||||
+449
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
* Copyright © 2020 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Calder Kitagawa
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_SBIX_SBIX_HH
|
||||
#define OT_COLOR_SBIX_SBIX_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
|
||||
/*
|
||||
* sbix -- Standard Bitmap Graphics
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
|
||||
*/
|
||||
#define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
struct SBIXGlyph
|
||||
{
|
||||
SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
|
||||
if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
|
||||
|
||||
new_glyph->xOffset = xOffset;
|
||||
new_glyph->yOffset = yOffset;
|
||||
new_glyph->graphicType = graphicType;
|
||||
data.copy (c, data_length);
|
||||
return_trace (new_glyph);
|
||||
}
|
||||
|
||||
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
|
||||
* edge of the graphic to the glyph’s origin.
|
||||
* That is, the x-coordinate of the point on the
|
||||
* baseline at the left edge of the glyph. */
|
||||
HBINT16 yOffset; /* The vertical (y-axis) offset from the bottom
|
||||
* edge of the graphic to the glyph’s origin.
|
||||
* That is, the y-coordinate of the point on the
|
||||
* baseline at the left edge of the glyph. */
|
||||
Tag graphicType; /* Indicates the format of the embedded graphic
|
||||
* data: one of 'jpg ', 'png ' or 'tiff', or the
|
||||
* special format 'dupe'. */
|
||||
UnsizedArrayOf<HBUINT8>
|
||||
data; /* The actual embedded graphic data. The total
|
||||
* length is inferred from sequential entries in
|
||||
* the glyphDataOffsets array and the fixed size
|
||||
* (8 bytes) of the preceding fields. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, data);
|
||||
};
|
||||
|
||||
struct SBIXStrike
|
||||
{
|
||||
static size_t get_size (unsigned num_glyphs)
|
||||
{ return min_size + num_glyphs * HBUINT32::static_size; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
|
||||
}
|
||||
|
||||
hb_blob_t *get_glyph_blob (unsigned int glyph_id,
|
||||
hb_blob_t *sbix_blob,
|
||||
hb_tag_t file_type,
|
||||
int *x_offset,
|
||||
int *y_offset,
|
||||
unsigned int num_glyphs,
|
||||
unsigned int *strike_ppem) const
|
||||
{
|
||||
if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
|
||||
|
||||
unsigned int retry_count = 8;
|
||||
unsigned int sbix_len = sbix_blob->length;
|
||||
unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
|
||||
assert (strike_offset < sbix_len);
|
||||
|
||||
retry:
|
||||
if (unlikely (glyph_id >= num_glyphs ||
|
||||
imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
|
||||
imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
|
||||
(unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
|
||||
unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
|
||||
|
||||
const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
|
||||
|
||||
if (glyph->graphicType == HB_TAG ('d','u','p','e'))
|
||||
{
|
||||
if (glyph_length >= 2)
|
||||
{
|
||||
glyph_id = *((HBUINT16 *) &glyph->data);
|
||||
if (retry_count--)
|
||||
goto retry;
|
||||
}
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
if (unlikely (file_type != glyph->graphicType))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
if (strike_ppem) *strike_ppem = ppem;
|
||||
if (x_offset) *x_offset = glyph->xOffset;
|
||||
if (y_offset) *y_offset = glyph->yOffset;
|
||||
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c, unsigned int available_len) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
|
||||
|
||||
auto* out = c->serializer->start_embed<SBIXStrike> ();
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (unlikely (!c->serializer->extend (out, num_output_glyphs + 1))) return_trace (false);
|
||||
out->ppem = ppem;
|
||||
out->resolution = resolution;
|
||||
HBUINT32 head;
|
||||
head = get_size (num_output_glyphs + 1);
|
||||
|
||||
bool has_glyphs = false;
|
||||
for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
|
||||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
|
||||
unlikely (imageOffsetsZ[old_gid].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1].is_null () ||
|
||||
imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
|
||||
imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
|
||||
(unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
|
||||
{
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
continue;
|
||||
}
|
||||
has_glyphs = true;
|
||||
unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
|
||||
unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
|
||||
if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
|
||||
return_trace (false);
|
||||
out->imageOffsetsZ[new_gid] = head;
|
||||
head += delta;
|
||||
}
|
||||
if (has_glyphs)
|
||||
out->imageOffsetsZ[num_output_glyphs] = head;
|
||||
else
|
||||
c->serializer->revert (snap);
|
||||
return_trace (has_glyphs);
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
|
||||
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
|
||||
* strike was designed. (E.g., 96 PPI, 192 PPI.) */
|
||||
protected:
|
||||
UnsizedArrayOf<Offset32To<SBIXGlyph>>
|
||||
imageOffsetsZ; /* Offset from the beginning of the strike data header
|
||||
* to bitmap data for an individual glyph ID. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, imageOffsetsZ);
|
||||
};
|
||||
|
||||
struct sbix
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
|
||||
|
||||
bool has_data () const { return version; }
|
||||
|
||||
const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<sbix> (face);
|
||||
num_glyphs = face->get_num_glyphs ();
|
||||
}
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
||||
bool has_data () const { return table->has_data (); }
|
||||
|
||||
bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
bool scale = true) const
|
||||
{
|
||||
/* We only support PNG right now, and following function checks type. */
|
||||
return get_png_extents (font, glyph, extents, scale);
|
||||
}
|
||||
|
||||
hb_blob_t *reference_png (hb_font_t *font,
|
||||
hb_codepoint_t glyph_id,
|
||||
int *x_offset,
|
||||
int *y_offset,
|
||||
unsigned int *available_ppem) const
|
||||
{
|
||||
return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
|
||||
HB_TAG ('p','n','g',' '),
|
||||
x_offset, y_offset,
|
||||
num_glyphs, available_ppem);
|
||||
}
|
||||
|
||||
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
unsigned int strike_ppem = 0;
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyph_extents_t pixel_extents;
|
||||
|
||||
if (!font->get_glyph_extents (glyph, &extents, false))
|
||||
return false;
|
||||
|
||||
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
|
||||
return false;
|
||||
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
if (hb_blob_is_immutable (blob))
|
||||
return false;
|
||||
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
pixel_extents.width, -pixel_extents.height,
|
||||
HB_PAINT_IMAGE_FORMAT_PNG,
|
||||
0.f,
|
||||
&extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const SBIXStrike &choose_strike (hb_font_t *font) const
|
||||
{
|
||||
unsigned count = table->strikes.len;
|
||||
if (unlikely (!count))
|
||||
return Null (SBIXStrike);
|
||||
|
||||
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
|
||||
if (!requested_ppem)
|
||||
requested_ppem = 1<<30; /* Choose largest strike. */
|
||||
/* TODO Add DPI sensitivity as well? */
|
||||
unsigned int best_i = 0;
|
||||
unsigned int best_ppem = table->get_strike (0).ppem;
|
||||
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
{
|
||||
unsigned int ppem = (table->get_strike (i)).ppem;
|
||||
if ((requested_ppem <= ppem && ppem < best_ppem) ||
|
||||
(requested_ppem > best_ppem && ppem > best_ppem))
|
||||
{
|
||||
best_i = i;
|
||||
best_ppem = ppem;
|
||||
}
|
||||
}
|
||||
|
||||
return table->get_strike (best_i);
|
||||
}
|
||||
|
||||
struct PNGHeader
|
||||
{
|
||||
HBUINT8 signature[8];
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
HBUINT32 length;
|
||||
Tag type;
|
||||
} header;
|
||||
HBUINT32 width;
|
||||
HBUINT32 height;
|
||||
HBUINT8 bitDepth;
|
||||
HBUINT8 colorType;
|
||||
HBUINT8 compressionMethod;
|
||||
HBUINT8 filterMethod;
|
||||
HBUINT8 interlaceMethod;
|
||||
} IHDR;
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (29);
|
||||
};
|
||||
|
||||
bool get_png_extents (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
bool scale = true) const
|
||||
{
|
||||
/* Following code is safe to call even without data.
|
||||
* But faster to short-circuit. */
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
int x_offset = 0, y_offset = 0;
|
||||
unsigned int strike_ppem = 0;
|
||||
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
|
||||
|
||||
const PNGHeader &png = *blob->as<PNGHeader>();
|
||||
|
||||
if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
extents->x_bearing = x_offset;
|
||||
extents->y_bearing = png.IHDR.height + y_offset;
|
||||
extents->width = png.IHDR.width;
|
||||
extents->height = -1 * png.IHDR.height;
|
||||
|
||||
/* Convert to font units. */
|
||||
if (strike_ppem && scale)
|
||||
{
|
||||
float scale = font->face->get_upem () / (float) strike_ppem;
|
||||
extents->x_bearing = roundf (extents->x_bearing * scale);
|
||||
extents->y_bearing = roundf (extents->y_bearing * scale);
|
||||
extents->width = roundf (extents->width * scale);
|
||||
extents->height = roundf (extents->height * scale);
|
||||
}
|
||||
|
||||
if (scale)
|
||||
font->scale_glyph_extents (extents);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return strike_ppem;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_blob_ptr_t<sbix> table;
|
||||
|
||||
unsigned int num_glyphs;
|
||||
};
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
hb_barrier () &&
|
||||
version >= 1 &&
|
||||
strikes.sanitize (c, this)));
|
||||
}
|
||||
|
||||
bool
|
||||
add_strike (hb_subset_context_t *c, unsigned i) const
|
||||
{
|
||||
if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
|
||||
return false;
|
||||
|
||||
return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
|
||||
}
|
||||
|
||||
bool serialize_strike_offsets (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
auto *out = c->serializer->start_embed<Array32OfOffset32To<SBIXStrike>> ();
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
hb_vector_t<Offset32To<SBIXStrike>*> new_strikes;
|
||||
hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
|
||||
for (int i = strikes.len - 1; i >= 0; --i)
|
||||
{
|
||||
auto* o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return_trace (false);
|
||||
*o = 0;
|
||||
auto snap = c->serializer->snapshot ();
|
||||
c->serializer->push ();
|
||||
bool ret = add_strike (c, i);
|
||||
if (!ret)
|
||||
{
|
||||
c->serializer->pop_discard ();
|
||||
out->pop ();
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
else
|
||||
{
|
||||
objidxs.push (c->serializer->pop_pack ());
|
||||
new_strikes.push (o);
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < new_strikes.length; ++i)
|
||||
c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t* c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
|
||||
|
||||
return_trace (serialize_strike_offsets (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number — set to 1 */
|
||||
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.
|
||||
* Bits 2 to 15: reserved (set to 0). */
|
||||
Array32OfOffset32To<SBIXStrike>
|
||||
strikes; /* Offsets from the beginning of the 'sbix'
|
||||
* table to data for each individual bitmap strike. */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, strikes);
|
||||
};
|
||||
|
||||
struct sbix_accelerator_t : sbix::accelerator_t {
|
||||
sbix_accelerator_t (hb_face_t *face) : sbix::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
#endif /* OT_COLOR_SBIX_SBIX_HH */
|
||||
+829
@@ -0,0 +1,829 @@
|
||||
/*
|
||||
* Copyright © 2018 Ebrahim Byagowi
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef OT_COLOR_SVG_SVG_HH
|
||||
#define OT_COLOR_SVG_SVG_HH
|
||||
|
||||
#include "../../../hb-open-type.hh"
|
||||
#include "../../../hb-blob.hh"
|
||||
#include "../../../hb-limits.hh"
|
||||
#include "../../../hb-map.hh"
|
||||
#include "../../../hb-paint.hh"
|
||||
#include "../../../hb-zlib.hh"
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* SVG -- SVG (Scalable Vector Graphics)
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/svg
|
||||
*/
|
||||
|
||||
#define HB_OT_TAG_SVG HB_TAG('S','V','G',' ')
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
static inline hb_blob_t *
|
||||
hb_ot_svg_reference_normalized_blob (hb_blob_t *image,
|
||||
const char **svg,
|
||||
unsigned *len)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_reference (image);
|
||||
unsigned data_len = 0;
|
||||
const char *data = hb_blob_get_data (blob, &data_len);
|
||||
|
||||
if (!data || !data_len)
|
||||
goto fail;
|
||||
|
||||
if (hb_blob_is_gzip (data, data_len))
|
||||
{
|
||||
uint32_t expected_size = 0;
|
||||
if (hb_gzip_get_uncompressed_size (data, data_len, &expected_size) &&
|
||||
unlikely ((size_t) expected_size > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
|
||||
goto fail;
|
||||
|
||||
hb_blob_t *uncompressed = hb_blob_decompress_gzip (blob,
|
||||
HB_SVG_MAX_DOCUMENT_SIZE);
|
||||
if (!uncompressed)
|
||||
goto fail;
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
blob = uncompressed;
|
||||
data = hb_blob_get_data (blob, &data_len);
|
||||
if (!data || !data_len)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (unlikely ((size_t) data_len > (size_t) HB_SVG_MAX_DOCUMENT_SIZE))
|
||||
goto fail;
|
||||
|
||||
if (svg) *svg = data;
|
||||
if (len) *len = data_len;
|
||||
return blob;
|
||||
|
||||
fail:
|
||||
hb_blob_destroy (blob);
|
||||
if (svg) *svg = nullptr;
|
||||
if (len) *len = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct SVGDocumentIndexEntry
|
||||
{
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
|
||||
|
||||
hb_codepoint_t get_start_glyph () const
|
||||
{ return startGlyphID; }
|
||||
|
||||
hb_codepoint_t get_end_glyph () const
|
||||
{ return endGlyphID; }
|
||||
|
||||
hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
|
||||
{
|
||||
return hb_blob_create_sub_blob (svg_blob,
|
||||
index_offset + (unsigned int) svgDoc,
|
||||
svgDocLength);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
hb_barrier () &&
|
||||
svgDoc.sanitize (c, base, svgDocLength));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 startGlyphID; /* The first glyph ID in the range described by
|
||||
* this index entry. */
|
||||
HBUINT16 endGlyphID; /* The last glyph ID in the range described by
|
||||
* this index entry. Must be >= startGlyphID. */
|
||||
NNOffset32To<UnsizedArrayOf<HBUINT8>>
|
||||
svgDoc; /* Offset from the beginning of the SVG Document Index
|
||||
* to an SVG document. Must be non-zero. */
|
||||
HBUINT32 svgDocLength; /* Length of the SVG document.
|
||||
* Must be non-zero. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
||||
struct SVG
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
|
||||
|
||||
struct svg_id_span_t
|
||||
{
|
||||
const char *p;
|
||||
unsigned len;
|
||||
|
||||
bool operator == (const svg_id_span_t &o) const
|
||||
{
|
||||
return len == o.len && !memcmp (p, o.p, len);
|
||||
}
|
||||
|
||||
uint32_t hash () const
|
||||
{
|
||||
uint32_t h = hb_hash (len);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
h = h * 33u + (unsigned char) p[i];
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct svg_defs_entry_t
|
||||
{
|
||||
svg_id_span_t id;
|
||||
unsigned start;
|
||||
unsigned end;
|
||||
};
|
||||
|
||||
struct svg_doc_cache_t
|
||||
{
|
||||
hb_blob_t *blob = nullptr;
|
||||
const char *svg = nullptr;
|
||||
unsigned len = 0;
|
||||
hb_vector_t<svg_defs_entry_t> defs_entries;
|
||||
hb_codepoint_t start_glyph = HB_CODEPOINT_INVALID;
|
||||
hb_codepoint_t end_glyph = HB_CODEPOINT_INVALID;
|
||||
hb_vector_t<hb_pair_t<uint32_t, uint32_t>> glyph_spans;
|
||||
hb_hashmap_t<svg_id_span_t, hb_pair_t<uint32_t, uint32_t>> id_spans;
|
||||
};
|
||||
|
||||
bool has_data () const { return svgDocEntries; }
|
||||
|
||||
struct accelerator_t
|
||||
{
|
||||
accelerator_t (hb_face_t *face);
|
||||
~accelerator_t ();
|
||||
|
||||
hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
|
||||
table->svgDocEntries);
|
||||
}
|
||||
|
||||
unsigned get_document_count () const
|
||||
{ return table->get_document_count (); }
|
||||
|
||||
bool get_glyph_document_index (hb_codepoint_t glyph_id, unsigned *index) const
|
||||
{ return table->get_glyph_document_index (glyph_id, index); }
|
||||
|
||||
bool get_document_glyph_range (unsigned index,
|
||||
hb_codepoint_t *start_glyph,
|
||||
hb_codepoint_t *end_glyph) const
|
||||
{ return table->get_document_glyph_range (index, start_glyph, end_glyph); }
|
||||
|
||||
bool has_data () const { return table->has_data (); }
|
||||
|
||||
const svg_doc_cache_t *
|
||||
get_or_create_doc_cache (hb_blob_t *image,
|
||||
const char *svg,
|
||||
unsigned len,
|
||||
unsigned doc_index,
|
||||
hb_codepoint_t start_glyph,
|
||||
hb_codepoint_t end_glyph) const;
|
||||
|
||||
const char *
|
||||
doc_cache_get_svg (const svg_doc_cache_t *doc,
|
||||
unsigned *len) const;
|
||||
|
||||
const hb_vector_t<svg_defs_entry_t> *
|
||||
doc_cache_get_defs_entries (const svg_doc_cache_t *doc) const;
|
||||
|
||||
bool
|
||||
doc_cache_get_glyph_span (const svg_doc_cache_t *doc,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned *start,
|
||||
unsigned *end) const;
|
||||
|
||||
bool
|
||||
doc_cache_find_id_span (const svg_doc_cache_t *doc,
|
||||
svg_id_span_t id,
|
||||
unsigned *start,
|
||||
unsigned *end) const;
|
||||
|
||||
bool
|
||||
doc_cache_find_id_cstr (const svg_doc_cache_t *doc,
|
||||
const char *id,
|
||||
unsigned *start,
|
||||
unsigned *end) const;
|
||||
|
||||
bool paint_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
hb_blob_t *blob = reference_blob_for_glyph (glyph);
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return false;
|
||||
|
||||
bool ret = funcs->image (data,
|
||||
blob,
|
||||
0, 0,
|
||||
HB_PAINT_IMAGE_FORMAT_SVG,
|
||||
0.f,
|
||||
nullptr);
|
||||
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
svg_doc_cache_t *
|
||||
make_doc_cache (hb_blob_t *image,
|
||||
const char *svg,
|
||||
unsigned len,
|
||||
hb_codepoint_t start_glyph,
|
||||
hb_codepoint_t end_glyph) const;
|
||||
|
||||
static void destroy_doc_cache (svg_doc_cache_t *doc);
|
||||
|
||||
hb_blob_ptr_t<SVG> table;
|
||||
mutable hb_vector_t<hb_atomic_t<svg_doc_cache_t *>> doc_caches;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (sizeof (hb_blob_ptr_t<SVG>) +
|
||||
sizeof (hb_vector_t<hb_atomic_t<svg_doc_cache_t *>>));
|
||||
};
|
||||
|
||||
const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
|
||||
{ return (this+svgDocEntries).bsearch (glyph_id); }
|
||||
|
||||
unsigned get_document_count () const
|
||||
{
|
||||
if (!has_data ())
|
||||
return 0;
|
||||
return (this + svgDocEntries).len;
|
||||
}
|
||||
|
||||
bool get_glyph_document_index (hb_codepoint_t glyph_id, unsigned *index) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
return (this + svgDocEntries).bfind (glyph_id, index);
|
||||
}
|
||||
|
||||
bool get_document_glyph_range (unsigned index,
|
||||
hb_codepoint_t *start_glyph,
|
||||
hb_codepoint_t *end_glyph) const
|
||||
{
|
||||
if (!has_data ())
|
||||
return false;
|
||||
|
||||
const auto &entries = this + svgDocEntries;
|
||||
if (index >= entries.len)
|
||||
return false;
|
||||
|
||||
const auto &entry = entries.arrayZ[index];
|
||||
if (start_glyph) *start_glyph = entry.get_start_glyph ();
|
||||
if (end_glyph) *end_glyph = entry.get_end_glyph ();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (likely (c->check_struct (this) &&
|
||||
(this+svgDocEntries).sanitize_shallow (c)));
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version (starting at 0). */
|
||||
Offset32To<SortedArray16Of<SVGDocumentIndexEntry>>
|
||||
svgDocEntries; /* Offset (relative to the start of the SVG table) to the
|
||||
* SVG Documents Index. Must be non-zero. */
|
||||
/* Array of SVG Document Index Entries. */
|
||||
HBUINT32 reserved; /* Set to 0. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
};
|
||||
|
||||
namespace _hb_svg_cache_impl {
|
||||
|
||||
struct glyph_entry_t
|
||||
{
|
||||
hb_codepoint_t glyph;
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
struct id_entry_t
|
||||
{
|
||||
SVG::svg_id_span_t id;
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
struct open_elem_t
|
||||
{
|
||||
unsigned start;
|
||||
SVG::svg_id_span_t id;
|
||||
bool in_defs_content;
|
||||
bool is_defs;
|
||||
};
|
||||
|
||||
static const unsigned MAX_DEPTH = 128;
|
||||
|
||||
static inline int
|
||||
find_substr (const char *s,
|
||||
unsigned n,
|
||||
unsigned from,
|
||||
const char *needle,
|
||||
unsigned needle_len)
|
||||
{
|
||||
if (!needle_len || from >= n || needle_len > n)
|
||||
return -1;
|
||||
for (unsigned i = from; i + needle_len <= n; i++)
|
||||
if (s[i] == needle[0] && !memcmp (s + i, needle, needle_len))
|
||||
return (int) i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
parse_id_in_start_tag (const char *svg,
|
||||
unsigned tag_start,
|
||||
unsigned tag_end,
|
||||
SVG::svg_id_span_t *id)
|
||||
{
|
||||
unsigned p = tag_start;
|
||||
while (p + 4 <= tag_end)
|
||||
{
|
||||
if (!memcmp (svg + p, "id=\"", 4))
|
||||
{
|
||||
unsigned b = p + 4;
|
||||
unsigned e = b;
|
||||
while (e < tag_end && svg[e] != '"') e++;
|
||||
if (e <= tag_end && e > b)
|
||||
{
|
||||
*id = {svg + b, e - b};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!memcmp (svg + p, "id='", 4))
|
||||
{
|
||||
unsigned b = p + 4;
|
||||
unsigned e = b;
|
||||
while (e < tag_end && svg[e] != '\'') e++;
|
||||
if (e <= tag_end && e > b)
|
||||
{
|
||||
*id = {svg + b, e - b};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
parse_glyph_id_span (const SVG::svg_id_span_t &id,
|
||||
hb_codepoint_t *glyph)
|
||||
{
|
||||
if (id.len <= 5 || memcmp (id.p, "glyph", 5))
|
||||
return false;
|
||||
|
||||
hb_codepoint_t gid = 0;
|
||||
for (unsigned i = 5; i < id.len; i++)
|
||||
{
|
||||
unsigned char c = (unsigned char) id.p[i];
|
||||
if (c < '0' || c > '9')
|
||||
return false;
|
||||
hb_codepoint_t digit = (hb_codepoint_t) (c - '0');
|
||||
if (unlikely (gid > HB_CODEPOINT_INVALID / 10 ||
|
||||
(gid == HB_CODEPOINT_INVALID / 10 &&
|
||||
digit > HB_CODEPOINT_INVALID % 10)))
|
||||
return false;
|
||||
gid = (hb_codepoint_t) (gid * 10 + digit);
|
||||
}
|
||||
|
||||
*glyph = gid;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
parse_cache_entries_linear (const char *svg,
|
||||
unsigned len,
|
||||
hb_vector_t<SVG::svg_defs_entry_t> *defs_entries,
|
||||
hb_vector_t<glyph_entry_t> *glyph_spans,
|
||||
hb_vector_t<id_entry_t> *id_entries)
|
||||
{
|
||||
open_elem_t stack[MAX_DEPTH] = {};
|
||||
unsigned depth = 0;
|
||||
if (unlikely (!defs_entries->alloc (256) ||
|
||||
!glyph_spans->alloc (256) ||
|
||||
!id_entries->alloc (256)))
|
||||
return false;
|
||||
|
||||
unsigned defs_depth = 0;
|
||||
unsigned i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if (svg[i] != '<')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 4 <= len && !memcmp (svg + i, "<!--", 4))
|
||||
{
|
||||
int cend = find_substr (svg, len, i + 4, "-->", 3);
|
||||
if (cend < 0) return false;
|
||||
i = (unsigned) cend + 3;
|
||||
continue;
|
||||
}
|
||||
if (i + 9 <= len && !memcmp (svg + i, "<![CDATA[", 9))
|
||||
{
|
||||
int cend = find_substr (svg, len, i + 9, "]]>", 3);
|
||||
if (cend < 0) return false;
|
||||
i = (unsigned) cend + 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool closing = (i + 1 < len && svg[i + 1] == '/');
|
||||
bool special = (i + 1 < len && (svg[i + 1] == '!' || svg[i + 1] == '?'));
|
||||
|
||||
unsigned gt = i + 1;
|
||||
char quote = 0;
|
||||
while (gt < len)
|
||||
{
|
||||
char c = svg[gt];
|
||||
if (quote)
|
||||
{
|
||||
if (c == quote) quote = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '"' || c == '\'')
|
||||
quote = c;
|
||||
else if (c == '>')
|
||||
break;
|
||||
}
|
||||
gt++;
|
||||
}
|
||||
if (gt >= len)
|
||||
return false;
|
||||
|
||||
if (special)
|
||||
{
|
||||
i = gt + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned p = i + (closing ? 2 : 1);
|
||||
while (p < gt && isspace ((unsigned char) svg[p])) p++;
|
||||
const char *name = svg + p;
|
||||
unsigned name_len = 0;
|
||||
while (p + name_len < gt)
|
||||
{
|
||||
unsigned char c = (unsigned char) name[name_len];
|
||||
if (!(isalnum (c) || c == '_' || c == '-' || c == ':'))
|
||||
break;
|
||||
name_len++;
|
||||
}
|
||||
bool is_defs = (name_len == 4 && !memcmp (name, "defs", 4));
|
||||
|
||||
if (closing)
|
||||
{
|
||||
if (!depth)
|
||||
{
|
||||
i = gt + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
open_elem_t e = stack[--depth];
|
||||
unsigned end = gt + 1;
|
||||
|
||||
if (e.id.len)
|
||||
{
|
||||
if (unlikely (!id_entries->push_or_fail (id_entry_t {e.id, (uint32_t) e.start, (uint32_t) end})))
|
||||
return false;
|
||||
|
||||
if (e.in_defs_content)
|
||||
{
|
||||
if (unlikely (!defs_entries->push_or_fail ()))
|
||||
return false;
|
||||
auto &slot = defs_entries->tail ();
|
||||
slot.id = e.id;
|
||||
slot.start = e.start;
|
||||
slot.end = end;
|
||||
}
|
||||
|
||||
hb_codepoint_t gid;
|
||||
if (parse_glyph_id_span (e.id, &gid))
|
||||
{
|
||||
if (unlikely (!glyph_spans->push_or_fail (glyph_entry_t {gid, (uint32_t) e.start, (uint32_t) end})))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.is_defs && defs_depth)
|
||||
defs_depth--;
|
||||
|
||||
i = end;
|
||||
continue;
|
||||
}
|
||||
|
||||
SVG::svg_id_span_t id = {};
|
||||
parse_id_in_start_tag (svg, i, gt, &id);
|
||||
|
||||
unsigned r = gt;
|
||||
while (r > i && isspace ((unsigned char) svg[r - 1])) r--;
|
||||
bool self_closing = (r > i && svg[r - 1] == '/');
|
||||
|
||||
open_elem_t e = {};
|
||||
e.start = i;
|
||||
e.id = id;
|
||||
e.in_defs_content = defs_depth > 0;
|
||||
e.is_defs = is_defs;
|
||||
|
||||
if (self_closing)
|
||||
{
|
||||
unsigned end = gt + 1;
|
||||
if (e.id.len)
|
||||
{
|
||||
if (unlikely (!id_entries->push_or_fail (id_entry_t {e.id, (uint32_t) e.start, (uint32_t) end})))
|
||||
return false;
|
||||
|
||||
if (e.in_defs_content)
|
||||
{
|
||||
if (unlikely (!defs_entries->push_or_fail ()))
|
||||
return false;
|
||||
auto &slot = defs_entries->tail ();
|
||||
slot.id = e.id;
|
||||
slot.start = e.start;
|
||||
slot.end = end;
|
||||
}
|
||||
|
||||
hb_codepoint_t gid;
|
||||
if (parse_glyph_id_span (e.id, &gid))
|
||||
{
|
||||
if (unlikely (!glyph_spans->push_or_fail (glyph_entry_t {gid, (uint32_t) e.start, (uint32_t) end})))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (depth >= MAX_DEPTH))
|
||||
return false;
|
||||
stack[depth++] = e;
|
||||
if (is_defs)
|
||||
defs_depth++;
|
||||
}
|
||||
|
||||
i = gt + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* namespace _hb_svg_cache_impl */
|
||||
|
||||
inline
|
||||
SVG::accelerator_t::accelerator_t (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<SVG> (face);
|
||||
doc_caches.init ();
|
||||
unsigned doc_count = table->get_document_count ();
|
||||
if (doc_count && unlikely (!doc_caches.resize (doc_count)))
|
||||
doc_caches.clear ();
|
||||
for (unsigned i = 0; i < doc_caches.length; i++)
|
||||
doc_caches.arrayZ[i].set_relaxed (nullptr);
|
||||
}
|
||||
|
||||
inline
|
||||
SVG::accelerator_t::~accelerator_t ()
|
||||
{
|
||||
for (unsigned i = 0; i < doc_caches.length; i++)
|
||||
destroy_doc_cache (doc_caches.arrayZ[i].get_relaxed ());
|
||||
doc_caches.fini ();
|
||||
table.destroy ();
|
||||
}
|
||||
|
||||
inline void
|
||||
SVG::accelerator_t::destroy_doc_cache (svg_doc_cache_t *doc)
|
||||
{
|
||||
if (!doc)
|
||||
return;
|
||||
doc->glyph_spans.fini ();
|
||||
doc->defs_entries.fini ();
|
||||
doc->id_spans.fini ();
|
||||
hb_blob_destroy (doc->blob);
|
||||
hb_free (doc);
|
||||
}
|
||||
|
||||
inline SVG::svg_doc_cache_t *
|
||||
SVG::accelerator_t::make_doc_cache (hb_blob_t *image,
|
||||
const char *svg,
|
||||
unsigned len,
|
||||
hb_codepoint_t start_glyph,
|
||||
hb_codepoint_t end_glyph) const
|
||||
{
|
||||
static const uint32_t INVALID_SPAN = 0xFFFFFFFFu;
|
||||
|
||||
auto *doc = (svg_doc_cache_t *) hb_malloc (sizeof (svg_doc_cache_t));
|
||||
if (!doc)
|
||||
return nullptr;
|
||||
|
||||
doc->blob = nullptr;
|
||||
doc->svg = nullptr;
|
||||
doc->len = 0;
|
||||
doc->defs_entries.init ();
|
||||
doc->start_glyph = HB_CODEPOINT_INVALID;
|
||||
doc->end_glyph = HB_CODEPOINT_INVALID;
|
||||
doc->glyph_spans.init ();
|
||||
doc->id_spans.init ();
|
||||
|
||||
doc->blob = hb_blob_reference (image);
|
||||
doc->svg = svg;
|
||||
doc->len = len;
|
||||
doc->start_glyph = start_glyph;
|
||||
doc->end_glyph = end_glyph;
|
||||
|
||||
if (unlikely (start_glyph == HB_CODEPOINT_INVALID || end_glyph < start_glyph))
|
||||
{
|
||||
destroy_doc_cache (doc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned glyph_count = end_glyph - start_glyph + 1;
|
||||
if (!doc->glyph_spans.resize ((int) glyph_count))
|
||||
{
|
||||
destroy_doc_cache (doc);
|
||||
return nullptr;
|
||||
}
|
||||
for (unsigned i = 0; i < glyph_count; i++)
|
||||
doc->glyph_spans.arrayZ[i] = hb_pair_t<uint32_t, uint32_t> (INVALID_SPAN, INVALID_SPAN);
|
||||
|
||||
hb_vector_t<_hb_svg_cache_impl::glyph_entry_t> glyph_spans;
|
||||
glyph_spans.init ();
|
||||
hb_vector_t<_hb_svg_cache_impl::id_entry_t> id_entries;
|
||||
id_entries.init ();
|
||||
if (!_hb_svg_cache_impl::parse_cache_entries_linear (svg, len,
|
||||
&doc->defs_entries,
|
||||
&glyph_spans,
|
||||
&id_entries))
|
||||
{
|
||||
id_entries.fini ();
|
||||
glyph_spans.fini ();
|
||||
destroy_doc_cache (doc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < glyph_spans.length; i++)
|
||||
{
|
||||
const auto &span = glyph_spans.arrayZ[i];
|
||||
if (unlikely (span.glyph < start_glyph || span.glyph > end_glyph))
|
||||
continue;
|
||||
doc->glyph_spans.arrayZ[span.glyph - start_glyph] = hb_pair_t<uint32_t, uint32_t> (span.start, span.end);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < id_entries.length; i++)
|
||||
{
|
||||
const auto &e = id_entries.arrayZ[i];
|
||||
hb_pair_t<uint32_t, uint32_t> *out = nullptr;
|
||||
if (doc->id_spans.has (e.id, &out))
|
||||
continue;
|
||||
if (unlikely (!doc->id_spans.set (e.id, hb_pair_t<uint32_t, uint32_t> (e.start, e.end))))
|
||||
{
|
||||
id_entries.fini ();
|
||||
glyph_spans.fini ();
|
||||
destroy_doc_cache (doc);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
id_entries.fini ();
|
||||
glyph_spans.fini ();
|
||||
return doc;
|
||||
}
|
||||
|
||||
inline const SVG::svg_doc_cache_t *
|
||||
SVG::accelerator_t::get_or_create_doc_cache (hb_blob_t *image,
|
||||
const char *svg,
|
||||
unsigned len,
|
||||
unsigned doc_index,
|
||||
hb_codepoint_t start_glyph,
|
||||
hb_codepoint_t end_glyph) const
|
||||
{
|
||||
if (doc_index >= doc_caches.length)
|
||||
return nullptr;
|
||||
|
||||
auto &slot = doc_caches.arrayZ[doc_index];
|
||||
auto *doc = slot.get_acquire ();
|
||||
if (doc)
|
||||
return doc;
|
||||
|
||||
auto *fresh = make_doc_cache (image, svg, len, start_glyph, end_glyph);
|
||||
if (!fresh)
|
||||
return nullptr;
|
||||
|
||||
auto *expected = (svg_doc_cache_t *) nullptr;
|
||||
if (slot.cmpexch (expected, fresh))
|
||||
return fresh;
|
||||
|
||||
destroy_doc_cache (fresh);
|
||||
return expected;
|
||||
}
|
||||
|
||||
inline const char *
|
||||
SVG::accelerator_t::doc_cache_get_svg (const svg_doc_cache_t *doc,
|
||||
unsigned *len) const
|
||||
{
|
||||
if (!doc)
|
||||
{
|
||||
if (len) *len = 0;
|
||||
return nullptr;
|
||||
}
|
||||
if (len) *len = doc->len;
|
||||
return doc->svg;
|
||||
}
|
||||
|
||||
inline const hb_vector_t<SVG::svg_defs_entry_t> *
|
||||
SVG::accelerator_t::doc_cache_get_defs_entries (const svg_doc_cache_t *doc) const
|
||||
{
|
||||
return doc ? &doc->defs_entries : nullptr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
SVG::accelerator_t::doc_cache_get_glyph_span (const svg_doc_cache_t *doc,
|
||||
hb_codepoint_t glyph,
|
||||
unsigned *start,
|
||||
unsigned *end) const
|
||||
{
|
||||
static const uint32_t INVALID_SPAN = 0xFFFFFFFFu;
|
||||
if (!doc || doc->start_glyph == HB_CODEPOINT_INVALID ||
|
||||
glyph < doc->start_glyph || glyph > doc->end_glyph)
|
||||
return false;
|
||||
|
||||
const auto &span = doc->glyph_spans.arrayZ[glyph - doc->start_glyph];
|
||||
if (span.first == INVALID_SPAN)
|
||||
return false;
|
||||
if (unlikely (span.first > span.second || span.second > doc->len))
|
||||
return false;
|
||||
|
||||
if (start) *start = span.first;
|
||||
if (end) *end = span.second;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
SVG::accelerator_t::doc_cache_find_id_span (const svg_doc_cache_t *doc,
|
||||
svg_id_span_t id,
|
||||
unsigned *start,
|
||||
unsigned *end) const
|
||||
{
|
||||
if (!doc || !id.p || !id.len)
|
||||
return false;
|
||||
hb_pair_t<uint32_t, uint32_t> *span = nullptr;
|
||||
if (!doc->id_spans.has (id, &span))
|
||||
return false;
|
||||
if (unlikely (span->first > span->second || span->second > doc->len))
|
||||
return false;
|
||||
if (start) *start = span->first;
|
||||
if (end) *end = span->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
SVG::accelerator_t::doc_cache_find_id_cstr (const svg_doc_cache_t *doc,
|
||||
const char *id,
|
||||
unsigned *start,
|
||||
unsigned *end) const
|
||||
{
|
||||
if (!id) return false;
|
||||
svg_id_span_t key = {id, (unsigned) strlen (id)};
|
||||
return doc_cache_find_id_span (doc, key, start, end);
|
||||
}
|
||||
|
||||
struct SVG_accelerator_t : SVG::accelerator_t {
|
||||
SVG_accelerator_t (hb_face_t *face) : SVG::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* OT_COLOR_SVG_SVG_HH */
|
||||
+394
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGE_HH
|
||||
|
||||
#include "../types.hh"
|
||||
#include "CoverageFormat1.hh"
|
||||
#include "CoverageFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void Coverage_serialize (hb_serialize_context_t *c,
|
||||
Iterator it);
|
||||
|
||||
struct Coverage
|
||||
{
|
||||
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CoverageFormat1_3<SmallTypes> format1;
|
||||
CoverageFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
CoverageFormat1_3<MediumTypes>format3;
|
||||
CoverageFormat2_4<MediumTypes>format4;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
HB_ALWAYS_INLINE
|
||||
#endif
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
case 4: return_trace (u.format4.sanitize (c));
|
||||
#endif
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Has interface. */
|
||||
unsigned operator [] (hb_codepoint_t k) const { return get (k); }
|
||||
bool has (hb_codepoint_t k) const { return (*this)[k] != NOT_COVERED; }
|
||||
/* Predicate. */
|
||||
bool operator () (hb_codepoint_t k) const { return has (k); }
|
||||
|
||||
unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.get_coverage (glyph_id);
|
||||
case 2: return u.format2.get_coverage (glyph_id);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_coverage (glyph_id);
|
||||
case 4: return u.format4.get_coverage (glyph_id);
|
||||
#endif
|
||||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id,
|
||||
hb_ot_layout_mapping_cache_t *cache) const
|
||||
{
|
||||
unsigned coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED;
|
||||
coverage = get_coverage (glyph_id);
|
||||
if (cache) {
|
||||
if (coverage == NOT_COVERED)
|
||||
cache->set_unchecked (glyph_id, cache->MAX_VALUE);
|
||||
else if (likely (coverage < cache->MAX_VALUE))
|
||||
cache->set_unchecked (glyph_id, coverage);
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
unsigned int get_coverage_binary (hb_codepoint_t glyph_id,
|
||||
hb_ot_layout_binary_cache_t *cache) const
|
||||
{
|
||||
unsigned coverage;
|
||||
if (cache && cache->get (glyph_id, &coverage)) return coverage < cache->MAX_VALUE ? coverage : NOT_COVERED;
|
||||
coverage = get_coverage (glyph_id);
|
||||
if (cache) {
|
||||
if (coverage == NOT_COVERED)
|
||||
cache->set_unchecked (glyph_id, cache->MAX_VALUE);
|
||||
else
|
||||
cache->set_unchecked (glyph_id, 0);
|
||||
}
|
||||
return coverage;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
switch (u.format.v) {
|
||||
case 1: return u.format1.get_population ();
|
||||
case 2: return u.format2.get_population ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_population ();
|
||||
case 4: return u.format4.get_population ();
|
||||
#endif
|
||||
default:return NOT_COVERED;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned count = hb_len (glyphs);
|
||||
unsigned num_ranges = 0;
|
||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||
hb_codepoint_t max = 0;
|
||||
bool unsorted = false;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last != (hb_codepoint_t) -2 && g < last)
|
||||
unsorted = true;
|
||||
if (last + 1 != g)
|
||||
num_ranges++;
|
||||
last = g;
|
||||
if (g > max) max = g;
|
||||
}
|
||||
u.format.v = !unsorted && count <= num_ranges * 3 ? 1 : 2;
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (max > 0xFFFFu)
|
||||
u.format.v += 2;
|
||||
if (unlikely (max > 0xFFFFFFu))
|
||||
#else
|
||||
if (unlikely (max > 0xFFFFu))
|
||||
#endif
|
||||
{
|
||||
c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs));
|
||||
case 2: return_trace (u.format2.serialize (c, glyphs));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (u.format3.serialize (c, glyphs));
|
||||
case 4: return_trace (u.format4.serialize (c, glyphs));
|
||||
#endif
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto it =
|
||||
+ iter ()
|
||||
| hb_take (c->plan->source->get_num_glyphs ())
|
||||
| hb_map_retains_sorting (c->plan->glyph_map_gsub)
|
||||
| hb_filter ([] (hb_codepoint_t glyph) { return glyph != HB_MAP_VALUE_INVALID; })
|
||||
;
|
||||
|
||||
// Cache the iterator result as it will be iterated multiple times
|
||||
// by the serialize code below.
|
||||
hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
|
||||
Coverage_serialize (c->serializer, glyphs.iter ());
|
||||
return_trace (bool (glyphs));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersects (glyphs);
|
||||
case 2: return u.format2.intersects (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersects (glyphs);
|
||||
case 4: return u.format4.intersects (glyphs);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersects_coverage (glyphs, index);
|
||||
case 2: return u.format2.intersects_coverage (glyphs, index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersects_coverage (glyphs, index);
|
||||
case 4: return u.format4.intersects_coverage (glyphs, index);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned cost () const
|
||||
{
|
||||
switch (u.format.v) {
|
||||
case 1: hb_barrier (); return u.format1.cost ();
|
||||
case 2: hb_barrier (); return u.format2.cost ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: hb_barrier (); return u.format3.cost ();
|
||||
case 4: hb_barrier (); return u.format4.cost ();
|
||||
#endif
|
||||
default:return 0u;
|
||||
}
|
||||
}
|
||||
|
||||
/* Might return false if array looks unsorted.
|
||||
* Used for faster rejection of corrupt data. */
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.collect_coverage (glyphs);
|
||||
case 2: return u.format2.collect_coverage (glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.collect_coverage (glyphs);
|
||||
case 4: return u.format4.collect_coverage (glyphs);
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
switch (u.format.v)
|
||||
{
|
||||
case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
|
||||
case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
|
||||
case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
|
||||
#endif
|
||||
default:return ;
|
||||
}
|
||||
}
|
||||
|
||||
struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
|
||||
{
|
||||
static constexpr bool is_sorted_iterator = true;
|
||||
iter_t (const Coverage &c_ = Null (Coverage))
|
||||
{
|
||||
hb_memset (this, 0, sizeof (*this));
|
||||
format = c_.u.format.v;
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.init (c_.u.format1); return;
|
||||
case 2: u.format2.init (c_.u.format2); return;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: u.format3.init (c_.u.format3); return;
|
||||
case 4: u.format4.init (c_.u.format4); return;
|
||||
#endif
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
bool __more__ () const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1.__more__ ();
|
||||
case 2: return u.format2.__more__ ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.__more__ ();
|
||||
case 4: return u.format4.__more__ ();
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
void __next__ ()
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: u.format1.__next__ (); break;
|
||||
case 2: u.format2.__next__ (); break;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: u.format3.__next__ (); break;
|
||||
case 4: u.format4.__next__ (); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
typedef hb_codepoint_t __item_t__;
|
||||
__item_t__ __item__ () const { return get_glyph (); }
|
||||
|
||||
hb_codepoint_t get_glyph () const
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1.get_glyph ();
|
||||
case 2: return u.format2.get_glyph ();
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3.get_glyph ();
|
||||
case 4: return u.format4.get_glyph ();
|
||||
#endif
|
||||
default:return 0;
|
||||
}
|
||||
}
|
||||
bool operator != (const iter_t& o) const
|
||||
{
|
||||
if (unlikely (format != o.format)) return true;
|
||||
switch (format)
|
||||
{
|
||||
case 1: return u.format1 != o.u.format1;
|
||||
case 2: return u.format2 != o.u.format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return u.format3 != o.u.format3;
|
||||
case 4: return u.format4 != o.u.format4;
|
||||
#endif
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
iter_t __end__ () const
|
||||
{
|
||||
iter_t it;
|
||||
it.format = format;
|
||||
switch (format)
|
||||
{
|
||||
case 1: it.u.format1 = u.format1.__end__ (); break;
|
||||
case 2: it.u.format2 = u.format2.__end__ (); break;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: it.u.format3 = u.format3.__end__ (); break;
|
||||
case 4: it.u.format4 = u.format4.__end__ (); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int format;
|
||||
union {
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1_3<MediumTypes>::iter_t format3;
|
||||
#endif
|
||||
CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
|
||||
CoverageFormat1_3<SmallTypes>::iter_t format1;
|
||||
} u;
|
||||
};
|
||||
iter_t iter () const { return iter_t (*this); }
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
static inline void
|
||||
Coverage_serialize (hb_serialize_context_t *c,
|
||||
Iterator it)
|
||||
{ c->start_embed<Coverage> ()->serialize (c, it); }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
#define NOT_COVERED ((unsigned int) -1)
|
||||
|
||||
template <typename Types>
|
||||
struct CoverageFormat1_3
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
public:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 1 */
|
||||
SortedArray16Of<typename Types::HBGlyphID>
|
||||
glyphArray; /* Array of GlyphIDs--in numerical order */
|
||||
|
||||
DEFINE_SIZE_ARRAY (4, glyphArray);
|
||||
|
||||
private:
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (glyphArray.sanitize (c));
|
||||
}
|
||||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
unsigned int i;
|
||||
glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
return glyphArray.len;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (glyphArray.serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (glyphArray.len > glyphs->get_population () * hb_bit_storage ((unsigned) glyphArray.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& g : glyphArray.as_array ())
|
||||
if (glyphs->has (g))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{ return glyphs->has (glyphArray[index]); }
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
unsigned count = glyphArray.len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
if (glyphs.has (glyphArray[i]))
|
||||
intersect_glyphs << glyphArray[i];
|
||||
}
|
||||
|
||||
unsigned cost () const { return hb_bit_storage ((unsigned) glyphArray.len); /* bsearch cost */ }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_sorted_array (glyphArray.as_array ()); }
|
||||
|
||||
public:
|
||||
/* Older compilers need this to be public. */
|
||||
struct iter_t
|
||||
{
|
||||
void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
|
||||
bool __more__ () const { return i < c->glyphArray.len; }
|
||||
void __next__ () { i++; }
|
||||
hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return i != o.i; }
|
||||
iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
|
||||
|
||||
private:
|
||||
const struct CoverageFormat1_3 *c;
|
||||
unsigned int i;
|
||||
};
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
||||
|
||||
#include "RangeRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template <typename Types>
|
||||
struct CoverageFormat2_4
|
||||
{
|
||||
friend struct Coverage;
|
||||
|
||||
public:
|
||||
HBUINT16 coverageFormat; /* Format identifier--format = 2 */
|
||||
SortedArray16Of<RangeRecord<Types>>
|
||||
rangeRecord; /* Array of glyph ranges--ordered by
|
||||
* Start GlyphID. rangeCount entries
|
||||
* long */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (4, rangeRecord);
|
||||
|
||||
private:
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (rangeRecord.sanitize (c));
|
||||
}
|
||||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
|
||||
return likely (range.first <= range.last)
|
||||
? (unsigned int) range.value + (glyph_id - range.first)
|
||||
: NOT_COVERED;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
typename Types::large_int ret = 0;
|
||||
for (const auto &r : rangeRecord)
|
||||
ret += r.get_population ();
|
||||
return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c, Iterator glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
|
||||
unsigned num_ranges = 0;
|
||||
hb_codepoint_t last = (hb_codepoint_t) -2;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last + 1 != g)
|
||||
num_ranges++;
|
||||
last = g;
|
||||
}
|
||||
|
||||
if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
|
||||
if (!num_ranges) return_trace (true);
|
||||
|
||||
unsigned count = 0;
|
||||
unsigned range = (unsigned) -1;
|
||||
last = (hb_codepoint_t) -2;
|
||||
unsigned unsorted = false;
|
||||
for (auto g: glyphs)
|
||||
{
|
||||
if (last + 1 != g)
|
||||
{
|
||||
if (unlikely (last != (hb_codepoint_t) -2 && last + 1 > g))
|
||||
unsorted = true;
|
||||
|
||||
range++;
|
||||
rangeRecord.arrayZ[range].first = g;
|
||||
rangeRecord.arrayZ[range].value = count;
|
||||
}
|
||||
rangeRecord.arrayZ[range].last = g;
|
||||
last = g;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (unlikely (unsorted))
|
||||
rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
|
||||
{
|
||||
for (auto g : *glyphs)
|
||||
if (get_coverage (g) != NOT_COVERED)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return hb_any (+ hb_iter (rangeRecord)
|
||||
| hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
|
||||
}
|
||||
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
auto *range = rangeRecord.as_array ().bsearch (index);
|
||||
if (range)
|
||||
return range->intersects (*glyphs);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename IterableOut,
|
||||
hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
|
||||
void intersect_set (const hb_set_t &glyphs, IterableOut&& intersect_glyphs) const
|
||||
{
|
||||
/* Break out of loop for overlapping, broken, tables,
|
||||
* to avoid fuzzer timouts. */
|
||||
hb_codepoint_t last = 0;
|
||||
for (const auto& range : rangeRecord)
|
||||
{
|
||||
if (unlikely (range.first < last))
|
||||
break;
|
||||
last = range.last;
|
||||
for (hb_codepoint_t g = range.first - 1;
|
||||
glyphs.next (&g) && g <= last;)
|
||||
intersect_glyphs << g;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
for (const auto& range: rangeRecord)
|
||||
if (unlikely (!range.collect_coverage (glyphs)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
/* Older compilers need this to be public. */
|
||||
struct iter_t
|
||||
{
|
||||
void init (const CoverageFormat2_4 &c_)
|
||||
{
|
||||
c = &c_;
|
||||
coverage = 0;
|
||||
i = 0;
|
||||
j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
|
||||
if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
|
||||
{
|
||||
/* Broken table. Skip. */
|
||||
i = c->rangeRecord.len;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
bool __more__ () const { return i < c->rangeRecord.len; }
|
||||
void __next__ ()
|
||||
{
|
||||
if (j >= c->rangeRecord[i].last)
|
||||
{
|
||||
i++;
|
||||
if (__more__ ())
|
||||
{
|
||||
unsigned int old = coverage;
|
||||
j = c->rangeRecord.arrayZ[i].first;
|
||||
coverage = c->rangeRecord.arrayZ[i].value;
|
||||
if (unlikely (coverage != old + 1))
|
||||
{
|
||||
/* Broken table. Skip. Important to avoid DoS.
|
||||
* Also, our callers depend on coverage being
|
||||
* consecutive and monotonically increasing,
|
||||
* ie. iota(). */
|
||||
i = c->rangeRecord.len;
|
||||
j = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
j = 0;
|
||||
return;
|
||||
}
|
||||
coverage++;
|
||||
j++;
|
||||
}
|
||||
hb_codepoint_t get_glyph () const { return j; }
|
||||
bool operator != (const iter_t& o) const
|
||||
{ return i != o.i || j != o.j; }
|
||||
iter_t __end__ () const
|
||||
{
|
||||
iter_t it;
|
||||
it.init (*c);
|
||||
it.i = c->rangeRecord.len;
|
||||
it.j = 0;
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
const struct CoverageFormat2_4 *c;
|
||||
unsigned int i, coverage;
|
||||
hb_codepoint_t j;
|
||||
};
|
||||
private:
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright © 2007,2008,2009 Red Hat, Inc.
|
||||
* Copyright © 2010,2012 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Red Hat Author(s): Behdad Esfahbod
|
||||
* Google Author(s): Behdad Esfahbod, Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
|
||||
#define OT_LAYOUT_COMMON_RANGERECORD_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
||||
template <typename Types>
|
||||
struct RangeRecord
|
||||
{
|
||||
typename Types::HBGlyphID first; /* First GlyphID in the range */
|
||||
typename Types::HBGlyphID last; /* Last GlyphID in the range */
|
||||
HBUINT16 value; /* Value */
|
||||
|
||||
DEFINE_SIZE_STATIC (2 + 2 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < first ? -1 : g <= last ? 0 : +1; }
|
||||
|
||||
HB_INTERNAL static int cmp_range (const void *pa, const void *pb) {
|
||||
const RangeRecord *a = (const RangeRecord *) pa;
|
||||
const RangeRecord *b = (const RangeRecord *) pb;
|
||||
if (a->first < b->first) return -1;
|
||||
if (a->first > b->first) return +1;
|
||||
if (a->last < b->last) return -1;
|
||||
if (a->last > b->last) return +1;
|
||||
if (a->value < b->value) return -1;
|
||||
if (a->value > b->value) return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned get_population () const
|
||||
{
|
||||
if (unlikely (last < first)) return 0;
|
||||
return (last - first + 1);
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t &glyphs) const
|
||||
{ return glyphs.intersects (first, last); }
|
||||
|
||||
template <typename set_t>
|
||||
bool collect_coverage (set_t *glyphs) const
|
||||
{ return glyphs->add_range (first, last); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(garretrieger): This was previously implemented using
|
||||
// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
|
||||
// but that only works when there is only a single namespace level.
|
||||
// The macro should probably be fixed so it can work in this situation.
|
||||
extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
|
||||
template <typename Spec>
|
||||
struct Null<OT::Layout::Common::RangeRecord<Spec>> {
|
||||
static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
|
||||
return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
|
||||
+1060
File diff suppressed because it is too large
Load Diff
+84
@@ -0,0 +1,84 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHOR_HH
|
||||
|
||||
#include "AnchorFormat1.hh"
|
||||
#include "AnchorFormat2.hh"
|
||||
#include "AnchorFormat3.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct Anchor
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
AnchorFormat1 format1;
|
||||
AnchorFormat2 format2;
|
||||
AnchorFormat3 format3;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format.v);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!u.format.v.sanitize (c)) return_trace (false);
|
||||
hb_barrier ();
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.sanitize (c));
|
||||
case 2: return_trace (u.format2.sanitize (c));
|
||||
case 3: return_trace (u.format3.sanitize (c));
|
||||
default:return_trace (true);
|
||||
}
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
|
||||
float *x, float *y) const
|
||||
{
|
||||
*x = *y = 0;
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
|
||||
case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
|
||||
case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
case 2:
|
||||
if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
// AnchorFormat 2 just containins extra hinting information, so
|
||||
// if hints are being dropped convert to format 1.
|
||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
|
||||
}
|
||||
return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
|
||||
case 3: return_trace (u.format3.subset (c));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
switch (u.format.v) {
|
||||
case 1: case 2:
|
||||
return;
|
||||
case 3:
|
||||
u.format3.collect_variation_indices (c);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHOR_HH
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat1
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
}
|
||||
|
||||
AnchorFormat1* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
AnchorFormat1* out = c->embed<AnchorFormat1> (this);
|
||||
if (!out) return_trace (out);
|
||||
out->format = 1;
|
||||
return_trace (out);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat2
|
||||
{
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
HBUINT16 anchorPoint; /* Index to glyph contour point */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (8);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
|
||||
#ifdef HB_NO_HINTING
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
unsigned int x_ppem = font->x_ppem;
|
||||
unsigned int y_ppem = font->y_ppem;
|
||||
hb_position_t cx = 0, cy = 0;
|
||||
bool ret;
|
||||
|
||||
ret = (x_ppem || y_ppem) &&
|
||||
font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
|
||||
*x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
|
||||
*y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
|
||||
}
|
||||
|
||||
AnchorFormat2* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (c->embed<AnchorFormat2> (this));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
|
||||
@@ -0,0 +1,123 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorFormat3
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 3 */
|
||||
FWORD xCoordinate; /* Horizontal value--in design units */
|
||||
FWORD yCoordinate; /* Vertical value--in design units */
|
||||
Offset16To<Device>
|
||||
xDeviceTable; /* Offset to Device table for X
|
||||
* coordinate-- from beginning of
|
||||
* Anchor table (may be NULL) */
|
||||
Offset16To<Device>
|
||||
yDeviceTable; /* Offset to Device table for Y
|
||||
* coordinate-- from beginning of
|
||||
* Anchor table (may be NULL) */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (10);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!c->check_struct (this))) return_trace (false);
|
||||
|
||||
return_trace (xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
|
||||
}
|
||||
|
||||
void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
|
||||
float *x, float *y) const
|
||||
{
|
||||
hb_font_t *font = c->font;
|
||||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
|
||||
if ((font->x_ppem || font->has_nonzero_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
|
||||
{
|
||||
hb_barrier ();
|
||||
*x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
|
||||
}
|
||||
if ((font->y_ppem || font->has_nonzero_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
|
||||
{
|
||||
hb_barrier ();
|
||||
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->embed (format))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false);
|
||||
|
||||
unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
if (x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
{
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
|
||||
x_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
|
||||
if (y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
{
|
||||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (y_varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
|
||||
y_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
{
|
||||
if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool no_downgrade = (!xDeviceTable.is_null () && !(this+xDeviceTable).is_variation_device ()) ||
|
||||
x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX ||
|
||||
y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX ||
|
||||
(!yDeviceTable.is_null () && !(this+yDeviceTable).is_variation_device ());
|
||||
|
||||
if (!no_downgrade)
|
||||
return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
||||
if (!c->serializer->embed (yDeviceTable)) return_trace (false);
|
||||
|
||||
out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, &c->plan->layout_variation_idx_delta_map);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
(this+xDeviceTable).collect_variation_indices (c);
|
||||
(this+yDeviceTable).collect_variation_indices (c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
|
||||
#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct AnchorMatrix
|
||||
{
|
||||
HBUINT16 rows; /* Number of rows */
|
||||
UnsizedArrayOf<Offset16To<Anchor, AnchorMatrix>>
|
||||
matrixZ; /* Matrix of offsets to Anchor tables--
|
||||
* from beginning of AnchorMatrix table */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, matrixZ);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!c->check_struct (this)) return_trace (false);
|
||||
hb_barrier ();
|
||||
if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
|
||||
unsigned int count = rows * cols;
|
||||
if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
hb_barrier ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!matrixZ[i].sanitize (c, this)) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
const Anchor& get_anchor (hb_ot_apply_context_t *c,
|
||||
unsigned int row, unsigned int col,
|
||||
unsigned int cols, bool *found) const
|
||||
{
|
||||
*found = false;
|
||||
if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
|
||||
auto &offset = matrixZ[row * cols + col];
|
||||
if (unlikely (!offset.sanitize (&c->sanitizer, this))) return Null (Anchor);
|
||||
hb_barrier ();
|
||||
*found = !offset.is_null ();
|
||||
return this+offset;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
Iterator index_iter) const
|
||||
{
|
||||
for (unsigned i : index_iter)
|
||||
(this+matrixZ[i]).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
unsigned num_rows,
|
||||
Iterator index_iter) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
|
||||
if (!index_iter) return_trace (false);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
out->rows = num_rows;
|
||||
for (const unsigned i : index_iter)
|
||||
{
|
||||
auto *offset = c->serializer->embed (matrixZ[i]);
|
||||
if (!offset) return_trace (false);
|
||||
offset->serialize_subset (c, matrixZ[i], this);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool offset_is_null (unsigned row, unsigned col, unsigned num_cols) const
|
||||
{
|
||||
if (unlikely (row >= rows || col >= num_cols)) return true;
|
||||
auto &offset = matrixZ[row * num_cols + col];
|
||||
return offset.is_null ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ChainContextPos : ChainContext {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#ifndef OT_LAYOUT_GPOS_COMMON_HH
|
||||
#define OT_LAYOUT_GPOS_COMMON_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
enum attach_type_t {
|
||||
ATTACH_TYPE_NONE = 0X00,
|
||||
|
||||
/* Each attachment should be either a mark or a cursive; can't be both. */
|
||||
ATTACH_TYPE_MARK = 0X01,
|
||||
ATTACH_TYPE_CURSIVE = 0X02,
|
||||
};
|
||||
|
||||
/* buffer **position** var allocations */
|
||||
#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
|
||||
#define attach_type() var.u8[2] /* attachment type */
|
||||
/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
|
||||
|
||||
template<typename Iterator, typename SrcLookup>
|
||||
static void SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned new_format);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_COMMON_HH
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ContextPos : Context {};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
|
||||
|
||||
#include "CursivePosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct CursivePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
CursivePosFormat1 format1;
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */
|
||||
@@ -0,0 +1,332 @@
|
||||
#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
|
||||
|
||||
#include "Anchor.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct EntryExitRecord
|
||||
{
|
||||
friend struct CursivePosFormat1;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const struct CursivePosFormat1 *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const struct CursivePosFormat1 *src_base) const
|
||||
{
|
||||
(src_base+entryAnchor).collect_variation_indices (c);
|
||||
(src_base+exitAnchor).collect_variation_indices (c);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const struct CursivePosFormat1 *src_base) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
ret |= out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
|
||||
ret |= out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
protected:
|
||||
Offset16To<Anchor, struct CursivePosFormat1>
|
||||
entryAnchor; /* Offset to EntryAnchor table--from
|
||||
* beginning of CursivePos
|
||||
* subtable--may be NULL */
|
||||
Offset16To<Anchor, struct CursivePosFormat1>
|
||||
exitAnchor; /* Offset to ExitAnchor table--from
|
||||
* beginning of CursivePos
|
||||
* subtable--may be NULL */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
static inline void
|
||||
reverse_cursive_minor_offset (hb_glyph_position_t *pos,
|
||||
unsigned int len,
|
||||
unsigned int i,
|
||||
hb_direction_t direction,
|
||||
unsigned int new_parent)
|
||||
{
|
||||
int chain = pos[i].attach_chain(), type = pos[i].attach_type();
|
||||
if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
|
||||
return;
|
||||
|
||||
pos[i].attach_chain() = 0;
|
||||
|
||||
unsigned int j = (int) i + chain;
|
||||
|
||||
if (unlikely (j >= len))
|
||||
return;
|
||||
|
||||
/* Stop if we see new parent in the chain. */
|
||||
if (j == new_parent)
|
||||
return;
|
||||
|
||||
int16_t reversed_chain = -chain;
|
||||
/* The old edge was cleared above; if the reversed distance truncates,
|
||||
* keep it detached instead of storing a poisoned chain.
|
||||
*/
|
||||
if (unlikely (reversed_chain != -chain))
|
||||
return;
|
||||
|
||||
reverse_cursive_minor_offset (pos, len, j, direction, new_parent);
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
pos[j].y_offset = -pos[i].y_offset;
|
||||
else
|
||||
pos[j].x_offset = -pos[i].x_offset;
|
||||
|
||||
pos[j].attach_chain() = reversed_chain;
|
||||
pos[j].attach_type() = type;
|
||||
}
|
||||
|
||||
|
||||
struct CursivePosFormat1
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
Array16Of<EntryExitRecord>
|
||||
entryExitRecord; /* Array of EntryExit records--in
|
||||
* Coverage Index order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, entryExitRecord);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (unlikely (!coverage.sanitize (c, this)))
|
||||
return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (entryExitRecord.sanitize_shallow (c));
|
||||
else
|
||||
return_trace (entryExitRecord.sanitize (c, this));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, entryExitRecord)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
|
||||
if (!this_record.entryAnchor ||
|
||||
unlikely (!this_record.entryAnchor.sanitize (&c->sanitizer, this))) return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_from;
|
||||
if (unlikely (!skippy_iter.prev (&unsafe_from)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
|
||||
if (!prev_record.exitAnchor ||
|
||||
unlikely (!prev_record.exitAnchor.sanitize (&c->sanitizer, this)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
hb_barrier ();
|
||||
|
||||
unsigned int i = skippy_iter.idx;
|
||||
unsigned int j = buffer->idx;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attaching glyph at %u to glyph at %u",
|
||||
i, j);
|
||||
}
|
||||
|
||||
buffer->unsafe_to_break (i, j + 1);
|
||||
float entry_x, entry_y, exit_x, exit_y;
|
||||
(this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
|
||||
(this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
|
||||
|
||||
hb_glyph_position_t *pos = buffer->pos;
|
||||
|
||||
hb_position_t d;
|
||||
/* Main-direction adjustment */
|
||||
switch (c->direction) {
|
||||
case HB_DIRECTION_LTR:
|
||||
pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
|
||||
|
||||
d = roundf (entry_x) + pos[j].x_offset;
|
||||
pos[j].x_advance -= d;
|
||||
pos[j].x_offset -= d;
|
||||
break;
|
||||
case HB_DIRECTION_RTL:
|
||||
d = roundf (exit_x) + pos[i].x_offset;
|
||||
pos[i].x_advance -= d;
|
||||
pos[i].x_offset -= d;
|
||||
|
||||
pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_TTB:
|
||||
pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
|
||||
|
||||
d = roundf (entry_y) + pos[j].y_offset;
|
||||
pos[j].y_advance -= d;
|
||||
pos[j].y_offset -= d;
|
||||
break;
|
||||
case HB_DIRECTION_BTT:
|
||||
d = roundf (exit_y) + pos[i].y_offset;
|
||||
pos[i].y_advance -= d;
|
||||
pos[i].y_offset -= d;
|
||||
|
||||
pos[j].y_advance = roundf (entry_y);
|
||||
break;
|
||||
case HB_DIRECTION_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cross-direction adjustment */
|
||||
|
||||
/* We attach child to parent (think graph theory and rooted trees whereas
|
||||
* the root stays on baseline and each node aligns itself against its
|
||||
* parent.
|
||||
*
|
||||
* Optimize things for the case of RightToLeft, as that's most common in
|
||||
* Arabic. */
|
||||
unsigned int child = i;
|
||||
unsigned int parent = j;
|
||||
hb_position_t x_offset = roundf (entry_x - exit_x);
|
||||
hb_position_t y_offset = roundf (entry_y - exit_y);
|
||||
if (!(c->lookup_props & LookupFlag::RightToLeft))
|
||||
{
|
||||
unsigned int k = child;
|
||||
child = parent;
|
||||
parent = k;
|
||||
x_offset = -x_offset;
|
||||
y_offset = -y_offset;
|
||||
}
|
||||
|
||||
/* If child was already connected to someone else, walk through its old
|
||||
* chain and reverse the link direction, such that the whole tree of its
|
||||
* previous connection now attaches to new parent. Watch out for case
|
||||
* where new parent is on the path from old chain...
|
||||
*/
|
||||
reverse_cursive_minor_offset (pos, buffer->len, child, c->direction, parent);
|
||||
|
||||
pos[child].attach_chain() = (int) parent - (int) child;
|
||||
if (pos[child].attach_chain() != (int) parent - (int) child)
|
||||
{
|
||||
pos[child].attach_chain() = 0;
|
||||
goto overflow;
|
||||
}
|
||||
pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
|
||||
pos[child].y_offset = y_offset;
|
||||
else
|
||||
pos[child].x_offset = x_offset;
|
||||
|
||||
/* If parent was attached to child, separate them.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/2469
|
||||
*/
|
||||
if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
|
||||
{
|
||||
pos[parent].attach_chain() = 0;
|
||||
if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
|
||||
pos[parent].y_offset = 0;
|
||||
else
|
||||
pos[parent].x_offset = 0;
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"cursive attached glyph at %u to glyph at %u",
|
||||
i, j);
|
||||
}
|
||||
|
||||
overflow:
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_subset_context_t *c,
|
||||
Iterator it,
|
||||
const struct CursivePosFormat1 *src_base)
|
||||
{
|
||||
if (unlikely (!c->serializer->extend_min ((*this)))) return;
|
||||
this->format = 1;
|
||||
this->entryExitRecord.len = it.len ();
|
||||
|
||||
for (const EntryExitRecord& entry_record : + it
|
||||
| hb_map (hb_second))
|
||||
entry_record.subset (c, src_base);
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c->serializer, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, entryExitRecord)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
|
||||
{ return hb_pair (glyph_map[p.first], p.second);})
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
out->serialize (c, it, this);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
|
||||
#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct ExtensionPos : Extension<ExtensionPos>
|
||||
{
|
||||
typedef struct PosLookupSubTable SubTable;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
#ifndef OT_LAYOUT_GPOS_GPOS_HH
|
||||
#define OT_LAYOUT_GPOS_GPOS_HH
|
||||
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
#include "Common.hh"
|
||||
#include "PosLookup.hh"
|
||||
|
||||
namespace OT {
|
||||
|
||||
using Layout::GPOS_impl::PosLookup;
|
||||
|
||||
namespace Layout {
|
||||
|
||||
static void
|
||||
propagate_attachment_offsets (hb_glyph_position_t *pos,
|
||||
unsigned int len,
|
||||
unsigned int i,
|
||||
hb_direction_t direction,
|
||||
unsigned nesting_level = HB_MAX_NESTING_LEVEL);
|
||||
|
||||
/*
|
||||
* GPOS -- Glyph Positioning
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
|
||||
*/
|
||||
|
||||
struct GPOS : GSUBGPOS
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
|
||||
|
||||
using Lookup = PosLookup;
|
||||
|
||||
const PosLookup& get_lookup (unsigned int i) const
|
||||
{ return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
|
||||
|
||||
static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
|
||||
static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
|
||||
static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<PosLookup> (&l);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (GSUBGPOS::sanitize<PosLookup> (c));
|
||||
}
|
||||
|
||||
HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
|
||||
hb_face_t *face) const;
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
|
||||
{
|
||||
if (!c->gpos_lookups->has (i)) continue;
|
||||
const PosLookup &l = get_lookup (i);
|
||||
l.dispatch (c);
|
||||
}
|
||||
}
|
||||
|
||||
void closure_lookups (hb_face_t *face,
|
||||
const hb_set_t *glyphs,
|
||||
hb_set_t *lookup_indexes /* IN/OUT */) const
|
||||
{ GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
|
||||
|
||||
typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
propagate_attachment_offsets (hb_glyph_position_t *pos,
|
||||
unsigned int len,
|
||||
unsigned int i,
|
||||
hb_direction_t direction,
|
||||
unsigned nesting_level)
|
||||
{
|
||||
/* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
|
||||
* offset of glyph they are attached to. */
|
||||
int chain = pos[i].attach_chain();
|
||||
int type = pos[i].attach_type();
|
||||
|
||||
pos[i].attach_chain() = 0;
|
||||
|
||||
unsigned int j = (int) i + chain;
|
||||
|
||||
if (unlikely (j >= len))
|
||||
return;
|
||||
|
||||
if (unlikely (!nesting_level))
|
||||
return;
|
||||
|
||||
if (pos[j].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
|
||||
|
||||
assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
|
||||
|
||||
if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
|
||||
{
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
pos[i].y_offset += pos[j].y_offset;
|
||||
else
|
||||
pos[i].x_offset += pos[j].x_offset;
|
||||
}
|
||||
else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
|
||||
{
|
||||
pos[i].x_offset += pos[j].x_offset;
|
||||
pos[i].y_offset += pos[j].y_offset;
|
||||
|
||||
// i is the position of the mark; j is the base.
|
||||
if (j < i)
|
||||
{
|
||||
/* This is the common case: mark follows base.
|
||||
* And currently the only way in OpenType. */
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = j; k < i; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = j + 1; k < i + 1; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
}
|
||||
else // j > i
|
||||
{
|
||||
/* This can happen with `kerx`: a mark attaching
|
||||
* to a base after it in the logical order. */
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
for (unsigned int k = i; k < j; k++) {
|
||||
pos[i].x_offset += pos[k].x_advance;
|
||||
pos[i].y_offset += pos[k].y_advance;
|
||||
}
|
||||
else
|
||||
for (unsigned int k = i + 1; k < j + 1; k++) {
|
||||
pos[i].x_offset -= pos[k].x_advance;
|
||||
pos[i].y_offset -= pos[k].y_advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
|
||||
{
|
||||
unsigned int count = buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
|
||||
{
|
||||
//_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
|
||||
{
|
||||
_hb_buffer_assert_gsubgpos_vars (buffer);
|
||||
|
||||
unsigned int len;
|
||||
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
|
||||
hb_direction_t direction = buffer->props.direction;
|
||||
|
||||
/* Handle attachments */
|
||||
if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
|
||||
{
|
||||
auto *pos = buffer->pos;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5514
|
||||
if (HB_DIRECTION_IS_FORWARD (direction))
|
||||
{
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (pos[i].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
} else {
|
||||
for (unsigned i = len; i-- > 0; )
|
||||
if (pos[i].attach_chain())
|
||||
propagate_attachment_offsets (pos, len, i, direction);
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely (font->slant_xy) &&
|
||||
HB_DIRECTION_IS_HORIZONTAL (direction))
|
||||
{
|
||||
/* Slanting shaping results is only supported for horizontal text,
|
||||
* as it gets weird otherwise. */
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (unlikely (pos[i].y_offset))
|
||||
pos[i].x_offset += roundf (font->slant_xy * pos[i].y_offset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
|
||||
GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_GPOS_HH */
|
||||
@@ -0,0 +1,68 @@
|
||||
#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH
|
||||
#define OT_LAYOUT_GPOS_LIGATUREARRAY_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
typedef AnchorMatrix LigatureAttach; /* component-major--
|
||||
* in order of writing direction--,
|
||||
* mark-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
|
||||
struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
||||
{
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
Iterator coverage,
|
||||
unsigned class_count,
|
||||
const hb_map_t *klass_mapping,
|
||||
hb_sorted_vector_t<hb_codepoint_t> &new_coverage /* OUT */) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
|
||||
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
for (const auto _ : + hb_zip (coverage, *this)
|
||||
| hb_filter (glyph_map, hb_first))
|
||||
{
|
||||
const LigatureAttach& src = (this + _.second);
|
||||
bool non_empty = + hb_range (src.rows * class_count)
|
||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||
| hb_map ([&] (const unsigned index) { return !src.offset_is_null (index / class_count, index % class_count, class_count); })
|
||||
| hb_any;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
auto *matrix = out->serialize_append (c->serializer);
|
||||
if (unlikely (!matrix)) return_trace (false);
|
||||
|
||||
auto indexes =
|
||||
+ hb_range (src.rows * class_count)
|
||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||
;
|
||||
ret |= matrix->serialize_subset (c,
|
||||
_.second,
|
||||
this,
|
||||
src.rows,
|
||||
indexes);
|
||||
|
||||
hb_codepoint_t new_gid = glyph_map.get (_.first);
|
||||
new_coverage.push (new_gid);
|
||||
}
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_HH */
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
|
||||
#define OT_LAYOUT_GPOS_MARKARRAY_HH
|
||||
|
||||
#include "AnchorMatrix.hh"
|
||||
#include "MarkRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (Array16Of<MarkRecord>::sanitize (c, this));
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c,
|
||||
unsigned int mark_index, unsigned int glyph_index,
|
||||
const AnchorMatrix &anchors, unsigned int class_count,
|
||||
unsigned int glyph_pos) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
|
||||
unsigned int mark_class = record.klass;
|
||||
|
||||
const Anchor& mark_anchor = this + record.markAnchor;
|
||||
bool found;
|
||||
const Anchor& glyph_anchor = anchors.get_anchor (c, glyph_index, mark_class, class_count, &found);
|
||||
/* If this subtable doesn't have an anchor for this base and this class,
|
||||
* return false such that the subsequent subtables have a chance at it. */
|
||||
if (unlikely (!found)) return_trace (false);
|
||||
|
||||
float mark_x, mark_y, base_x, base_y;
|
||||
|
||||
buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
|
||||
mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
|
||||
glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attaching mark glyph at %u to glyph at %u",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
hb_glyph_position_t &o = buffer->cur_pos();
|
||||
o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
|
||||
if (o.attach_chain() != (int) glyph_pos - (int) buffer->idx)
|
||||
{
|
||||
o.attach_chain() = 0;
|
||||
goto overflow;
|
||||
}
|
||||
o.attach_type() = ATTACH_TYPE_MARK;
|
||||
o.x_offset = roundf (base_x - mark_x);
|
||||
o.y_offset = roundf (base_y - mark_y);
|
||||
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"attached mark glyph at %u to glyph at %u",
|
||||
c->buffer->idx, glyph_pos);
|
||||
}
|
||||
|
||||
overflow:
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool subset (hb_subset_context_t *c,
|
||||
Iterator coverage,
|
||||
const hb_map_t *klass_mapping) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
|
||||
auto* out = c->serializer->start_embed (this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (coverage, this->iter ())
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
bool ret = false;
|
||||
unsigned new_length = 0;
|
||||
for (const auto& mark_record : mark_iter) {
|
||||
ret |= mark_record.subset (c, this, klass_mapping);
|
||||
new_length++;
|
||||
}
|
||||
|
||||
if (unlikely (!c->serializer->check_assign (out->len, new_length,
|
||||
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
HB_INTERNAL inline
|
||||
void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
|
||||
const MarkArray &mark_array,
|
||||
const hb_set_t &glyphset,
|
||||
hb_map_t* klass_mapping /* INOUT */)
|
||||
{
|
||||
hb_set_t orig_classes;
|
||||
|
||||
+ hb_zip (mark_coverage, mark_array)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (&MarkRecord::get_class)
|
||||
| hb_sink (orig_classes)
|
||||
;
|
||||
|
||||
unsigned idx = 0;
|
||||
for (auto klass : orig_classes.iter ())
|
||||
{
|
||||
if (klass_mapping->has (klass)) continue;
|
||||
klass_mapping->set (klass, idx);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKBASEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKBASEPOS_HH
|
||||
|
||||
#include "MarkBasePosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkBasePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkBasePosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkBasePosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKBASEPOS_HH */
|
||||
@@ -0,0 +1,250 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
|
||||
|
||||
#include "MarkArray.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef AnchorMatrix BaseArray; /* base-major--
|
||||
* in order of BaseCoverage Index--,
|
||||
* mark-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
template <typename Types>
|
||||
struct MarkBasePosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to MarkCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
baseCoverage; /* Offset to BaseCoverage table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
HBUINT16 classCount; /* Number of classes defined for marks */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
typename Types::template OffsetTo<BaseArray>
|
||||
baseArray; /* Offset to BaseArray table--from
|
||||
* beginning of MarkBasePos subtable */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
markCoverage.sanitize (c, this) &&
|
||||
baseCoverage.sanitize (c, this) &&
|
||||
markArray.sanitize (c, this) &&
|
||||
baseArray.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+baseCoverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned basecount = (this+baseArray).rows;
|
||||
auto base_iter =
|
||||
+ hb_zip (this+baseCoverage, hb_range (basecount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
for (const unsigned row : base_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (base_indexes)
|
||||
;
|
||||
}
|
||||
(this+baseArray).collect_variation_indices (c, base_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||
|
||||
static inline bool accept (hb_buffer_t *buffer, unsigned idx)
|
||||
{
|
||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||
* Reject others...
|
||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||
return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
|
||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
|
||||
(idx == 0 ||
|
||||
_hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
|
||||
!_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
|
||||
);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph.
|
||||
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/4124
|
||||
if (!accept (buffer, j - 1) &&
|
||||
NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
|
||||
match = skippy_iter.SKIP;
|
||||
}
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
|
||||
|
||||
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
if (base_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ mark_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||
(this+markCoverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
unsigned basecount = (this+baseArray).rows;
|
||||
auto base_iter =
|
||||
+ hb_zip (this+baseCoverage, hb_range (basecount))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
hb_sorted_vector_t<unsigned> base_indexes;
|
||||
auto &base_array = (this+baseArray);
|
||||
for (const auto _ : + base_iter)
|
||||
{
|
||||
unsigned row = _.second;
|
||||
bool non_empty = + hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return !base_array.offset_is_null (row, col, (unsigned) classCount); })
|
||||
| hb_any
|
||||
;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
hb_codepoint_t new_g = glyph_map.get ( _.first);
|
||||
new_coverage.push (new_g);
|
||||
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (base_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
if (!new_coverage) return_trace (false);
|
||||
if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->baseArray.serialize_subset (c, baseArray, this,
|
||||
new_coverage.length,
|
||||
base_indexes.iter ()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH */
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKLIGPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKLIGPOS_HH
|
||||
|
||||
#include "MarkLigPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkLigPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkLigPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkLigPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKLIGPOS_HH */
|
||||
@@ -0,0 +1,218 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
|
||||
|
||||
#include "LigatureArray.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct MarkLigPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
markCoverage; /* Offset to Mark Coverage table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
ligatureCoverage; /* Offset to Ligature Coverage
|
||||
* table--from beginning of MarkLigPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
markArray; /* Offset to MarkArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
typename Types::template OffsetTo<LigatureArray>
|
||||
ligatureArray; /* Offset to LigatureArray table--from
|
||||
* beginning of MarkLigPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
markCoverage.sanitize (c, this) &&
|
||||
ligatureCoverage.sanitize (c, this) &&
|
||||
markArray.sanitize (c, this) &&
|
||||
ligatureArray.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+ligatureCoverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned ligcount = (this+ligatureArray).len;
|
||||
auto lig_iter =
|
||||
+ hb_zip (this+ligatureCoverage, hb_range (ligcount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
const LigatureArray& lig_array = this+ligatureArray;
|
||||
for (const unsigned i : lig_iter)
|
||||
{
|
||||
hb_sorted_vector_t<unsigned> lig_indexes;
|
||||
unsigned row_count = lig_array[i].rows;
|
||||
for (unsigned row : + hb_range (row_count))
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (lig_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
|
||||
|
||||
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
if (lig_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
const LigatureArray& lig_array = this+ligatureArray;
|
||||
const LigatureAttach& lig_attach = lig_array[lig_index];
|
||||
|
||||
/* Find component to attach to */
|
||||
unsigned int comp_count = lig_attach.rows;
|
||||
if (unlikely (!comp_count))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
/* We must now check whether the ligature ID of the current mark glyph
|
||||
* is identical to the ligature ID of the found ligature. If yes, we
|
||||
* can directly use the component index. If not, we attach the mark
|
||||
* glyph to the last component of the ligature. */
|
||||
unsigned int comp_index;
|
||||
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[idx]);
|
||||
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
||||
comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
|
||||
else
|
||||
comp_index = comp_count - 1;
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = c->plan->glyph_map_gsub;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark_iter =
|
||||
+ hb_zip (this+markCoverage, this+markArray)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
auto new_mark_coverage =
|
||||
+ mark_iter
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
;
|
||||
|
||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||
(this+markCoverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_lig_coverage;
|
||||
if (!out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
||||
hb_iter (this+ligatureCoverage),
|
||||
classCount, &klass_mapping, new_lig_coverage))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->ligatureCoverage.serialize_serialize (c->serializer, new_lig_coverage.iter ()));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH */
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH
|
||||
#define OT_LAYOUT_GPOS_MARKMARKPOS_HH
|
||||
|
||||
#include "MarkMarkPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkMarkPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
MarkMarkPosFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
MarkMarkPosFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */
|
||||
@@ -0,0 +1,239 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
|
||||
|
||||
#include "MarkMarkPosFormat1.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef AnchorMatrix Mark2Array; /* mark2-major--
|
||||
* in order of Mark2Coverage Index--,
|
||||
* mark1-minor--
|
||||
* ordered by class--zero-based. */
|
||||
|
||||
template <typename Types>
|
||||
struct MarkMarkPosFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark1Coverage; /* Offset to Combining Mark1 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
mark2Coverage; /* Offset to Combining Mark2 Coverage
|
||||
* table--from beginning of MarkMarkPos
|
||||
* subtable */
|
||||
HBUINT16 classCount; /* Number of defined mark classes */
|
||||
typename Types::template OffsetTo<MarkArray>
|
||||
mark1Array; /* Offset to Mark1Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
typename Types::template OffsetTo<Mark2Array>
|
||||
mark2Array; /* Offset to Mark2Array table--from
|
||||
* beginning of MarkMarkPos subtable */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + 4 * Types::size);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
mark1Coverage.sanitize (c, this) &&
|
||||
mark2Coverage.sanitize (c, this) &&
|
||||
mark1Array.sanitize (c, this) &&
|
||||
hb_barrier () &&
|
||||
mark2Array.sanitize (c, this, (unsigned int) classCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+mark1Coverage).intersects (glyphs) &&
|
||||
(this+mark2Coverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+mark1Coverage, this+mark1Array)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
|
||||
;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
|
||||
|
||||
unsigned mark2_count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2_count))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
for (const unsigned row : mark2_iter)
|
||||
{
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (mark2_indexes)
|
||||
;
|
||||
}
|
||||
(this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+mark1Coverage; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark1_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* now we search backwards for a suitable mark glyph until a non-mark glyph */
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
|
||||
unsigned unsafe_from;
|
||||
if (unlikely (!skippy_iter.prev (&unsafe_from)))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int j = skippy_iter.idx;
|
||||
|
||||
unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||
unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
|
||||
unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
|
||||
|
||||
if (likely (id1 == id2))
|
||||
{
|
||||
if (id1 == 0) /* Marks belonging to the same base. */
|
||||
goto good;
|
||||
else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
|
||||
goto good;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If ligature ids don't match, it may be the case that one of the marks
|
||||
* itself is a ligature. In which case match. */
|
||||
if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
|
||||
goto good;
|
||||
}
|
||||
|
||||
/* Didn't match. */
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
|
||||
good:
|
||||
unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
|
||||
if (mark2_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass_mapping;
|
||||
Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
|
||||
|
||||
if (!klass_mapping.get_population ()) return_trace (false);
|
||||
out->classCount = klass_mapping.get_population ();
|
||||
|
||||
auto mark1_iter =
|
||||
+ hb_zip (this+mark1Coverage, this+mark1Array)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ mark1_iter
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
|
||||
(this+mark1Coverage).iter (),
|
||||
&klass_mapping)))
|
||||
return_trace (false);
|
||||
|
||||
unsigned mark2count = (this+mark2Array).rows;
|
||||
auto mark2_iter =
|
||||
+ hb_zip (this+mark2Coverage, hb_range (mark2count))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
;
|
||||
|
||||
new_coverage.reset ();
|
||||
hb_sorted_vector_t<unsigned> mark2_indexes;
|
||||
auto &mark2_array = (this+mark2Array);
|
||||
for (const auto _ : + mark2_iter)
|
||||
{
|
||||
unsigned row = _.second;
|
||||
|
||||
bool non_empty = + hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
|
||||
| hb_any
|
||||
;
|
||||
|
||||
if (!non_empty) continue;
|
||||
|
||||
hb_codepoint_t new_g = glyph_map.get ( _.first);
|
||||
new_coverage.push (new_g);
|
||||
|
||||
+ hb_range ((unsigned) classCount)
|
||||
| hb_filter (klass_mapping)
|
||||
| hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
|
||||
| hb_sink (mark2_indexes)
|
||||
;
|
||||
}
|
||||
|
||||
if (!new_coverage) return_trace (false);
|
||||
if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
|
||||
mark2_iter.len (),
|
||||
mark2_indexes.iter ()));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */
|
||||
@@ -0,0 +1,51 @@
|
||||
#ifndef OT_LAYOUT_GPOS_MARKRECORD_HH
|
||||
#define OT_LAYOUT_GPOS_MARKRECORD_HH
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct MarkRecord
|
||||
{
|
||||
friend struct MarkArray;
|
||||
|
||||
public:
|
||||
HBUINT16 klass; /* Class defined for this mark */
|
||||
Offset16To<Anchor>
|
||||
markAnchor; /* Offset to Anchor table--from
|
||||
* beginning of MarkArray table */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
|
||||
unsigned get_class () const { return (unsigned) klass; }
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const void *src_base,
|
||||
const hb_map_t *klass_mapping) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->klass = klass_mapping->get (klass);
|
||||
return_trace (out->markAnchor.serialize_subset (c, markAnchor, src_base));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const void *src_base) const
|
||||
{
|
||||
(src_base+markAnchor).collect_variation_indices (c);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_MARKRECORD_HH */
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOS_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOS_HH
|
||||
|
||||
#include "PairPosFormat1.hh"
|
||||
#include "PairPosFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PairPos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
PairPosFormat1_3<SmallTypes> format1;
|
||||
PairPosFormat2_4<SmallTypes> format2;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
PairPosFormat1_3<MediumTypes> format3;
|
||||
PairPosFormat2_4<MediumTypes> format4;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
public:
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
|
||||
case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOS_HH
|
||||
@@ -0,0 +1,254 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
||||
|
||||
#include "PairSet.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairPosFormat1_3
|
||||
{
|
||||
using PairSet = GPOS_impl::PairSet<Types>;
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat[2]; /* [0] Defines the types of data in
|
||||
* ValueRecord1--for the first glyph
|
||||
* in the pair--may be zero (0) */
|
||||
/* [1] Defines the types of data in
|
||||
* ValueRecord2--for the second glyph
|
||||
* in the pair--may be zero (0) */
|
||||
Array16Of<typename Types::template OffsetTo<PairSet>>
|
||||
pairSet; /* Array of PairSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (!c->check_struct (this)) return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
unsigned int len1 = valueFormat[0].get_len ();
|
||||
unsigned int len2 = valueFormat[1].get_len ();
|
||||
typename PairSet::sanitize_closure_t closure =
|
||||
{
|
||||
valueFormat,
|
||||
len1,
|
||||
PairSet::get_size (len1, len2)
|
||||
};
|
||||
|
||||
return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
auto &cov = this+coverage;
|
||||
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len))
|
||||
{
|
||||
for (hb_codepoint_t g : glyphs->iter())
|
||||
{
|
||||
unsigned i = cov.get_coverage (g);
|
||||
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
+ hb_zip (cov, pairSet)
|
||||
| hb_filter (*glyphs, hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
|
||||
{ return (this+_).intersects (glyphs, valueFormat); })
|
||||
| hb_any
|
||||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
| hb_map (hb_second)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
+ it
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
|
||||
;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
unsigned int count = pairSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
(this+pairSet[i]).collect_glyphs (c, valueFormat);
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
struct external_cache_t
|
||||
{
|
||||
hb_ot_layout_mapping_cache_t coverage;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_to;
|
||||
if (unlikely (!skippy_iter.next (&unsafe_to)))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat[0], valueFormat[1]);
|
||||
|
||||
if (c->plan->normalized_coords)
|
||||
{
|
||||
/* all device flags will be dropped when full instancing, no need to strip
|
||||
* hints, also do not strip emtpy cause we don't compute the new default
|
||||
* value during stripping */
|
||||
newFormats = compute_effective_value_formats (glyphset, false, false, &c->plan->layout_variation_idx_delta_map);
|
||||
}
|
||||
/* do not strip hints for VF */
|
||||
else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
|
||||
bool has_fvar = (blob != hb_blob_get_empty ());
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
bool strip = !has_fvar;
|
||||
/* special case: strip hints when a VF has no GDEF varstore after
|
||||
* subsetting*/
|
||||
if (has_fvar && !c->plan->has_gdef_varstore)
|
||||
strip = true;
|
||||
newFormats = compute_effective_value_formats (glyphset, strip, true);
|
||||
}
|
||||
|
||||
out->valueFormat[0] = newFormats.first;
|
||||
out->valueFormat[1] = newFormats.second;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
|
||||
{
|
||||
auto snap = c->serializer->snapshot ();
|
||||
auto *o = out->pairSet.serialize_append (c->serializer);
|
||||
if (unlikely (!o)) return false;
|
||||
bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
|
||||
if (!ret)
|
||||
{
|
||||
out->pairSet.pop ();
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
|
||||
|
||||
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset,
|
||||
bool strip_hints, bool strip_empty,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map = nullptr) const
|
||||
{
|
||||
unsigned record_size = PairSet::get_size (valueFormat);
|
||||
|
||||
unsigned format1 = 0;
|
||||
unsigned format2 = 0;
|
||||
for (const auto & _ :
|
||||
+ hb_zip (this+coverage, pairSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map (hb_second)
|
||||
)
|
||||
{
|
||||
const PairSet& set = (this + _);
|
||||
const PairValueRecord *record = &set.firstPairValueRecord;
|
||||
|
||||
unsigned count = set.len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (record->intersects (glyphset))
|
||||
{
|
||||
format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 (), strip_hints, strip_empty, &set, varidx_delta_map);
|
||||
format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]), strip_hints, strip_empty, &set, varidx_delta_map);
|
||||
}
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat[0] && format2 == valueFormat[1])
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
|
||||
@@ -0,0 +1,389 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
||||
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct PairPosFormat2_4 : ValueBase
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat1; /* ValueRecord definition--for the
|
||||
* first glyph of the pair--may be zero
|
||||
* (0) */
|
||||
ValueFormat valueFormat2; /* ValueRecord definition--for the
|
||||
* second glyph of the pair--may be
|
||||
* zero (0) */
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef1; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the first glyph of the pair */
|
||||
typename Types::template OffsetTo<ClassDef>
|
||||
classDef2; /* Offset to ClassDef table--from
|
||||
* beginning of PairPos subtable--for
|
||||
* the second glyph of the pair */
|
||||
HBUINT16 class1Count; /* Number of classes in ClassDef1
|
||||
* table--includes Class0 */
|
||||
HBUINT16 class2Count; /* Number of classes in ClassDef2
|
||||
* table--includes Class0 */
|
||||
ValueRecord values; /* Matrix of value pairs:
|
||||
* class1-major, class2-minor,
|
||||
* Each entry has value1 and value2 */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!(c->check_struct (this)
|
||||
&& coverage.sanitize (c, this)
|
||||
&& classDef1.sanitize (c, this)
|
||||
&& classDef2.sanitize (c, this))) return_trace (false);
|
||||
|
||||
unsigned int len1 = valueFormat1.get_len ();
|
||||
unsigned int len2 = valueFormat2.get_len ();
|
||||
unsigned int stride = HBUINT16::static_size * (len1 + len2);
|
||||
unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
|
||||
return_trace (c->check_range ((const void *) values,
|
||||
count,
|
||||
stride) &&
|
||||
(c->lazy_some_gpos ||
|
||||
(valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
|
||||
valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride))));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+coverage).intersects (glyphs) &&
|
||||
(this+classDef2).intersects (glyphs);
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!intersects (c->glyph_set)) return;
|
||||
if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
|
||||
|
||||
hb_set_t klass1_glyphs, klass2_glyphs;
|
||||
if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
|
||||
if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
|
||||
|
||||
hb_set_t class1_set, class2_set;
|
||||
for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
|
||||
{
|
||||
if (!klass1_glyphs.has (cp)) class1_set.add (0);
|
||||
else
|
||||
{
|
||||
unsigned klass1 = (this+classDef1).get (cp);
|
||||
class1_set.add (klass1);
|
||||
}
|
||||
}
|
||||
|
||||
class2_set.add (0);
|
||||
for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
|
||||
{
|
||||
unsigned klass2 = (this+classDef2).get (cp);
|
||||
class2_set.add (klass2);
|
||||
}
|
||||
|
||||
if (class1_set.is_empty ()
|
||||
|| class2_set.is_empty ()
|
||||
|| (class2_set.get_population() == 1 && class2_set.has(0)))
|
||||
return;
|
||||
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
|
||||
for (const unsigned class1_idx : class1_set.iter ())
|
||||
{
|
||||
for (const unsigned class2_idx : class2_set.iter ())
|
||||
{
|
||||
unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
|
||||
if (valueFormat1.has_device ())
|
||||
valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
|
||||
|
||||
if (valueFormat2.has_device ())
|
||||
valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
struct external_cache_t
|
||||
{
|
||||
hb_ot_layout_mapping_cache_t coverage;
|
||||
hb_ot_layout_mapping_cache_t first;
|
||||
hb_ot_layout_mapping_cache_t second;
|
||||
};
|
||||
void *external_cache_create () const
|
||||
{
|
||||
external_cache_t *cache = (external_cache_t *) hb_malloc (sizeof (external_cache_t));
|
||||
if (likely (cache))
|
||||
{
|
||||
cache->coverage.clear ();
|
||||
cache->first.clear ();
|
||||
cache->second.clear ();
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c, void *external_cache) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
external_cache_t *cache = (external_cache_t *) external_cache;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
|
||||
#else
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
#endif
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
auto &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset_fast (buffer->idx);
|
||||
unsigned unsafe_to;
|
||||
if (unlikely (!skippy_iter.next (&unsafe_to)))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, unsafe_to);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint, cache ? &cache->first : nullptr);
|
||||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint, cache ? &cache->second : nullptr);
|
||||
#else
|
||||
unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
|
||||
unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
|
||||
#endif
|
||||
if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
|
||||
{
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned int len1 = valueFormat1.get_len ();
|
||||
unsigned int len2 = valueFormat2.get_len ();
|
||||
unsigned int record_len = len1 + len2;
|
||||
|
||||
const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
|
||||
|
||||
bool applied_first = false, applied_second = false;
|
||||
|
||||
|
||||
/* Isolate simple kerning and apply it half to each side.
|
||||
* Results in better cursor positioning / underline drawing.
|
||||
*
|
||||
* Disabled, because causes issues... :-(
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3408
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
|
||||
*/
|
||||
#ifndef HB_SPLIT_KERN
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
if (!len2)
|
||||
{
|
||||
const hb_direction_t dir = buffer->props.direction;
|
||||
const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
|
||||
const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
|
||||
unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
|
||||
if (backward)
|
||||
mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
|
||||
/* Add Devices. */
|
||||
mask |= mask << 4;
|
||||
|
||||
if (valueFormat1 & ~mask)
|
||||
goto bail;
|
||||
|
||||
/* Is simple kern. Apply value on an empty position slot,
|
||||
* then split it between sides. */
|
||||
|
||||
hb_glyph_position_t pos{};
|
||||
if (valueFormat1.apply_value (c, this, v, pos))
|
||||
{
|
||||
hb_position_t *src = &pos.x_advance;
|
||||
hb_position_t *dst1 = &buffer->cur_pos().x_advance;
|
||||
hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
|
||||
unsigned i = horizontal ? 0 : 1;
|
||||
|
||||
hb_position_t kern = src[i];
|
||||
hb_position_t kern1 = kern >> 1;
|
||||
hb_position_t kern2 = kern - kern1;
|
||||
|
||||
if (!backward)
|
||||
{
|
||||
dst1[i] += kern1;
|
||||
dst2[i] += kern2;
|
||||
dst2[i + 2] += kern2;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst1[i] += kern1;
|
||||
dst1[i + 2] += src[i + 2] - kern2;
|
||||
dst2[i] += kern2;
|
||||
}
|
||||
|
||||
applied_first = applied_second = kern != 0;
|
||||
goto success;
|
||||
}
|
||||
goto boring;
|
||||
}
|
||||
}
|
||||
bail:
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
applied_first = len1 && valueFormat1.apply_value (c, this, v, buffer->cur_pos());
|
||||
applied_second = len2 && valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
|
||||
|
||||
if (applied_first || applied_second)
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
c->buffer->idx, skippy_iter.idx);
|
||||
}
|
||||
|
||||
success:
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
else
|
||||
boring:
|
||||
buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
|
||||
|
||||
if (len2)
|
||||
{
|
||||
skippy_iter.idx++;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
||||
buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
|
||||
}
|
||||
|
||||
buffer->idx = skippy_iter.idx;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_map_t klass1_map;
|
||||
out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
|
||||
out->class1Count = klass1_map.get_population ();
|
||||
|
||||
hb_map_t klass2_map;
|
||||
out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
|
||||
out->class2Count = klass2_map.get_population ();
|
||||
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
|
||||
hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
|
||||
|
||||
if (c->plan->normalized_coords)
|
||||
{
|
||||
/* in case of full instancing, all var device flags will be dropped so no
|
||||
* need to strip hints here */
|
||||
newFormats = compute_effective_value_formats (klass1_map, klass2_map, false, false, &c->plan->layout_variation_idx_delta_map);
|
||||
}
|
||||
/* do not strip hints for VF */
|
||||
else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
|
||||
bool has_fvar = (blob != hb_blob_get_empty ());
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
bool strip = !has_fvar;
|
||||
/* special case: strip hints when a VF has no GDEF varstore after
|
||||
* subsetting*/
|
||||
if (has_fvar && !c->plan->has_gdef_varstore)
|
||||
strip = true;
|
||||
newFormats = compute_effective_value_formats (klass1_map, klass2_map, strip, true);
|
||||
}
|
||||
|
||||
out->valueFormat1 = newFormats.first;
|
||||
out->valueFormat2 = newFormats.second;
|
||||
|
||||
unsigned total_len = len1 + len2;
|
||||
hb_vector_t<unsigned> class2_idxs (+ hb_range ((unsigned) class2Count) | hb_filter (klass2_map));
|
||||
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
||||
{
|
||||
for (unsigned class2_idx : class2_idxs)
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * total_len;
|
||||
valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], &c->plan->layout_variation_idx_delta_map);
|
||||
valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], &c->plan->layout_variation_idx_delta_map);
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = out->coverage.serialize_subset(c, coverage, this);
|
||||
return_trace (out->class1Count && out->class2Count && ret);
|
||||
}
|
||||
|
||||
|
||||
hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
|
||||
const hb_map_t& klass2_map,
|
||||
bool strip_hints, bool strip_empty,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map = nullptr) const
|
||||
{
|
||||
unsigned len1 = valueFormat1.get_len ();
|
||||
unsigned len2 = valueFormat2.get_len ();
|
||||
unsigned record_size = len1 + len2;
|
||||
|
||||
unsigned format1 = 0;
|
||||
unsigned format2 = 0;
|
||||
|
||||
for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
|
||||
{
|
||||
for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
|
||||
{
|
||||
unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * record_size;
|
||||
format1 = format1 | valueFormat1.get_effective_format (&values[idx], strip_hints, strip_empty, this, varidx_delta_map);
|
||||
format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1], strip_hints, strip_empty, this, varidx_delta_map);
|
||||
}
|
||||
|
||||
if (format1 == valueFormat1 && format2 == valueFormat2)
|
||||
break;
|
||||
}
|
||||
|
||||
return hb_pair (format1, format2);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRSET_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRSET_HH
|
||||
|
||||
#include "PairValueRecord.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairSet : ValueBase
|
||||
{
|
||||
template <typename Types2>
|
||||
friend struct PairPosFormat1_3;
|
||||
|
||||
using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
|
||||
|
||||
protected:
|
||||
HBUINT16 len; /* Number of PairValueRecords */
|
||||
PairValueRecord firstPairValueRecord;
|
||||
/* Array of PairValueRecords--ordered
|
||||
* by GlyphID of the second glyph */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
|
||||
static size_t get_size (unsigned len1, unsigned len2)
|
||||
{
|
||||
return Types::HBGlyphID::static_size + Value::static_size * (len1 + len2);
|
||||
}
|
||||
static size_t get_size (const ValueFormat valueFormats[2])
|
||||
{
|
||||
unsigned len1 = valueFormats[0].get_len ();
|
||||
unsigned len2 = valueFormats[1].get_len ();
|
||||
return get_size (len1, len2);
|
||||
}
|
||||
|
||||
struct sanitize_closure_t
|
||||
{
|
||||
const ValueFormat *valueFormats;
|
||||
unsigned int len1; /* valueFormats[0].get_len() */
|
||||
size_t stride; /* bytes */
|
||||
};
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!(c->check_struct (this) &&
|
||||
hb_barrier () &&
|
||||
c->check_range (&firstPairValueRecord,
|
||||
len,
|
||||
closure->stride))) return_trace (false);
|
||||
hb_barrier ();
|
||||
|
||||
unsigned int count = len;
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
return_trace (c->lazy_some_gpos ||
|
||||
(closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
|
||||
closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride)));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphs->has (record->secondGlyph))
|
||||
return true;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
c->input->add_array (&record->secondGlyph, len, record_size);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned record_size = get_size (valueFormats);
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (c->glyph_set->has (record->secondGlyph))
|
||||
{ record->collect_variation_indices (c, valueFormats, this); }
|
||||
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
unsigned int pos) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int len1 = valueFormats[0].get_len ();
|
||||
unsigned int len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = get_size (len1, len2);
|
||||
|
||||
const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
|
||||
&firstPairValueRecord,
|
||||
len,
|
||||
record_size);
|
||||
if (record)
|
||||
{
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"try kerning glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
bool applied_first = len1 && valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
|
||||
bool applied_second = len2 && valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
|
||||
|
||||
if (applied_first || applied_second)
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"kerned glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"tried kerning glyphs at %u,%u",
|
||||
c->buffer->idx, pos);
|
||||
}
|
||||
|
||||
if (applied_first || applied_second)
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
|
||||
if (len2)
|
||||
{
|
||||
pos++;
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3824
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
|
||||
buffer->unsafe_to_break (buffer->idx, pos + 1);
|
||||
}
|
||||
|
||||
buffer->idx = pos;
|
||||
return_trace (true);
|
||||
}
|
||||
buffer->unsafe_to_concat (buffer->idx, pos + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const ValueFormat valueFormats[2],
|
||||
const ValueFormat newFormats[2]) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->len = 0;
|
||||
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned len1 = valueFormats[0].get_len ();
|
||||
unsigned len2 = valueFormats[1].get_len ();
|
||||
unsigned record_size = get_size (len1, len2);
|
||||
|
||||
typename PairValueRecord::context_t context =
|
||||
{
|
||||
this,
|
||||
valueFormats,
|
||||
newFormats,
|
||||
len1,
|
||||
&glyph_map,
|
||||
&c->plan->layout_variation_idx_delta_map
|
||||
};
|
||||
|
||||
const PairValueRecord *record = &firstPairValueRecord;
|
||||
unsigned count = len, num = 0;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphset.has (record->secondGlyph)
|
||||
&& record->subset (c, &context)) num++;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
|
||||
out->len = num;
|
||||
if (!num) c->serializer->revert (snap);
|
||||
return_trace (num);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRSET_HH
|
||||
@@ -0,0 +1,99 @@
|
||||
#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct PairValueRecord
|
||||
{
|
||||
template <typename Types2>
|
||||
friend struct PairSet;
|
||||
|
||||
protected:
|
||||
typename Types::HBGlyphID
|
||||
secondGlyph; /* GlyphID of second glyph in the
|
||||
* pair--first glyph is listed in the
|
||||
* Coverage table */
|
||||
ValueRecord values; /* Positioning data for the first glyph
|
||||
* followed by for second glyph */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (Types::HBGlyphID::static_size, values);
|
||||
|
||||
int cmp (hb_codepoint_t k) const
|
||||
{ return secondGlyph.cmp (k); }
|
||||
|
||||
struct context_t
|
||||
{
|
||||
const ValueBase *base;
|
||||
const ValueFormat *valueFormats;
|
||||
const ValueFormat *newFormats;
|
||||
unsigned len1; /* valueFormats[0].get_len() */
|
||||
const hb_map_t *glyph_map;
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map;
|
||||
};
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
context_t *closure) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *s = c->serializer;
|
||||
auto *out = s->start_embed (*this);
|
||||
if (unlikely (!s->extend_min (out))) return_trace (false);
|
||||
|
||||
out->secondGlyph = (*closure->glyph_map)[secondGlyph];
|
||||
|
||||
closure->valueFormats[0].copy_values (s,
|
||||
closure->newFormats[0],
|
||||
closure->base, &values[0],
|
||||
closure->layout_variation_idx_delta_map);
|
||||
closure->valueFormats[1].copy_values (s,
|
||||
closure->newFormats[1],
|
||||
closure->base,
|
||||
&values[closure->len1],
|
||||
closure->layout_variation_idx_delta_map);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueFormat *valueFormats,
|
||||
const ValueBase *base) const
|
||||
{
|
||||
unsigned record1_len = valueFormats[0].get_len ();
|
||||
unsigned record2_len = valueFormats[1].get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
|
||||
|
||||
if (valueFormats[0].has_device ())
|
||||
valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
|
||||
|
||||
if (valueFormats[1].has_device ())
|
||||
valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t& glyphset) const
|
||||
{
|
||||
return glyphset.has(secondGlyph);
|
||||
}
|
||||
|
||||
const Value* get_values_1 () const
|
||||
{
|
||||
return &values[0];
|
||||
}
|
||||
|
||||
const Value* get_values_2 (ValueFormat format1) const
|
||||
{
|
||||
return &values[format1.get_len ()];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef OT_LAYOUT_GPOS_POSLOOKUP_HH
|
||||
#define OT_LAYOUT_GPOS_POSLOOKUP_HH
|
||||
|
||||
#include "PosLookupSubTable.hh"
|
||||
#include "../../../hb-ot-layout-common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PosLookup : Lookup
|
||||
{
|
||||
using SubTable = PosLookupSubTable;
|
||||
|
||||
const SubTable& get_subtable (unsigned int i) const
|
||||
{ return Lookup::get_subtable<SubTable> (i); }
|
||||
|
||||
bool is_reverse () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ return dispatch (c); }
|
||||
|
||||
hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
|
||||
{
|
||||
if (c->is_lookup_visited (this_index))
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
|
||||
c->set_lookup_visited (this_index);
|
||||
if (!intersects (c->glyphs))
|
||||
{
|
||||
c->set_lookup_inactive (this_index);
|
||||
return hb_closure_lookups_context_t::default_return_value ();
|
||||
}
|
||||
|
||||
hb_closure_lookups_context_t::return_t ret = dispatch (c);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename set_t>
|
||||
void collect_coverage (set_t *glyphs) const
|
||||
{
|
||||
hb_collect_coverage_context_t<set_t> c (glyphs);
|
||||
dispatch (&c);
|
||||
}
|
||||
|
||||
template <typename context_t>
|
||||
static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{ return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{ return Lookup::subset<SubTable> (c); }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{ return Lookup::sanitize<SubTable> (c); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_POSLOOKUP_HH */
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
|
||||
#define OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
|
||||
|
||||
#include "SinglePos.hh"
|
||||
#include "PairPos.hh"
|
||||
#include "CursivePos.hh"
|
||||
#include "MarkBasePos.hh"
|
||||
#include "MarkLigPos.hh"
|
||||
#include "MarkMarkPos.hh"
|
||||
#include "ContextPos.hh"
|
||||
#include "ChainContextPos.hh"
|
||||
#include "ExtensionPos.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct PosLookupSubTable
|
||||
{
|
||||
friend struct ::OT::Lookup;
|
||||
friend struct PosLookup;
|
||||
|
||||
enum Type {
|
||||
Single = 1,
|
||||
Pair = 2,
|
||||
Cursive = 3,
|
||||
MarkBase = 4,
|
||||
MarkLig = 5,
|
||||
MarkMark = 6,
|
||||
Context = 7,
|
||||
ChainContext = 8,
|
||||
Extension = 9
|
||||
};
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
|
||||
{
|
||||
TRACE_DISPATCH (this, lookup_type);
|
||||
switch (lookup_type) {
|
||||
case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
|
||||
case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
|
||||
default: return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c, lookup_type);
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
SinglePos single;
|
||||
PairPos pair;
|
||||
CursivePos cursive;
|
||||
MarkBasePos markBase;
|
||||
MarkLigPos markLig;
|
||||
MarkMarkPos markMark;
|
||||
ContextPos context;
|
||||
ChainContextPos chainContext;
|
||||
ExtensionPos extension;
|
||||
} u;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (0);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HB_OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH */
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOS_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOS_HH
|
||||
|
||||
#include "SinglePosFormat1.hh"
|
||||
#include "SinglePosFormat2.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePos
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
SinglePosFormat1 format1;
|
||||
SinglePosFormat2 format2;
|
||||
} u;
|
||||
|
||||
public:
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned get_format (Iterator glyph_val_iter_pairs)
|
||||
{
|
||||
hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
|
||||
|
||||
for (const auto iter : glyph_val_iter_pairs)
|
||||
for (const auto _ : hb_zip (iter.second, first_val_iter))
|
||||
if (_.first != _.second)
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup* src,
|
||||
Iterator glyph_val_iter_pairs,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned newFormat)
|
||||
{
|
||||
if (unlikely (!c->extend_min (u.format.v))) return;
|
||||
unsigned format = 2;
|
||||
ValueFormat new_format;
|
||||
new_format = newFormat;
|
||||
|
||||
if (glyph_val_iter_pairs)
|
||||
format = get_format (glyph_val_iter_pairs);
|
||||
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: u.format1.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
case 2: u.format2.serialize (c,
|
||||
src,
|
||||
glyph_val_iter_pairs,
|
||||
new_format,
|
||||
layout_variation_idx_delta_map);
|
||||
return;
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Iterator, typename SrcLookup>
|
||||
static void
|
||||
SinglePos_serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned new_format)
|
||||
{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_delta_map, new_format); }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOS_HH */
|
||||
@@ -0,0 +1,190 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
|
||||
|
||||
#include "Common.hh"
|
||||
#include "ValueFormat.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePosFormat1 : ValueBase
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat; /* Defines the types of data in the
|
||||
* ValueRecord */
|
||||
ValueRecord values; /* Defines positioning
|
||||
* value(s)--applied to all glyphs in
|
||||
* the Coverage table */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (6, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
hb_barrier () &&
|
||||
/* The coverage table may use a range to represent a set
|
||||
* of glyphs, which means a small number of bytes can
|
||||
* generate a large glyph set. Manually modify the
|
||||
* sanitizer max ops to take this into account.
|
||||
*
|
||||
* Note: This check *must* be right after coverage sanitize. */
|
||||
c->check_ops ((this + coverage).get_population () >> 1) &&
|
||||
valueFormat.sanitize_value (c, this, values));
|
||||
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (*c->glyph_set, intersection);
|
||||
if (!intersection) return;
|
||||
|
||||
valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
ValueFormat get_value_format () const { return valueFormat; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this, values, buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_blob_t *table_blob,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer {};
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
|
||||
|
||||
valueFormat.apply_value (&c, this, values, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
ValueFormat newFormat,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||
{
|
||||
if (unlikely (!c->extend_min (this))) return;
|
||||
if (unlikely (!c->check_assign (valueFormat,
|
||||
newFormat,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
|
||||
for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
|
||||
{
|
||||
src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map);
|
||||
// Only serialize the first entry in the iterator, the rest are assumed to
|
||||
// be the same.
|
||||
break;
|
||||
}
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c, glyphs);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
hb_set_t intersection;
|
||||
(this+coverage).intersect_set (glyphset, intersection);
|
||||
|
||||
unsigned new_format = valueFormat;
|
||||
|
||||
if (c->plan->normalized_coords)
|
||||
{
|
||||
new_format = valueFormat.get_effective_format (values.arrayZ, false, false, this, &c->plan->layout_variation_idx_delta_map);
|
||||
}
|
||||
/* do not strip hints for VF */
|
||||
else if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
{
|
||||
hb_blob_t* blob = hb_face_reference_table (c->plan->source, HB_TAG ('f','v','a','r'));
|
||||
bool has_fvar = (blob != hb_blob_get_empty ());
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
bool strip = !has_fvar;
|
||||
/* special case: strip hints when a VF has no GDEF varstore after
|
||||
* subsetting*/
|
||||
if (has_fvar && !c->plan->has_gdef_varstore)
|
||||
strip = true;
|
||||
new_format = valueFormat.get_effective_format (values.arrayZ,
|
||||
strip, /* strip hints */
|
||||
true, /* strip empty */
|
||||
this, nullptr);
|
||||
}
|
||||
|
||||
auto it =
|
||||
+ hb_iter (intersection)
|
||||
| hb_map_retains_sorting (glyph_map)
|
||||
| hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
|
||||
;
|
||||
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */
|
||||
@@ -0,0 +1,213 @@
|
||||
#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
|
||||
#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
|
||||
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
struct SinglePosFormat2 : ValueBase
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 2 */
|
||||
Offset16To<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of subtable */
|
||||
ValueFormat valueFormat; /* Defines the types of data in the
|
||||
* ValueRecord */
|
||||
HBUINT16 valueCount; /* Number of ValueRecords */
|
||||
ValueRecord values; /* Array of ValueRecords--positioning
|
||||
* values applied to glyphs */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (8, values);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
valueFormat.sanitize_values (c, this, values, valueCount));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
|
||||
{
|
||||
if (!valueFormat.has_device ()) return;
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (c->glyph_set, hb_first)
|
||||
;
|
||||
|
||||
if (!it) return;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
|
||||
|
||||
for (unsigned i : + it
|
||||
| hb_map (hb_second))
|
||||
valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
|
||||
|
||||
}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
ValueFormat get_value_format () const { return valueFormat; }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
if (unlikely (index >= valueCount)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioning glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
valueFormat.apply_value (c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
buffer->cur_pos());
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"positioned glyph at %u",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
buffer->idx++;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_blob_t *table_blob,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
if (unlikely (index >= valueCount)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer {};
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer, table_blob);
|
||||
|
||||
valueFormat.apply_value (&c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
void serialize (hb_serialize_context_t *c,
|
||||
const SrcLookup *src,
|
||||
Iterator it,
|
||||
ValueFormat newFormat,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map)
|
||||
{
|
||||
auto out = c->extend_min (this);
|
||||
if (unlikely (!out)) return;
|
||||
if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
|
||||
if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
|
||||
|
||||
+ it
|
||||
| hb_map (hb_second)
|
||||
| hb_apply ([&] (hb_array_t<const Value> _)
|
||||
{ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); })
|
||||
;
|
||||
|
||||
auto glyphs =
|
||||
+ it
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
coverage.serialize_serialize (c, glyphs);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned compute_effective_format (const hb_face_t *face,
|
||||
Iterator it,
|
||||
bool is_instancing, bool strip_hints,
|
||||
bool has_gdef_varstore,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
|
||||
{
|
||||
hb_blob_t* blob = hb_face_reference_table (face, HB_TAG ('f','v','a','r'));
|
||||
bool has_fvar = (blob != hb_blob_get_empty ());
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
unsigned new_format = 0;
|
||||
if (is_instancing)
|
||||
{
|
||||
new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), false, false, this, varidx_delta_map);
|
||||
}
|
||||
/* do not strip hints for VF */
|
||||
else if (strip_hints)
|
||||
{
|
||||
bool strip = !has_fvar;
|
||||
if (has_fvar && !has_gdef_varstore)
|
||||
strip = true;
|
||||
new_format = new_format | valueFormat.get_effective_format (+ it | hb_map (hb_second), strip, true, this, nullptr);
|
||||
}
|
||||
else
|
||||
new_format = valueFormat;
|
||||
|
||||
return new_format;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
unsigned sub_length = valueFormat.get_len ();
|
||||
auto values_array = values.as_array (valueCount * sub_length);
|
||||
|
||||
auto it =
|
||||
+ hb_zip (this+coverage, hb_range ((unsigned) valueCount))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
|
||||
{
|
||||
return hb_pair (glyph_map[_.first],
|
||||
values_array.sub_array (_.second * sub_length,
|
||||
sub_length));
|
||||
})
|
||||
;
|
||||
|
||||
unsigned new_format = compute_effective_format (c->plan->source, it,
|
||||
bool (c->plan->normalized_coords),
|
||||
bool (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
|
||||
c->plan->has_gdef_varstore,
|
||||
&c->plan->layout_variation_idx_delta_map);
|
||||
bool ret = bool (it);
|
||||
SinglePos_serialize (c->serializer, this, it, &c->plan->layout_variation_idx_delta_map, new_format);
|
||||
return_trace (ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */
|
||||
+446
@@ -0,0 +1,446 @@
|
||||
#ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
||||
#define OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
||||
|
||||
#include "../../../hb-ot-layout-gsubgpos.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GPOS_impl {
|
||||
|
||||
typedef HBUINT16 Value;
|
||||
|
||||
struct ValueBase {}; // Dummy base class tag for OffsetTo<Value> bases.
|
||||
|
||||
typedef UnsizedArrayOf<Value> ValueRecord;
|
||||
|
||||
struct ValueFormat : HBUINT16
|
||||
{
|
||||
enum Flags {
|
||||
xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
|
||||
yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
|
||||
xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
|
||||
yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
|
||||
xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
|
||||
yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
|
||||
xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
|
||||
yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
|
||||
ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
|
||||
reserved = 0xF000u, /* For future use */
|
||||
|
||||
devices = 0x00F0u /* Mask for having any Device table */
|
||||
};
|
||||
|
||||
/* All fields are options. Only those available advance the value pointer. */
|
||||
#if 0
|
||||
HBINT16 xPlacement; /* Horizontal adjustment for
|
||||
* placement--in design units */
|
||||
HBINT16 yPlacement; /* Vertical adjustment for
|
||||
* placement--in design units */
|
||||
HBINT16 xAdvance; /* Horizontal adjustment for
|
||||
* advance--in design units (only used
|
||||
* for horizontal writing) */
|
||||
HBINT16 yAdvance; /* Vertical adjustment for advance--in
|
||||
* design units (only used for vertical
|
||||
* writing) */
|
||||
Offset16To<Device> xPlaDevice; /* Offset to Device table for
|
||||
* horizontal placement--measured from
|
||||
* beginning of PosTable (may be NULL) */
|
||||
Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
|
||||
* placement--measured from beginning
|
||||
* of PosTable (may be NULL) */
|
||||
Offset16To<Device> xAdvDevice; /* Offset to Device table for
|
||||
* horizontal advance--measured from
|
||||
* beginning of PosTable (may be NULL) */
|
||||
Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
|
||||
* advance--measured from beginning of
|
||||
* PosTable (may be NULL) */
|
||||
#endif
|
||||
|
||||
NumType& operator = (uint16_t i) { v = i; return *this; }
|
||||
|
||||
// Note: spec says skip 2 bytes per bit in the valueformat. But reports
|
||||
// from Microsoft developers indicate that only the fields that are
|
||||
// currently defined are counted. We don't expect any new fields to
|
||||
// be added to ValueFormat. As such, we use the faster hb_popcount8
|
||||
// that only processes the lowest 8 bits.
|
||||
unsigned int get_len () const { return hb_popcount8 ((uint8_t) *this); }
|
||||
size_t get_size () const { return get_len () * Value::static_size; }
|
||||
|
||||
hb_vector_t<unsigned> get_device_table_indices () const {
|
||||
unsigned i = 0;
|
||||
hb_vector_t<unsigned> result;
|
||||
unsigned format = *this;
|
||||
|
||||
if (format & xPlacement) i++;
|
||||
if (format & yPlacement) i++;
|
||||
if (format & xAdvance) i++;
|
||||
if (format & yAdvance) i++;
|
||||
|
||||
if (format & xPlaDevice) result.push (i++);
|
||||
if (format & yPlaDevice) result.push (i++);
|
||||
if (format & xAdvDevice) result.push (i++);
|
||||
if (format & yAdvDevice) result.push (i++);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool apply_value (hb_ot_apply_context_t *c,
|
||||
const ValueBase *base,
|
||||
const Value *values,
|
||||
hb_glyph_position_t &glyph_pos) const
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int format = *this;
|
||||
if (!format) return ret;
|
||||
|
||||
hb_font_t *font = c->font;
|
||||
bool horizontal =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
HB_DIRECTION_IS_HORIZONTAL (c->direction)
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
;
|
||||
|
||||
if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
|
||||
if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
|
||||
if (format & xAdvance) {
|
||||
if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
|
||||
values++;
|
||||
}
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (format & yAdvance) {
|
||||
if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
|
||||
values++;
|
||||
}
|
||||
|
||||
if (!has_device ()) return ret;
|
||||
|
||||
bool use_x_device = font->x_ppem || font->has_nonzero_coords;
|
||||
bool use_y_device = font->y_ppem || font->has_nonzero_coords;
|
||||
|
||||
if (!use_x_device && !use_y_device) return ret;
|
||||
|
||||
const ItemVariationStore &store = c->var_store;
|
||||
auto *cache = c->var_store_cache;
|
||||
|
||||
/* pixel -> fractional pixel */
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
if (use_x_device) glyph_pos.x_offset += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & yPlaDevice)
|
||||
{
|
||||
if (use_y_device) glyph_pos.y_offset += get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & xAdvDevice)
|
||||
{
|
||||
if (horizontal && use_x_device) glyph_pos.x_advance += get_device (values, &ret, base, c->sanitizer).get_x_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
if (format & yAdvDevice)
|
||||
{
|
||||
/* y_advance values grow downward but font-space grows upward, hence negation */
|
||||
if (!horizontal && use_y_device) glyph_pos.y_advance -= get_device (values, &ret, base, c->sanitizer).get_y_delta (font, store, cache);
|
||||
values++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int get_effective_format (const Value *values, bool strip_hints, bool strip_empty, const ValueBase *base,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
|
||||
if (format & flag)
|
||||
{
|
||||
if (strip_hints && flag >= xPlaDevice)
|
||||
{
|
||||
format = format & ~flag;
|
||||
values++;
|
||||
continue;
|
||||
}
|
||||
if (varidx_delta_map && flag >= xPlaDevice)
|
||||
{
|
||||
update_var_flag (values++, (Flags) flag, &format, base, varidx_delta_map);
|
||||
continue;
|
||||
}
|
||||
/* do not strip empty when instancing, cause we don't know whether the new
|
||||
* default value is 0 or not */
|
||||
if (strip_empty) should_drop (*values, (Flags) flag, &format);
|
||||
values++;
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
unsigned int get_effective_format (Iterator it, bool strip_hints, bool strip_empty, const ValueBase *base,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const {
|
||||
unsigned int new_format = 0;
|
||||
|
||||
for (const hb_array_t<const Value>& values : it)
|
||||
new_format = new_format | get_effective_format (&values, strip_hints, strip_empty, base, varidx_delta_map);
|
||||
|
||||
return new_format;
|
||||
}
|
||||
|
||||
void copy_values (hb_serialize_context_t *c,
|
||||
unsigned int new_format,
|
||||
const ValueBase *base,
|
||||
const Value *values,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
if (!format) return;
|
||||
|
||||
HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr;
|
||||
if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++);
|
||||
if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++);
|
||||
if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++);
|
||||
if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++);
|
||||
|
||||
if (!has_device ())
|
||||
return;
|
||||
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice);
|
||||
}
|
||||
|
||||
if (format & yPlaDevice)
|
||||
{
|
||||
add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice);
|
||||
}
|
||||
|
||||
if (format & xAdvDevice)
|
||||
{
|
||||
add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice);
|
||||
}
|
||||
|
||||
if (format & yAdvDevice)
|
||||
{
|
||||
add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map);
|
||||
copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice);
|
||||
}
|
||||
}
|
||||
|
||||
HBINT16* copy_value (hb_serialize_context_t *c,
|
||||
unsigned int new_format,
|
||||
Flags flag,
|
||||
Value value) const
|
||||
{
|
||||
// Filter by new format.
|
||||
if (!(new_format & flag)) return nullptr;
|
||||
return reinterpret_cast<HBINT16 *> (c->copy (value));
|
||||
}
|
||||
|
||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||
const ValueBase *base,
|
||||
const hb_array_t<const Value>& values) const
|
||||
{
|
||||
unsigned format = *this;
|
||||
unsigned i = 0;
|
||||
if (format & xPlacement) i++;
|
||||
if (format & yPlacement) i++;
|
||||
if (format & xAdvance) i++;
|
||||
if (format & yAdvance) i++;
|
||||
if (format & xPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yPlaDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::xAdvDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (format & ValueFormat::yAdvDevice)
|
||||
{
|
||||
(base + get_device (&(values[i]))).collect_variation_indices (c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool sanitize_value_devices (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
|
||||
if (format & xPlacement) values++;
|
||||
if (format & yPlacement) values++;
|
||||
if (format & xAdvance) values++;
|
||||
if (format & yAdvance) values++;
|
||||
|
||||
if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline Offset16To<Device, ValueBase>& get_device (Value* value)
|
||||
{
|
||||
return *static_cast<Offset16To<Device, ValueBase> *> (value);
|
||||
}
|
||||
static inline const Offset16To<Device, ValueBase>& get_device (const Value* value)
|
||||
{
|
||||
return *static_cast<const Offset16To<Device, ValueBase> *> (value);
|
||||
}
|
||||
static inline const Device& get_device (const Value* value,
|
||||
bool *worked,
|
||||
const ValueBase *base,
|
||||
hb_sanitize_context_t &c)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
auto &offset = *static_cast<const Offset16To<Device> *> (value);
|
||||
|
||||
if (unlikely (!offset.sanitize (&c, base)))
|
||||
return Null(Device);
|
||||
hb_barrier ();
|
||||
|
||||
return base + offset;
|
||||
}
|
||||
|
||||
void add_delta_to_value (HBINT16 *value,
|
||||
const ValueBase *base,
|
||||
const Value *src_value,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
{
|
||||
if (!value) return;
|
||||
unsigned varidx = (base + get_device (src_value)).get_variation_index ();
|
||||
hb_pair_t<unsigned, int> *varidx_delta;
|
||||
if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return;
|
||||
|
||||
*value += hb_second (*varidx_delta);
|
||||
}
|
||||
|
||||
bool copy_device (hb_serialize_context_t *c,
|
||||
const ValueBase *base,
|
||||
const Value *src_value,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map,
|
||||
unsigned int new_format, Flags flag) const
|
||||
{
|
||||
// Filter by new format.
|
||||
if (!(new_format & flag)) return true;
|
||||
|
||||
Value *dst_value = c->copy (*src_value);
|
||||
|
||||
if (!dst_value) return false;
|
||||
if (*dst_value == 0) return true;
|
||||
|
||||
*dst_value = 0;
|
||||
c->push ();
|
||||
if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map))
|
||||
{
|
||||
c->add_link (*dst_value, c->pop_pack ());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->pop_discard ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
|
||||
{
|
||||
if (worked) *worked |= bool (*value);
|
||||
return *reinterpret_cast<const HBINT16 *> (value);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool has_device () const
|
||||
{
|
||||
unsigned int format = *this;
|
||||
return (format & devices) != 0;
|
||||
}
|
||||
|
||||
bool sanitize_value (hb_sanitize_context_t *c, const ValueBase *base, const Value *values) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (unlikely (!c->check_range (values, get_size ()))) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
return_trace (!has_device () || sanitize_value_devices (c, base, values));
|
||||
}
|
||||
|
||||
bool sanitize_values (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
unsigned size = get_size ();
|
||||
|
||||
if (!c->check_range (values, count, size)) return_trace (false);
|
||||
|
||||
if (c->lazy_some_gpos)
|
||||
return_trace (true);
|
||||
|
||||
hb_barrier ();
|
||||
return_trace (sanitize_values_stride_unsafe (c, base, values, count, size));
|
||||
}
|
||||
|
||||
/* Just sanitize referenced Device tables. Doesn't check the values themselves. */
|
||||
bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const ValueBase *base, const Value *values, unsigned int count, unsigned int stride) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
||||
if (!has_device ()) return_trace (true);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
if (!sanitize_value_devices (c, base, values))
|
||||
return_trace (false);
|
||||
values = &StructAtOffset<const Value> (values, stride);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void should_drop (Value value, Flags flag, unsigned int* format) const
|
||||
{
|
||||
if (value) return;
|
||||
*format = *format & ~flag;
|
||||
}
|
||||
|
||||
void update_var_flag (const Value* value, Flags flag,
|
||||
unsigned int* format, const ValueBase *base,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *varidx_delta_map) const
|
||||
{
|
||||
if (*value)
|
||||
{
|
||||
unsigned varidx = (base + get_device (value)).get_variation_index ();
|
||||
hb_pair_t<unsigned, int> *varidx_delta;
|
||||
if (varidx_delta_map->has (varidx, &varidx_delta) &&
|
||||
varidx_delta->first != HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
return;
|
||||
}
|
||||
*format = *format & ~flag;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
|
||||
@@ -0,0 +1,139 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESET_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESET_HH
|
||||
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct AlternateSet
|
||||
{
|
||||
protected:
|
||||
Array16Of<typename Types::HBGlyphID>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, alternates);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (alternates.sanitize (c));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return hb_any (alternates, glyphs); }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{ c->output->add_array (alternates.arrayZ, alternates.len); }
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{ c->output->add_array (alternates.arrayZ, alternates.len); }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int count = alternates.len;
|
||||
|
||||
if (unlikely (!count)) return_trace (false);
|
||||
|
||||
hb_mask_t glyph_mask = c->buffer->cur().mask;
|
||||
hb_mask_t lookup_mask = c->lookup_mask;
|
||||
|
||||
/* Note: This breaks badly if two features enabled this lookup together. */
|
||||
unsigned int shift = hb_ctz (lookup_mask);
|
||||
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
|
||||
|
||||
/* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
|
||||
if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
|
||||
{
|
||||
/* Maybe we can do better than unsafe-to-break all; but since we are
|
||||
* changing random state, it would be hard to track that. Good 'nough. */
|
||||
c->buffer->unsafe_to_break (0, c->buffer->len);
|
||||
alt_index = c->random_number () % count + 1;
|
||||
}
|
||||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->sync_so_far ();
|
||||
c->buffer->message (c->font,
|
||||
"replacing glyph at %u (alternate substitution)",
|
||||
c->buffer->idx);
|
||||
}
|
||||
|
||||
c->replace_glyph (alternates[alt_index - 1]);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
c->buffer->message (c->font,
|
||||
"replaced glyph at %u (alternate substitution)",
|
||||
c->buffer->idx - 1u);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
unsigned
|
||||
get_alternates (unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{
|
||||
if (alternates.len && alternate_count)
|
||||
{
|
||||
+ alternates.as_array ().sub_array (start_offset, alternate_count)
|
||||
| hb_sink (hb_array (alternate_glyphs, *alternate_count))
|
||||
;
|
||||
}
|
||||
return alternates.len;
|
||||
}
|
||||
|
||||
void
|
||||
collect_alternates (hb_codepoint_t gid,
|
||||
hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
+ hb_enumerate (alternates)
|
||||
| hb_map ([gid] (hb_pair_t<unsigned, hb_codepoint_t> _) { return hb_pair (gid + (_.first << 24), _.second); })
|
||||
| hb_apply ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> &p) -> void
|
||||
{ _hb_collect_glyph_alternates_add (p.first, p.second,
|
||||
alternate_count, alternate_glyphs); })
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Iterator,
|
||||
hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
Iterator alts)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
return_trace (alternates.serialize (c, alts));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto it =
|
||||
+ hb_iter (alternates)
|
||||
| hb_filter (glyphset)
|
||||
| hb_map (glyph_map)
|
||||
;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
return_trace (out->serialize (c->serializer, it) &&
|
||||
out->alternates);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESET_HH */
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESUBST_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESUBST_HH
|
||||
|
||||
#include "AlternateSubstFormat1.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
struct AlternateSubst
|
||||
{
|
||||
protected:
|
||||
union {
|
||||
struct { HBUINT16 v; } format; /* Format identifier */
|
||||
AlternateSubstFormat1_2<SmallTypes> format1;
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
AlternateSubstFormat1_2<MediumTypes> format2;
|
||||
#endif
|
||||
} u;
|
||||
public:
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
|
||||
TRACE_DISPATCH (this, u.format.v);
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
|
||||
#endif
|
||||
default:return_trace (c->default_return_value ());
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
|
||||
* iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (u.format.v))) return_trace (false);
|
||||
unsigned int format = 1;
|
||||
u.format.v = format;
|
||||
switch (u.format.v) {
|
||||
case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
|
||||
default:return_trace (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO subset() should choose format. */
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESUBST_HH */
|
||||
@@ -0,0 +1,141 @@
|
||||
#ifndef OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
|
||||
#define OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
|
||||
|
||||
#include "AlternateSet.hh"
|
||||
#include "Common.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace GSUB_impl {
|
||||
|
||||
template <typename Types>
|
||||
struct AlternateSubstFormat1_2
|
||||
{
|
||||
protected:
|
||||
HBUINT16 format; /* Format identifier--format = 1 */
|
||||
typename Types::template OffsetTo<Coverage>
|
||||
coverage; /* Offset to Coverage table--from
|
||||
* beginning of Substitution table */
|
||||
Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
|
||||
alternateSet; /* Array of AlternateSet tables
|
||||
* ordered by Coverage Index */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
bool may_have_non_1to1 () const
|
||||
{ return false; }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (c->parent_active_glyphs (), hb_first)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
|
||||
;
|
||||
}
|
||||
|
||||
void closure_lookups (hb_closure_lookups_context_t *c) const {}
|
||||
|
||||
void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_map (hb_second)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
|
||||
;
|
||||
}
|
||||
|
||||
const Coverage &get_coverage () const { return this+coverage; }
|
||||
|
||||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||
|
||||
unsigned
|
||||
get_glyph_alternates (hb_codepoint_t gid,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{ return (this+alternateSet[(this+coverage).get_coverage (gid)])
|
||||
.get_alternates (start_offset, alternate_count, alternate_glyphs); }
|
||||
|
||||
void
|
||||
collect_glyph_alternates (hb_map_t *alternate_count /* IN/OUT */,
|
||||
hb_map_t *alternate_glyphs /* IN/OUT */) const
|
||||
{
|
||||
+ hb_iter (alternateSet)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_zip (this+coverage)
|
||||
| hb_apply ([&] (const hb_pair_t<const AlternateSet<Types> &, hb_codepoint_t> _) {
|
||||
_.first.collect_alternates (_.second, alternate_count, alternate_glyphs);
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (index == NOT_COVERED) return_trace (false);
|
||||
|
||||
return_trace ((this+alternateSet[index]).apply (c));
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
hb_sorted_array_t<const HBGlyphID16> glyphs,
|
||||
hb_array_t<const unsigned int> alternate_len_list,
|
||||
hb_array_t<const HBGlyphID16> alternate_glyphs_list)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
|
||||
for (unsigned int i = 0; i < glyphs.length; i++)
|
||||
{
|
||||
unsigned int alternate_len = alternate_len_list[i];
|
||||
if (unlikely (!alternateSet[i]
|
||||
.serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
|
||||
return_trace (false);
|
||||
alternate_glyphs_list += alternate_len;
|
||||
}
|
||||
return_trace (coverage.serialize_serialize (c, glyphs));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
|
||||
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
out->format = format;
|
||||
|
||||
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||
+ hb_zip (this+coverage, alternateSet)
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_map (glyph_map)
|
||||
| hb_sink (new_coverage)
|
||||
;
|
||||
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||
return_trace (bool (new_coverage));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user