Browse Source
Squashed commit of the following:
Squashed commit of the following:
commitpre-master-464939bc8993Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Oct 25 22:04:16 2020 +0100 added cppduals cleanly commit834cbc5abaAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Oct 25 22:03:40 2020 +0100 remove cppduals commit69b922cef2Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Oct 25 21:59:00 2020 +0100 cppduals in new diretory commit4337cc0e33Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Oct 25 21:49:52 2020 +0100 hicum license cleaning commitba439dfdf5Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Oct 17 13:19:05 2020 +0200 moved sh stamp, working commit29028ff34dAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Oct 17 12:56:54 2020 +0200 forgot something commit5743d2b551Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Oct 17 12:54:35 2020 +0200 rth stamp moved (no yet working) commit42d61da3ebAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Oct 17 11:54:10 2020 +0200 Hicum C/C++ code now under 3-clause BSD commit5088e869eaAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Oct 17 11:44:57 2020 +0200 cleaned comments commit18fc66e71bAuthor: dwarning <dwarning> Date: Sat Sep 12 19:48:11 2020 +0200 rm some less useful comments - no code change commit861f286fdaAuthor: Markus Mueller <metroid120@googlemail.com> Date: Tue Sep 8 15:45:46 2020 +0200 clean hicum2ask commita52274ba7dAuthor: Markus Mueller <metroid120@googlemail.com> Date: Tue Sep 8 15:43:18 2020 +0200 fix nqs transient commitfa7f96b4afAuthor: Markus Mueller <metroid120@googlemail.com> Date: Mon Sep 7 13:17:42 2020 +0200 fix HICUM csu readin commit23183f10b6Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Aug 8 15:35:32 2020 +0200 added it to Hicum states -> noise commit020fc70607Author: dwarning <dwarning> Date: Tue Aug 4 09:18:05 2020 +0200 change inst to here commit33d06d9732Author: dwarning <dwarning> Date: Tue Aug 4 09:12:37 2020 +0200 reintroduce iavl and correct ibici shot noise commit7251265231Author: dwarning <dwarning> Date: Tue Aug 4 08:59:26 2020 +0200 more reasonable plot scaling commit67919b9bd8Author: dwarning <dwarning> Date: Tue Aug 4 08:56:04 2020 +0200 yet another try for flicker noise scaling commit689177a55fAuthor: dwarning <dwarning> Date: Mon Aug 3 10:41:44 2020 +0200 correct multiplier scaling for rsu commit58b89af40aAuthor: dwarning <dwarning> Date: Sun Aug 2 18:57:14 2020 +0200 prevent division by 0 for rbi commita4e7eb5b6cAuthor: dwarning <dwarning> Date: Sun Aug 2 18:25:51 2020 +0200 fix instance multiplier application for noise commit36862a7bc6Author: dwarning <dwarning> Date: Fri Jul 31 21:06:13 2020 +0200 white spaces commit8a0504bb13Author: dwarning <dwarning> Date: Fri Jul 31 18:32:45 2020 +0200 add a transient analysis example commitc1f0348697Author: dwarning <dwarning> Date: Fri Jul 31 18:31:10 2020 +0200 still problems in different terminal configurations commit26e026e4c8Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 31 14:36:34 2020 +0200 fix stamp for Cth commitdd84b1fcd3Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 31 14:22:16 2020 +0200 fix bug in Cscp stamp commit1f13d2526fAuthor: dwarning <dwarning> Date: Fri Jul 31 11:29:25 2020 +0200 visualc mod - no impact to hicum commitcff491fecaAuthor: dwarning <dwarning> Date: Fri Jul 31 10:59:52 2020 +0200 wrong and twice assignment commit4a9dc52037Author: dwarning <dwarning> Date: Fri Jul 31 10:00:20 2020 +0200 twice assignment commitc76bcc7ccaAuthor: dwarning <dwarning> Date: Thu Jul 30 12:36:30 2020 +0200 delete base nodes from inner to outer commit4a472a3451Author: dwarning <dwarning> Date: Mon Jul 27 15:34:15 2020 +0200 correct the switch for Vbici limiting commitf47bc449b3Author: dwarning <dwarning> Date: Sun Jul 26 21:56:48 2020 +0200 few parameter adaptions to version 2.40 commit5901ec2902Author: dwarning <dwarning> Date: Sun Jul 26 16:37:44 2020 +0200 sign for CONSTCtoK must be + commit556171a905Author: dwarning <dwarning> Date: Sun Jul 26 16:36:15 2020 +0200 rbi is 0 if nodes are collapsed commit724887f32cAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 26 12:45:15 2020 +0200 add ngspice Temperature clipping in HICUM commitd735f445e5Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 26 12:13:39 2020 +0200 removed rbi fallback, removed rth_de commit162b174acdAuthor: dwarning <dwarning> Date: Sat Jul 25 12:31:05 2020 +0200 add few small-signal parameter commit5afb2dc8c8Author: dwarning <dwarning> Date: Fri Jul 24 16:49:11 2020 +0200 reduce unnecassary inits commit0efc047f5fAuthor: dwarning <dwarning> Date: Fri Jul 24 16:03:10 2020 +0200 few typos and comments commit14a5cd873bAuthor: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 24 11:25:51 2020 +0200 remove rbi stamps if nodes collapsed finish commitf5461183f3Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 24 11:17:33 2020 +0200 hicumL2 load -> remove stamp for rbi, if node BP BI collapsed commit00f51465e3Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 24 11:07:58 2020 +0200 finish cleaning commit019ef4e07eAuthor: Markus Mueller <metroid120@googlemail.com> Date: Fri Jul 24 10:50:05 2020 +0200 moving derivatives from _Tdev to _Vrth in a clean way (start) commit154036c09fAuthor: Markus Mueller <metroid120@googlemail.com> Date: Thu Jul 23 16:50:31 2020 +0200 consistent derivative with Vrth/Tdev=> will rework this, I do not like this commit03c3efd762Author: Markus Mueller <metroid120@googlemail.com> Date: Thu Jul 23 16:22:46 2020 +0200 finally: avalanche at very high T fix commit64704fd53eMerge: a26b3ee2b f6db74ac5 Author: Markus Mueller <metroid120@googlemail.com> Date: Thu Jul 23 15:56:29 2020 +0200 Merge remote-tracking branch 'origin/markus_dev' into markus_dev commit a26b3ee2b20c668df6d41938a06472440803855f Author: Markus Mueller <metroid120@googlemail.com> Date: Thu Jul 23 15:56:17 2020 +0200 start bugfix commit f6db74ac50da167d3081c1c7e8a2e5eda254183f Author: dwarning <dwarning> Date: Tue Jul 21 18:56:32 2020 +0200 rm obsolete files commit 9854038f2c22acf688fa494496ca7b71855198ea Author: dwarning <dwarning> Date: Tue Jul 21 16:48:56 2020 +0200 allow periphal resistors and rbi default 0 commit 34f579c08f9b8378c29074678e9cb651f49092ce Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jul 21 13:05:54 2020 +0200 fix bug node collapsing BI BP commit 6f5627f44169bd4eb72dea3fb7d8f6d600ddcdb5 Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jul 21 11:48:22 2020 +0200 node collapsing BI BP HICUM commit 187d391383cfe76fb5214971ac0ad7fe94b7e397 Author: dwarning <dwarning> Date: Tue Jul 21 09:58:59 2020 +0200 few corrections and reordering commit 0fc39a424e52804c40003b55ee398812cbaf151b Author: dwarning <dwarning> Date: Mon Jul 20 19:36:15 2020 +0200 unify nqs flag for setup/unsetup commit 8944ad2e32e69b87c79d512e05505d41f22bd311 Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 18 14:23:30 2020 +0200 iavl_Vbiei changed sign back ... commit cc9682f9e541fd16e89cfe687367257be975766f Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 18 14:05:12 2020 +0200 HICUM limit for avalanche commit 284583e0cc19ff5247d7ce8df8d3292ff60d2062 Author: dwarning <dwarning> Date: Wed Jul 15 10:11:46 2020 +0200 cleanup initial conditions to the traditional spice usage commit c3cadb8de18cfe522e33c1499e927890a3dbb90d Author: dwarning <dwarning> Date: Wed Jul 15 08:57:03 2020 +0200 rm unused files commit 8bc687ddbe66af29234b4aba9279d01fc4d9cda2 Author: dwarning <dwarning> Date: Mon Jul 13 10:44:56 2020 +0200 correct check6 init commit 9250464ac16eded2cc38deec0bf64af9bc03c639 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 12 14:00:46 2020 +0200 fix bug in HICUM Qjci calculation, derivatives now more rigorous with dual numbers commit 0fb86510aab4881e858728c588d72852e69df4ca Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 11 15:02:04 2020 +0200 fix gmin in HICUM commit 735339e288ceb61d0aa19e09fb6160bd16cbfed6 Merge: fd5b7a648 1659190b2 Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 11 14:45:08 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commitfd5b7a6485Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 11 14:44:01 2020 +0200 fix HICUM gmin commit1659190b21Author: dwarning <dwarning> Date: Sat Jul 11 09:57:29 2020 +0200 real node collapsing with slightly better results in qa test convergence problems in high current avalanche breakdown still exist commitaaa94e5c10Author: dwarning <dwarning> Date: Thu Jul 9 18:10:04 2020 +0200 add hspice to qa commit6fe586cf9dAuthor: dwarning <dwarning> Date: Thu Jul 9 17:26:28 2020 +0200 relax convergence criteria for qa test commit127c2ca451Author: dwarning <dwarning> Date: Thu Jul 9 14:02:48 2020 +0200 correct loop stopping criteria commitcfae080c1aAuthor: dwarning <dwarning> Date: Wed Jul 8 18:02:13 2020 +0200 examples now version 2.4.0 commit7b099242daAuthor: dwarning <dwarning> Date: Wed Jul 8 17:18:28 2020 +0200 rm non qa file commit0c2ef2f7c4Author: dwarning <dwarning> Date: Wed Jul 8 17:15:58 2020 +0200 qa test is now version 2.4.0 commite90939126dAuthor: dwarning <dwarning> Date: Wed Jul 8 17:13:29 2020 +0200 qa test is now version 2.4.0 commit114aeee5c5Author: dwarning <dwarning> Date: Wed Jul 8 17:12:05 2020 +0200 now version 2.4.0 commit0f33776513Author: dwarning <dwarning> Date: Wed Jul 8 11:40:43 2020 +0200 reactivate convergence check commit6f382c76d8Author: dwarning <dwarning> Date: Wed Jul 8 11:02:30 2020 +0200 rm old comments and artefacts commit5950a2fb03Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jul 8 09:51:03 2020 +0200 example print for dual number commitabab054352Author: dwarning <dwarning> Date: Tue Jul 7 08:51:51 2020 +0200 nqs must set after defaulting model parameters commit4c34e54c7bAuthor: dwarning <dwarning> Date: Mon Jul 6 21:37:04 2020 +0200 prevent false branch because of rounding error for flcomp commit4bb09b35c3Author: dwarning <dwarning> Date: Sun Jul 5 22:16:28 2020 +0200 clear separation between geometry and temperature scaling commit90ab76d876Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 5 18:14:08 2020 +0200 fix comments in HICUM scaling commitd7dd26880cAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 5 18:03:23 2020 +0200 forgot some parameters that depend on "area" and T, but are needed as model variables in load commit320a66c0a4Merge: d78032109 b09edc706 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 5 17:27:20 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commitd78032109fAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jul 5 17:26:45 2020 +0200 HICUM scaling with "area" and "m" parameters. commitb09edc706aAuthor: dwarning <dwarning> Date: Sun Jul 5 17:10:51 2020 +0200 must fallthrough because icVbe is after icVce commitdbd99a33a5Author: dwarning <dwarning> Date: Sun Jul 5 09:59:09 2020 +0200 some useful examples to show hicum2 capabilities commitba1c2de06eAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 4 20:21:38 2020 +0200 added comment to IC vars commit6fce26437eAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 4 20:03:13 2020 +0200 remove hicum inital conditions that are not spice-like commitaa283f40efAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jul 4 19:55:58 2020 +0200 added HICUM pole zero analysis commit2165afdf27Author: dwarning <dwarning> Date: Fri Jul 3 17:39:03 2020 +0200 another cut&paste error and typo commit8b680b0c28Author: dwarning <dwarning> Date: Fri Jul 3 17:28:40 2020 +0200 another cut&paste error commitf1698c7a81Author: dwarning <dwarning> Date: Fri Jul 3 15:42:37 2020 +0200 add shot noise sources for it and ibiei commit966891d5f7Author: dwarning <dwarning> Date: Fri Jul 3 14:39:31 2020 +0200 correct multiplier for flicker noise and base-emitter source connection commit80e932424fAuthor: dwarning <dwarning> Date: Fri Jul 3 14:27:52 2020 +0200 cut&paste error commit61ee68c782Author: dwarning <dwarning> Date: Thu Jul 2 21:05:58 2020 +0200 few corrections in noise model commitad16be59baAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Jul 1 14:44:13 2020 +0200 reorder code commite81b41c653Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jul 1 14:33:12 2020 +0200 fix bugs HICHUM acload commit1d5f88e93dAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 28 11:51:10 2020 +0200 fix bugs commitbbb729ae8fAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 28 11:03:48 2020 +0200 intermediate state commita95aade55aAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 27 20:16:37 2020 +0200 fix derivative in NQS network commita54c52221cAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 27 20:05:58 2020 +0200 small fixes HICUM commit7407302d50Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 27 17:48:23 2020 +0200 fix bug in HICUMacload commitbb03c8f663Merge: 1fa789874 e7d143e04 Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 24 13:17:15 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commit1fa7898747Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 24 13:16:20 2020 +0200 remove nqs from limit function and gmin commite7d143e044Author: dwarning <dwarning> Date: Tue Jun 23 18:22:40 2020 +0200 tk is not an alias parameter name commit75e3a4da64Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 23 16:24:59 2020 +0200 protect nqs network commit1c36e997baAuthor: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 23 15:44:46 2020 +0200 nqs in ac commit524abe95f3Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 23 15:21:27 2020 +0200 NQS in acload commit0833f955efAuthor: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 23 14:47:35 2020 +0200 move cross-coupled charges from state vector to here struct commit03b4a87477Author: dwarning <dwarning> Date: Mon Jun 22 11:52:42 2020 +0200 prevent crash if tnode is given but she parameter not commit9ab20e2f35Author: dwarning <dwarning> Date: Mon Jun 22 11:51:47 2020 +0200 alias for tnom commit3140bedc3fAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 21 21:50:39 2020 +0200 fix nqs commit8dfd2e5a4dAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 20 18:41:35 2020 +0200 fix HICUM setup commitf6e4bba9e3Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 20 18:40:04 2020 +0200 finish NQS for DC case commit21862cbdb9Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 20 17:55:01 2020 +0200 first test ok ... modify state vector now commit1c5773292eAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 20 17:45:57 2020 +0200 first implementation of NQS, not tested commit4fd24db766Author: dwarning <dwarning> Date: Fri Jun 19 22:12:49 2020 +0200 external temp node has number 5 commit8fb3f2ce9aMerge: b7e4c39d8 5f4085d4a Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jun 19 19:05:31 2020 +0200 Merge remote-tracking branch 'origin/markus_dev' into markus_dev commit b7e4c39d80b4b93ae58efc7449d43f39712f7bb9 Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jun 19 19:03:46 2020 +0200 fix unset t node HICUM commit 5f4085d4a8193cc9978f768d2d4fb89271b56c3a Author: dwarning <dwarning> Date: Wed Jun 17 20:34:02 2020 +0200 unify self-heating switch commit c927c32541f8ee57ebce35066a5b0b10fdbf76af Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 17 18:41:15 2020 +0200 qaSpec with ads run commit d05eaa744e6abefdb2a2a874c6028e6f8b714ef1 Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 17 17:38:50 2020 +0200 added derivatives for NQS network commit 88cf4bb92583cf8f02f5f65c23dde02a64f992e8 Author: dwarning <dwarning> Date: Wed Jun 17 13:24:03 2020 +0200 allow SHE also without external temperature node prevent crash with rth=0 commit 716125334263ed3819241cdb9342b6cc4ce174b1 Merge: a46cb231a e2bb25b12 Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 16 17:33:41 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commita46cb231a0Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 16 17:32:20 2020 +0200 tmp node to gnd in HICUM if no SH commite2bb25b125Author: dwarning <dwarning> Date: Mon Jun 15 08:54:50 2020 +0200 qaSpec guess for ads commitbbde282b51Author: dwarning <dwarning> Date: Mon Jun 15 08:33:17 2020 +0200 typo 1D commit4e6deec579Merge: 5da1d7031 6fbbeb06d Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 14 19:58:33 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commit5da1d7031cAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 14 19:57:56 2020 +0200 HICUMload transient part first review, small fixes commit96af16e673Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 14 18:53:49 2020 +0200 gmin fix commit6fbbeb06d9Author: dwarning <dwarning> Date: Sun Jun 14 11:05:12 2020 +0200 complete device node request for temp node commiteae118787eAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 13 21:52:32 2020 +0200 fix hicumACload singular matrix bug commit2a1f47e1e5Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 13 20:29:04 2020 +0200 cleaned commit7e5fdae917Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 13 20:19:51 2020 +0200 refactor gmin in HICUM commit7aadd9af4aMerge: f55f613c2 595e46447 Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 13 19:32:02 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commitf55f613c24Author: Markus Mueller <metroid120@googlemail.com> Date: Sat Jun 13 19:31:39 2020 +0200 added dual numbers include in ngspice/include commit595e464479Author: dwarning <dwarning> Date: Fri Jun 12 19:13:26 2020 +0200 introduce version parameter to prevent warnings in qa test commit147bf5eb4aAuthor: dwarning <dwarning> Date: Fri Jun 12 17:16:48 2020 +0200 use standard include path configuration for external cppduals commit7a41174b5eAuthor: dwarning <dwarning> Date: Thu Jun 11 18:22:42 2020 +0200 add ads for qa test commit3942fc48ceAuthor: Markus Mueller <metroid120@googlemail.com> Date: Thu Jun 11 17:40:13 2020 +0200 added charges for SHE in HICUMacload commit12fa8a8cf7Author: dwarning <dwarning> Date: Thu Jun 11 15:34:06 2020 +0200 resolve confusing naming of instance parameter structure commit7578aec2a8Author: dwarning <dwarning> Date: Thu Jun 11 15:29:40 2020 +0200 introduce version parameter to prevent warnings in qa test commitb401428cddAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 10 18:17:44 2020 +0200 minor cleaning commit5d28b97fb5Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 7 16:46:21 2020 +0200 added SHE stamps for DC currents in HICUMacload commit9737dc7a5bAuthor: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 7 16:36:36 2020 +0200 HICUM acload initial review commit6eefe34d56Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 7 13:58:24 2020 +0200 add real part of AC matrix commit55e14e62e7Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 7 13:20:12 2020 +0200 dirty fix iavl commit99a21e9f61Author: Markus Mueller <metroid120@googlemail.com> Date: Sun Jun 7 12:15:39 2020 +0200 some minor modificaitons, avalanche current problems commit99f8c9a9edMerge: 17898981c 6b9f5647c Author: Markus Mueller <metroid120@googlemail.com> Date: Fri Jun 5 10:27:08 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commit17898981cdAuthor: Markus Mueller <metroid120@googlemail.com> Date: Fri Jun 5 10:20:21 2020 +0200 minor cleaning, fix derivative iavl commit6b9f5647caAuthor: dwarning <dwarning> Date: Thu Jun 4 18:23:10 2020 +0200 first version for cmc qa check commit3f11d38774Author: Markus Mueller <metroid120@googlemail.com> Date: Thu Jun 4 16:37:09 2020 +0200 implemented experimental rth direct evaluation commit40900da8bfAuthor: Markus Mueller <metroid120@googlemail.com> Date: Thu Jun 4 14:45:12 2020 +0200 small correction commit7f1493bddbAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 19:25:35 2020 +0200 minor changes, cleaning commit55367a44a5Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 19:05:39 2020 +0200 completed all del voltages commitd32ff77aefAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 18:23:19 2020 +0200 renaming variables for cleaner code commite4b4978368Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 18:17:49 2020 +0200 adding derivatives of branches with respect to Vrth to the state vector commita6b39a749cAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 17:29:37 2020 +0200 correct Temperature update commit55c33ad675Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Jun 3 17:21:31 2020 +0200 before changing Temp in load commit7f7b31e5c0Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 2 20:01:07 2020 +0200 fixing small bugs commit7555278074Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 2 19:39:48 2020 +0200 fixed some stamps commit0d59e12518Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Jun 2 19:13:50 2020 +0200 fixed avalanche commitee25c6ce42Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Jun 1 20:07:25 2020 +0200 cleaned up commitd61b510207Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Jun 1 19:18:45 2020 +0200 hicumL2 load routine seems to be working, next ac? commit29a61f21e2Merge: c94120cbf dcf4a4487 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Jun 1 14:32:39 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commitc94120cbf9Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Jun 1 14:30:40 2020 +0200 first hicum convergence with SH commitdcf4a44871Merge: c37a88bec c1444a06b Author: dwarning <dwarning> Date: Mon Jun 1 10:57:42 2020 +0200 Merge branch 'markus_dev' of ssh://git.code.sf.net/p/ngspice/ngspice into markus_dev commit c37a88bec8a12ab766ac1471a1dc452eabea41d3 Author: dwarning <dwarning> Date: Mon Jun 1 10:56:53 2020 +0200 set the cppduals include folder above ngspice dir commit c1444a06b606cde594d7ad8054df527cdd1d4f68 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 31 20:38:16 2020 +0200 finish hicum SH review, next testing. commit e3c194e050701139506ff821f931f7e14141129b Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 31 20:26:41 2020 +0200 fixed some stamps, improved code readability, temp stamps corrected commit 59c50d509572bf916021abc40e69a896f71e7ef6 Author: Markus Mueller <metroid120@googlemail.com> Date: Sat May 30 20:37:28 2020 +0200 fixed rbi stamp, convergence looks pretty good DC no SH commit f7012280e626a885c5635a19db7025477def0f71 Author: Markus Mueller <metroid120@googlemail.com> Date: Sat May 30 17:12:37 2020 +0200 fix rbi convergence commit 326b29c4d86ff9f72fd2959419a8476f913cde48 Author: Markus Mueller <metroid120@googlemail.com> Date: Fri May 29 16:54:30 2020 +0200 started work on self heating commit 4994feaa2b1b3d13873665b9383ae6e74ecd24d5 Author: Markus Mueller <metroid120@googlemail.com> Date: Fri May 29 16:08:18 2020 +0200 corrected rbi stamp... commit 460e7ec04bd00563e4455a8868de1622dab10260 Author: mariok <mario.krattenmacher@web.de> Date: Wed May 20 11:22:01 2020 +0200 more thermal stuff implemented commit 194331867e3a92dd9740f72403f303a7121f5954 Author: mariok <mario.krattenmacher@web.de> Date: Tue May 19 16:24:34 2020 +0200 added HICUMtempCollPtr HICUMtempBasePtr HICUMtempEmitPtr commit 697af41531cc193346b9fca1f2584b44f0dc0a09 Author: dwarning <dwarning> Date: Tue May 19 08:03:35 2020 +0200 exchange hicum2temp file in VS project commit 03750cd24e528119c69d69cf2fc188cfe7d7d334 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 17 20:20:00 2020 +0200 ziwschenstand, checked code for maths errors commit 418966c6e5625be535766ed3c6df7c124431a589 Author: mariok <mario.krattenmacher@web.de> Date: Wed May 13 10:25:49 2020 +0200 can not call a function inside a comparision commit abecd18651a5d490bbe6d75ad33bffa204df3322 Author: mariok <mario.krattenmacher@web.de> Date: Wed May 13 10:09:11 2020 +0200 removed all buggs from hicumL2 to debug. commit 1fe3cc8b12420b0a3e28fd25290d9d583abe02a9 Merge: afdffacd4 58f66c1d4 Author: mariok <mario.krattenmacher@web.de> Date: Wed May 13 07:30:56 2020 +0200 Merge remote-tracking branch 'origin/markus_dev' into hicum2-mario commit afdffacd4b54c992d9168e6babb9ff1e29b0f916 Author: mariok <mario.krattenmacher@web.de> Date: Tue May 12 19:59:09 2020 +0200 ac und pz load commit 890ccc415fdba241e9964baa6c066e69ea8e7c7c Author: mariok <mario.krattenmacher@web.de> Date: Tue May 12 19:55:23 2020 +0200 implemented hicum_diode as example commit 63bf7113d4f46cb95c5c3e2b94f0e2e22ec81ea0 Author: mariok <mario.krattenmacher@web.de> Date: Tue May 12 18:33:51 2020 +0200 all temperature scaling equations done using dual numbers commit 96c66dd6456693e2f89b4d62390e12160b6c5823 Author: mariok <mario.krattenmacher@web.de> Date: Tue May 12 17:14:17 2020 +0200 started dual numbers in hicum2temp and a transfer struct in hicum2defs commit 58f66c1d460f8c7c80c23ab6a08f9ea370ab028f Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 12 12:28:50 2020 +0200 fix Vbe initialization commit 35deffa742aea641e5ddc5077c3d78179f84d133 Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 12 12:25:48 2020 +0200 cleaned further commit 304dd91f585aa5cc361ae996a9af2ff33043158a Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 12 12:15:52 2020 +0200 cleaned up, small fixes, include Tf commit 1d7da49e27b49f69449dffd164b5c3d079ca8f3f Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 12 09:37:39 2020 +0200 fixed bugs commit 479c2a19eaabc4c7545b60d3aaeaf4ad702e19a3 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon May 11 15:50:01 2020 +0200 forgot Nan catcher commit 5bbe0f9cf7022bff22bdf932f548e883ea2f79f0 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon May 11 15:48:03 2020 +0200 bugfix Q_p calculation commit 67857cf983e72243b3d6d37f882e4eadb20c0ecc Author: Markus Mueller <metroid120@googlemail.com> Date: Mon May 11 15:42:27 2020 +0200 fixed derivatives and itf for case without newton iteration commit d6ee2c206e3daf24fd52b9e58cf87961552c6b16 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon May 11 14:08:18 2020 +0200 resolved some un-initialized variables commit 76ed5cb36a9aca1ad2a1b081fa30d039d66b4e3b Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 10 20:48:38 2020 +0200 finished clean commit ba6e6d5e4990d048a34ab818e033363dd19f6869 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 10 18:48:24 2020 +0200 added all remaining hicum l2 elements commit 36244b809a3ea143aafc9bed62ea9376bc876f31 Author: Markus Mueller <metroid120@googlemail.com> Date: Sun May 10 17:45:27 2020 +0200 resolved Dietmar comments from email commit eaa5be9716360a4003920ed94057e4fe92be9fdd Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 5 16:38:08 2020 +0200 added base emitter recombination current and derivatives commit 4318b7165bccd5e4fba632de02da96e5a64920bd Author: Markus Mueller <metroid120@googlemail.com> Date: Tue May 5 14:30:15 2020 +0200 added initial conditions for all nodes, model converging again for simple modelcard commit 3008c526bff4cba463c362dec2efc2b6c4e60b2a Author: mariok <mario.krattenmacher@web.de> Date: Mon May 4 19:00:31 2020 +0200 removed QpT and testing only 1 OP commit 9cb4c1546f70543b5e3b4060a600157e493c2534 Author: mariok <mario.krattenmacher@web.de> Date: Mon May 4 18:37:52 2020 +0200 icVBE and icVCE used for DC commit 8a7369767551f3d5a2e18102ea0aae40a6dd8319 Author: mariok <mario.krattenmacher@web.de> Date: Mon May 4 18:03:46 2020 +0200 fixed dual number Q_0_hjei_vbe commit 5783938b086e9b1f9bfb17e32aaf24aedf72f72e Author: mariok <mario.krattenmacher@web.de> Date: Mon May 4 16:30:41 2020 +0200 reintroduced dtemp as instance parameter commit 9350f3f3be710f195fb68b3f9f9ce30f937444ba Author: dwarning <dwarning> Date: Sun May 3 17:25:12 2020 +0200 Revert some namings commit 197f6db83b7d5ad7a6bbb20acf2b884889bcd06c Author: dwarning <dwarning> Date: Sat May 2 23:18:58 2020 +0200 Adapt VS project to C++ commit af32f79641536edfa94cc683b6cede036969c667 Author: dwarning <dwarning> Date: Sat May 2 23:18:43 2020 +0200 Skip NQS effekt and revert some namings commit a995aa0ccec30cedf7c8088b5c6780abd0bab1c9 Author: dwarning <dwarning> Date: Sat May 2 23:18:27 2020 +0200 Skip NQS effekt commit d7295cbe78dd08ba99e95922e1a5a90de2b25666 Merge: 2502b57ee 6ca440e58 Author: Markus Mueller <metroid120@googlemail.com> Date: Wed Apr 29 19:04:32 2020 +0200 Merge branch 'markus_dev' of https://git.code.sf.net/p/ngspice/ngspice into markus_dev commit2502b57eeeAuthor: Markus Mueller <metroid120@googlemail.com> Date: Wed Apr 29 19:03:26 2020 +0200 added quests, derivative vciei changed to vbiei vbici commit6ca440e584Author: dwarning <dwarning> Date: Wed Apr 29 09:35:12 2020 +0200 add hicumL2.cpp instead of hicum2load.c in VS project commit6e98506a7fAuthor: dwarning <dwarning> Date: Wed Apr 29 09:33:08 2020 +0200 cmath seems not to have M_PI commitd6332815b3Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Apr 28 20:58:35 2020 +0200 derivatives it looking good commitaaaace7247Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Apr 28 19:39:48 2020 +0200 adding hicum derivatives like a mad-man commit2d8a3e3629Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Apr 28 18:44:46 2020 +0200 added Q_pT and derivatives...fun commit50a3e372cfAuthor: Markus Mueller <metroid120@googlemail.com> Date: Tue Apr 28 17:17:17 2020 +0200 starting work on transfer current commit8fd70e2f15Author: Markus Mueller <metroid120@googlemail.com> Date: Tue Apr 28 13:01:18 2020 +0200 added asks, found bug with ibci commit2baac89ae3Merge: 97a0aa856 c897e60c8 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 27 20:47:06 2020 +0200 Merge remote-tracking branch 'origin/hicum2-thermal' into markus_dev commit c897e60c8b1e6df92564bf6e56ce9e3efc2bd40f Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 27 18:12:40 2020 +0200 pointer in ask commit 3b0551c544e542e10006b77bc0684b3075c874f7 Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 27 17:36:19 2020 +0200 two small bugfixes commit b02c763ed1a1e1e53c095e8b88627a7d76e0954a Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 27 17:13:30 2020 +0200 HICUM2ask done according to VA-Code commit 97a0aa856b69806b3816a4db74e0b88a464b26a1 Merge: afbde8050 d86caadb0 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 27 16:22:32 2020 +0200 Merge remote-tracking branch 'origin/hicum2-thermal' into markus_dev commit afbde805009884b532fb9cad37827d2a4f6464ab Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 27 16:21:25 2020 +0200 zwischenstand commit d86caadb07482926593ce3cfc1dce53ebc009341 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 18:23:40 2020 +0200 added nodes for NQS commit 1b0cf0d08c7ca282dba8f1fbecf05b391324ef95 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 16:59:55 2020 +0200 testing with and without self heating commit 64c0c41180420b205b1eae1237634d31ffd2d1a5 Merge: 9da946bf2 0d0c6a080 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 16:29:18 2020 +0200 Merge branch 'markus_dev' into hicum2-thermal commit 0d0c6a0800681868ad8aa3f14367d1f81936e593 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 16:26:37 2020 +0200 assigned the temperature derivates to me commit 1b00fad771d6cd34b5bb3fd1fc5a1d23bcc87790 Merge: f5a1c35d8 dc7891f7b Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 14:16:32 2020 +0200 Merge branch 'markus_dev' of ssh://git.code.sf.net/p/ngspice/ngspice into markus_dev commit f5a1c35d803a2406e114133bb469705acd2fb7e5 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 23 14:14:40 2020 +0200 removed dummdumm commit dc7891f7b543b1f9651ed25e5632c631f402df49 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 19:16:36 2020 +0200 added more junction caps, checklist and overview commit 0dbf31bc739938eecc281656a3141085ffc4df42 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 19:00:16 2020 +0200 derivatives rbi commit 330d009fa684295f78f6b669fae2c663f7f4fe26 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 18:40:24 2020 +0200 more derivatives avalanche current, ibcis commit ce200d75e337c7cb684391b2d7556f6c2d8c8804 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 18:05:49 2020 +0200 derivatives peripheral junction caps, diodes commit 8ce9733f9176d5220c8db8c4deb322eb64f4ad1a Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 17:45:42 2020 +0200 derivatives tunneling current commit 806ff8013825cc154f11f2206644d0d8be825ecb Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 17:17:14 2020 +0200 derivatives critical current commit 8f49490cecf43ee22aecebcccb16752bc5a1728f Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 16:59:09 2020 +0200 derivatives T_f0 commit 3164dbe594025e16d8dfbd1c50922dbcac70e62a Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 16:38:34 2020 +0200 derivatives hole charge at low bias commit b32bf6dd149a218e74af389f3a7bea9adcc89f22 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 16:27:38 2020 +0200 zwischenstand commit 84307c4acfb72aeb0cf9acbd0ca64223a58a20cb Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 16:19:25 2020 +0200 zwischenstand commit 0d94c5d56d86c52ab0638e095d7c6b816723929f Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 20 10:56:58 2020 +0200 moved cppduals to system lib include commit 9da946bf2d5beaa1a1e74c0465d78bfd079bc320 Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 20 09:59:49 2020 +0200 started derivatives of hicum2 minority charge commit a2946e98a442e32fab493bcbd8d05ca934c20e20 Author: Markus Mueller <metroid120@googlemail.com> Date: Mon Apr 20 09:56:06 2020 +0200 introduced dual numbers, ported hiucm2load to c++ hicumL2.cpp, boolean type protected by extern "C" commit c7e5df27dbd5b74586d64c9404166e67a1c7af62 Author: mariok <mario.krattenmacher@web.de> Date: Thu Apr 16 14:44:41 2020 +0200 DC runs with Ixf commit 08a0e6a019957ba9c29ee96653254880b26c8c98 Author: mariok <mario.krattenmacher@web.de> Date: Wed Apr 15 18:15:26 2020 +0200 gummel works with flsh = 1 and flnqs = 0 commit b83e05ee95c6d9771189e54ce6834519d71071c3 Author: mariok <mario.krattenmacher@web.de> Date: Tue Apr 14 16:09:42 2020 +0200 added test to makefile commit 7d29a9a269cb405c71fd64249c5b439b87a64cc3 Author: mariok <mario.krattenmacher@web.de> Date: Tue Apr 14 10:06:27 2020 +0200 test circuit and results commit 14c46bc3bd3f2f2a4f333ef8e85e2d35dcfd8cc5 Author: mariok <mario.krattenmacher@web.de> Date: Mon Apr 13 18:12:06 2020 +0200 cleaned renaming in all files commit 67ddd98f7520d6cd729bbb5ca927859bb3d3f2b0 Author: dwarning <dwarning> Date: Wed Jan 29 13:08:02 2020 +0100 rename commit 9551b6df924e455bde48d5da3077dcd764d95761 Author: dwarning <dwarning> Date: Wed Jan 29 13:07:42 2020 +0100 rename commit 12bb866ba5d2481b09f6c9adc17ec21ed3038534 Author: dwarning <dwarning> Date: Wed Jan 29 13:06:45 2020 +0100 rename commit 414eeb4067249d3065181e308ffe7eb815a6f181 Author: dwarning <dwarning> Date: Tue Jan 28 22:18:08 2020 +0100 clarify charge and capacitance implementation commit c318ef15eefd0a0517cb35f4a4403a8e8cd00e17 Author: dwarning <dwarning> Date: Sat Jan 25 14:57:55 2020 +0100 introduce first excess phase network and update to 2.4.0 commit 85c34cfb0f2b594febbd0adcb315ebb4e5499748 Author: dwarning <dwarning> Date: Wed Jan 22 18:16:54 2020 +0100 VS update commit 86ff2778f8ffcce688e8e08099801d920d6a3927 Author: dwarning <dwarning> Date: Wed Jan 22 18:16:29 2020 +0100 OP infos commit 1607f4d88c026fd573e19a16793208c48b025612 Author: dwarning <dwarning> Date: Wed Jan 22 18:16:19 2020 +0100 OP infos commit ca1e114922fecc11a4245a04f5639c11d539be8f Author: dwarning <dwarning> Date: Wed Jan 22 18:16:11 2020 +0100 OP infos commit 408440d33b65741a7cd1171a9023f13cfb180e15 Author: dwarning <dwarning> Date: Tue Jan 21 11:25:56 2020 +0100 some cleanings commit 3364f6da87f79763344fd0f9ef705b521e23ee09 Author: dwarning <dwarning> Date: Tue Jan 14 09:55:58 2020 +0100 VS update commit 6fbefe4afa0fd1355eab636756ae592bad8b501f Author: dwarning <dwarning> Date: Tue Jan 14 09:55:48 2020 +0100 Ongoing derivations commit 86521dd7c0e067644765e4de450b2eead9a1c24a Author: dwarning <dwarning> Date: Tue Jan 14 09:02:52 2020 +0100 VS update commit ba5b106faeecc3170c3d018ec10b0a388c12e2cf Author: dwarning <dwarning> Date: Tue Jan 14 09:01:30 2020 +0100 Ongoing derivations commit ea6254eca3b21fb3c7044eee00053cfce170034f Author: dwarning <dwarning> Date: Sat Jan 11 17:17:21 2020 +0100 Initial HICUM2 integration commit 2bd0f1bdab6161ec21f790c4908590fcafa9b818 Author: dwarning <dwarning> Date: Mon Jan 6 00:11:48 2020 +0100 Initial HICUM2 integration commit 7d160f659e46021c0da882ea84ce4868ecd0acc0 Author: dwarning <dwarning> Date: Sun Jan 5 15:01:20 2020 +0100 Initial HICUM2 integration commit 420ca90e55bb77a3999527f25fa985146c6a1ef3 Author: dwarning <dwarning> Date: Sun Jan 5 15:00:06 2020 +0100 Initial HICUM2 integration
committed by
Holger Vogt
301 changed files with 109852 additions and 48 deletions
-
3.gitignore
-
11configure.ac
-
42examples/hicum2/hic2_ft.sp
-
24examples/hicum2/hic2_gain.sp
-
20examples/hicum2/hic2_gum.sp
-
18examples/hicum2/hic2_gum_inv.sp
-
31examples/hicum2/hic2_noise.sp
-
65examples/hicum2/hic2_noise_I.sp
-
65examples/hicum2/hic2_noise_V.sp
-
44examples/hicum2/hic2_noise_ver.sp
-
21examples/hicum2/hic2_out.sp
-
27examples/hicum2/hic2_tran.sp
-
175examples/hicum2/model-card-examples.lib
-
2src/Makefile.am
-
41src/include/cppduals/.appveyor.yml
-
18src/include/cppduals/.editorconfig
-
87src/include/cppduals/.gitlab-ci.yml
-
223src/include/cppduals/CMakeLists.txt
-
373src/include/cppduals/LICENSE.txt
-
354src/include/cppduals/README.md
-
2391src/include/cppduals/doc/Doxyfile.in
-
195src/include/cppduals/doc/DoxygenLayout.xml
-
12src/include/cppduals/doc/Greek_Epsilon_archaic.svg
-
2059src/include/cppduals/doc/customdoxygen.css
-
BINsrc/include/cppduals/doc/favicon.ico
-
20src/include/cppduals/doc/footer.html
-
200src/include/cppduals/doc/gitlab-release
-
57src/include/cppduals/doc/header.html
-
510src/include/cppduals/duals/arch/AVX/ComplexDual.h
-
548src/include/cppduals/duals/arch/AVX/Dual.h
-
229src/include/cppduals/duals/arch/SSE/ComplexDual.h
-
459src/include/cppduals/duals/arch/SSE/Dual.h
-
1384src/include/cppduals/duals/dual
-
774src/include/cppduals/duals/dual_eigen
-
BINsrc/include/cppduals/paper/benchmark.png
-
86src/include/cppduals/paper/paper.bib
-
164src/include/cppduals/paper/paper.md
-
240src/include/cppduals/tests/CMakeLists.txt
-
88src/include/cppduals/tests/bench_dual.cpp
-
398src/include/cppduals/tests/bench_eigen.cpp
-
74src/include/cppduals/tests/bench_example.cpp
-
109src/include/cppduals/tests/bench_fmt.cpp
-
244src/include/cppduals/tests/bench_gemm.cpp
-
43src/include/cppduals/tests/example.cpp
-
472src/include/cppduals/tests/gold-riick.bench_dual.json
-
1160src/include/cppduals/tests/gold-riick.bench_eigen.json
-
142src/include/cppduals/tests/runbench.sh
-
122src/include/cppduals/tests/sandbox.cpp
-
208src/include/cppduals/tests/test_1.cpp
-
1108src/include/cppduals/tests/test_dual.cpp
-
549src/include/cppduals/tests/test_eigen.cpp
-
215src/include/cppduals/tests/test_expm.cpp
-
213src/include/cppduals/tests/test_fmt.cpp
-
215src/include/cppduals/tests/test_funcs.cpp
-
402src/include/cppduals/tests/test_packets.cpp
-
119src/include/cppduals/tests/test_solve.cpp
-
342src/include/cppduals/tests/test_vectorize.cpp
-
106src/include/cppduals/tests/type_name.hpp
-
17src/include/cppduals/thirdparty/CMakeLists-gt.txt.in
-
220src/include/cppduals/thirdparty/CMakeLists.txt
-
4src/include/ngspice/bool.h
-
7src/include/ngspice/cktdefs.h
-
2src/spicelib/devices/Makefile.am
-
8src/spicelib/devices/dev.c
-
1src/spicelib/devices/dio/dioload.c
-
33src/spicelib/devices/hicum2/Makefile.am
-
304src/spicelib/devices/hicum2/hicum2.c
-
645src/spicelib/devices/hicum2/hicum2acld.c
-
251src/spicelib/devices/hicum2/hicum2ask.c
-
221src/spicelib/devices/hicum2/hicum2conv.c
-
1180src/spicelib/devices/hicum2/hicum2defs.h
-
27src/spicelib/devices/hicum2/hicum2ext.h
-
51src/spicelib/devices/hicum2/hicum2getic.c
-
85src/spicelib/devices/hicum2/hicum2init.c
-
20src/spicelib/devices/hicum2/hicum2init.h
-
11src/spicelib/devices/hicum2/hicum2itf.h
-
460src/spicelib/devices/hicum2/hicum2mask.c
-
634src/spicelib/devices/hicum2/hicum2mpar.c
-
293src/spicelib/devices/hicum2/hicum2noise.c
-
70src/spicelib/devices/hicum2/hicum2param.c
-
758src/spicelib/devices/hicum2/hicum2pzld.c
-
863src/spicelib/devices/hicum2/hicum2setup.c
-
73src/spicelib/devices/hicum2/hicum2soachk.c
-
43src/spicelib/devices/hicum2/hicum2trunc.c
-
3350src/spicelib/devices/hicum2/hicumL2.cpp
-
23src/spicelib/devices/hicum2/hicumL2.hpp
-
521src/spicelib/devices/hicum2/hicumL2temp.cpp
-
17src/spicelib/devices/hicum2/hicumL2temp.hpp
-
6src/spicelib/parser/inp2q.c
-
2src/spicelib/parser/inpdomod.c
-
1tests/Makefile.am
-
686tests/bin/ads.pm
-
2tests/bin/ngspice.pm
-
17tests/bin/run_cmc_check
-
37tests/hicum2/FG.cir
-
112tests/hicum2/FG.out
-
34tests/hicum2/FG_sh.cir
-
15tests/hicum2/Makefile.am
-
41tests/hicum2/npn/parameters/compare_para.pl
-
125tests/hicum2/npn/parameters/npn_1D
@ -0,0 +1,42 @@ |
|||||
|
HICUM2v2.40 Test ft=f(Ic) Vce=1V |
||||
|
|
||||
|
vce 1 0 dc 1.0 |
||||
|
vgain 1 c dc 0.0 |
||||
|
f 0 2 vgain -2 |
||||
|
l 2 b 1g |
||||
|
c 2 0 1g |
||||
|
ib 0 b dc 0.0 ac 1.0 |
||||
|
ic 0 c 0.001 |
||||
|
Q1 C B 0 hicumL2V2p40 |
||||
|
|
||||
|
.control |
||||
|
let run = 0 |
||||
|
let ft_runs = 9 |
||||
|
set curplot=new $ create a new plot |
||||
|
set curplotname=ft_plot |
||||
|
set curplottitle="HICUM2v2.40 ft = f(Ic)" |
||||
|
set scratch=$curplot $ store its name to 'scratch' |
||||
|
setplot $scratch $ make 'scratch' the active plot |
||||
|
let ft=unitvec(ft_runs) $ create a vector in plot 'scratch' to store ft data |
||||
|
let ic=unitvec(ft_runs) $ create a vector in plot 'scratch' to store ic data |
||||
|
foreach myic 1e-03 3e-03 6e-03 9e-03 14e-03 21e-03 27e-03 33e-3 40e-03 |
||||
|
alter ic = $myic |
||||
|
op |
||||
|
print all |
||||
|
ac dec 100 1Meg 800g |
||||
|
meas ac freq_at when vdb(vgain#branch)=0 |
||||
|
set run ="$&run" $ create a variable from the vector |
||||
|
set dt = $curplot $ store the current plot to dt |
||||
|
setplot $scratch $ make 'scratch' the active plot |
||||
|
let ic[run] = $myic $ store ic to vector ft in plot 'scratch' |
||||
|
let ft[run] = {$dt}.freq_at $ store ft to vector ft in plot 'scratch' |
||||
|
setplot $dt $ go back to the previous plot |
||||
|
let run = run + 1 |
||||
|
end |
||||
|
setplot unknown1 |
||||
|
plot ft vs ic xlog |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,24 @@ |
|||||
|
HICUM2v2.40 AC gain Test h21 = f(Ic) Vce=1V |
||||
|
|
||||
|
vce 1 0 dc 1.0 |
||||
|
vgain 1 c dc 0.0 |
||||
|
f 0 2 vgain -2 |
||||
|
l 2 b 1g |
||||
|
c 2 0 1g |
||||
|
ib 0 b dc 0.0 ac 1.0 |
||||
|
ic 0 c 0.001 |
||||
|
Q1 C B 0 hicumL2V2p40 |
||||
|
|
||||
|
.control |
||||
|
foreach myic 2e-03 4e-03 7e-03 9e-03 18e-03 33e-3 |
||||
|
alter ic = $myic |
||||
|
op |
||||
|
print all |
||||
|
ac dec 10 1Meg 800g |
||||
|
end |
||||
|
plot abs(ac1.vgain#branch) abs(ac2.vgain#branch) abs(ac3.vgain#branch) abs(ac4.vgain#branch) abs(ac5.vgain#branch) abs(ac6.vgain#branch) ylimit 0.1 300 loglog |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,20 @@ |
|||||
|
HICUM2v2.40 Gummel Test Ic,b,s=f(Vc,Ib) Vce=1V |
||||
|
|
||||
|
VB B 0 1.2 |
||||
|
VC C 0 1.0 |
||||
|
VS S 0 0.0 |
||||
|
|
||||
|
Q1 C B 0 S hicumL2V2p40 |
||||
|
|
||||
|
.control |
||||
|
option gmin=1e-14 |
||||
|
dc vb 0.2 1.2 0.01 |
||||
|
*plot i(vc) i(vb) i(vs) |
||||
|
*gnuplot fgum i(vc) i(vb) i(vs) xlimit 0.2 1.2 ylog ylimit 1e-12 0.1 |
||||
|
plot abs(i(vc)) abs(i(vb)) abs(i(vs)) xlimit 0.2 1.2 ylog ylimit 1e-14 0.1 |
||||
|
plot abs(i(vc))/abs(i(vb)) vs abs(i(vc)) xlog xlimit 1e-09 100e-3; ylimit 0 500 |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,18 @@ |
|||||
|
HICUM2v2.40 Gummel Test invers Ie,b,s=f(Ve,Ib) Vec=1V |
||||
|
|
||||
|
VB B 0 1.2 |
||||
|
VE E 0 1.0 |
||||
|
VS S 0 0.0 |
||||
|
|
||||
|
Q1 0 B E S hicumL2V2p40 |
||||
|
|
||||
|
.control |
||||
|
dc vb 0.2 1.2 0.01 |
||||
|
*plot i(ve) i(vb) i(vs) |
||||
|
plot abs(i(ve)) abs(i(vb)) abs(i(vs)) xlimit 0.2 1.2 ylog ylimit 1e-12 0.1 |
||||
|
plot abs(i(ve))/abs(i(vb)) vs abs(i(ve)) xlog xlimit 1e-06 100e-3 ylimit 0 50 |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,31 @@ |
|||||
|
HICUM2v2.40 Noise Test |
||||
|
|
||||
|
vcc 4 0 26 |
||||
|
vin 1 0 ac 1 |
||||
|
|
||||
|
ccouple 1 b 1 |
||||
|
|
||||
|
ibias 0 b 100uA |
||||
|
|
||||
|
rload 4 c 1k noisy=0 |
||||
|
|
||||
|
q1 c b 0 0 hicumL2V2p40 |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.control |
||||
|
op |
||||
|
print all |
||||
|
echo |
||||
|
noise v(c) vin dec 10 10 10G 1 |
||||
|
setplot |
||||
|
setplot noise1 |
||||
|
plot ally |
||||
|
plot inoise_spectrum onoise_spectrum loglog |
||||
|
setplot noise2 |
||||
|
print all |
||||
|
echo |
||||
|
print inoise_total onoise_total |
||||
|
.endc |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,65 @@ |
|||||
|
HICUM2v2.40 Noise Current Test |
||||
|
|
||||
|
* _______ |
||||
|
* _|_ _|_ |
||||
|
* /// / _ \ |
||||
|
* \/ \/ I1 |
||||
|
* /\_/\ |
||||
|
* R1 \___/ |
||||
|
* _/\ __| |
||||
|
* | \/ _| |
||||
|
* |____|' |
||||
|
* B |`-> |
||||
|
* _|_ E |
||||
|
* /VIN\ |
||||
|
* \___/ |
||||
|
* _|_ |
||||
|
* /// |
||||
|
* |
||||
|
* |
||||
|
|
||||
|
vin E 0 DC 0.0 ac 1.0u |
||||
|
I1 0 C 1uA |
||||
|
R1 C B 1000k noisy=0 |
||||
|
q1 C B E hicumL2V2p40 |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.control |
||||
|
setplot new |
||||
|
|
||||
|
let V1u = 0*vector(81) |
||||
|
let V10u = 0*vector(81) |
||||
|
let V100u = 0*vector(81) |
||||
|
let V1000u = 0*vector(81) |
||||
|
|
||||
|
op |
||||
|
noise v(C) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V1u = sqrt(v(onoise_spectrum))*1u |
||||
|
|
||||
|
alter I1 dc = 10u |
||||
|
op |
||||
|
noise v(C) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V10u = sqrt(v(onoise_spectrum))*1u |
||||
|
|
||||
|
alter I1 dc = 100u |
||||
|
op |
||||
|
noise v(C) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V100u = sqrt(v(onoise_spectrum))*1u |
||||
|
|
||||
|
alter I1 dc = 1000u |
||||
|
op |
||||
|
noise v(C) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V1000u = sqrt(v(onoise_spectrum))*1u |
||||
|
|
||||
|
|
||||
|
set pensize = 2 |
||||
|
plot unknown1.V1u unknown1.V10u unknown1.V100u unknown1.V1000u vs frequency loglog title LM394NoiseCurrent |
||||
|
|
||||
|
echo " ... done." |
||||
|
.endcontrol |
||||
|
.end |
||||
@ -0,0 +1,65 @@ |
|||||
|
HICUM2v2.40 Noise Voltage Test |
||||
|
|
||||
|
* _______ |
||||
|
* _|_ _|_ |
||||
|
* /// / _ \ |
||||
|
* \/ \/ I1 |
||||
|
* /\_/\ |
||||
|
* \___/ |
||||
|
* _______| |
||||
|
* | _| |
||||
|
* |____|' |
||||
|
* B |`-> |
||||
|
* _|_ E |
||||
|
* /VIN\ |
||||
|
* \___/ |
||||
|
* _|_ |
||||
|
* /// |
||||
|
* |
||||
|
* |
||||
|
|
||||
|
vin E 0 DC 0.0 ac 1.0u |
||||
|
I1 0 B 1uA |
||||
|
q1 B B E hicumL2V2p40 |
||||
|
|
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.control |
||||
|
setplot new |
||||
|
|
||||
|
let V1u = 0*vector(81) |
||||
|
let V10u = 0*vector(81) |
||||
|
let V100u = 0*vector(81) |
||||
|
let V1000u = 0*vector(81) |
||||
|
|
||||
|
op |
||||
|
noise v(B) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V1u = sqrt(v(onoise_spectrum)) |
||||
|
|
||||
|
alter I1 dc = 10u |
||||
|
op |
||||
|
noise v(B) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V10u = sqrt(v(onoise_spectrum)) |
||||
|
|
||||
|
alter I1 dc = 100u |
||||
|
op |
||||
|
noise v(B) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V100u = sqrt(v(onoise_spectrum)) |
||||
|
|
||||
|
alter I1 dc = 1000u |
||||
|
op |
||||
|
noise v(B) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
let unknown1.V1000u = sqrt(v(onoise_spectrum)) |
||||
|
|
||||
|
|
||||
|
set pensize = 2 |
||||
|
plot unknown1.V1u unknown1.V10u unknown1.V100u unknown1.V1000u vs frequency loglog title HICUM_NoiseVoltage |
||||
|
|
||||
|
echo " ... done." |
||||
|
.endcontrol |
||||
|
.end |
||||
@ -0,0 +1,44 @@ |
|||||
|
HICUM2v2.40 Noise Voltage Test |
||||
|
|
||||
|
* _______ |
||||
|
* _|_ _|_ |
||||
|
* /// / _ \ |
||||
|
* \/ \/ I1 |
||||
|
* /\_/\ |
||||
|
* \___/ |
||||
|
* _______| |
||||
|
* | _| |
||||
|
* |____|' |
||||
|
* B |`-> |
||||
|
* _|_ E |
||||
|
* /VIN\ |
||||
|
* \___/ |
||||
|
* _|_ |
||||
|
* /// |
||||
|
* |
||||
|
* |
||||
|
|
||||
|
vin E 0 DC 0.0 ac 1.0u |
||||
|
I1 0 B 25mA |
||||
|
q1 B B E hicumL2V2p40 |
||||
|
|
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.control |
||||
|
setplot new |
||||
|
|
||||
|
let V1u = 0*vector(81) |
||||
|
|
||||
|
op |
||||
|
noise v(B) vin dec 10 1 100Meg 1 |
||||
|
destroy |
||||
|
*let unknown1.V1u = sqrt(v(onoise_spectrum)) |
||||
|
let unknown1.V1u = v(onoise_spectrum) |
||||
|
|
||||
|
set pensize = 2 |
||||
|
plot unknown1.V1u vs frequency loglog title HICUM_NoiseVoltage |
||||
|
|
||||
|
echo " ... done." |
||||
|
.endcontrol |
||||
|
.end |
||||
@ -0,0 +1,21 @@ |
|||||
|
HICUM2v2.40 Output Test Ic=f(Vc,Ib) |
||||
|
|
||||
|
IB 0 B 1u |
||||
|
VC C 0 1.8 |
||||
|
VS S 0 0.0 |
||||
|
|
||||
|
Q1 C B 0 S tj hicumL2V2p40 |
||||
|
|
||||
|
.control |
||||
|
dc vc 0.0 1.8 0.01 ib 10u 100u 10u |
||||
|
plot -i(vc) |
||||
|
reset |
||||
|
altermod @hicumL2V2p40[flsh]=1 |
||||
|
dc vc 0.0 1.8 0.01 ib 1u 10u 1u |
||||
|
plot -i(vc) |
||||
|
plot v(tj) |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,27 @@ |
|||||
|
HICUM2v2.40 Amplifier in Time Domain |
||||
|
|
||||
|
vcc 2 0 2.5 |
||||
|
*vin 1 0 ac 1 dc 0 sin 0 25m 1G |
||||
|
vin 1 0 ac 1 dc 0 pulse 0 50m 0 5p 5p 4n 8n |
||||
|
rs 1 in 50 |
||||
|
c1 in b 1n |
||||
|
r1 2 c 180 |
||||
|
r2 c b 5k |
||||
|
q1 c b 0 0 hicuml2v2p40 |
||||
|
c2 c out 100p |
||||
|
r3 out 0 1k |
||||
|
|
||||
|
.ic v(c)=0.9 |
||||
|
.control |
||||
|
option method=gear |
||||
|
op |
||||
|
print all |
||||
|
ac dec 10 1Meg 9.9g |
||||
|
plot vdb(out) |
||||
|
tran 2p 200n |
||||
|
plot v(in) v(out) |
||||
|
.endc |
||||
|
|
||||
|
.include model-card-examples.lib |
||||
|
|
||||
|
.end |
||||
@ -0,0 +1,175 @@ |
|||||
|
* Example parameter test set |
||||
|
.model hicumL2V2p40 npn level=8 |
||||
|
* |
||||
|
*Transfer current |
||||
|
+ c10 = 9.074e-030 |
||||
|
+ qp0 = 1.008e-013 |
||||
|
+ ich = 0 |
||||
|
+ hf0 = 40 |
||||
|
+ hfe = 10.01 |
||||
|
+ hfc = 20.04 |
||||
|
+ hjei = 3.382 |
||||
|
+ ahjei = 3 |
||||
|
+ rhjei = 2 |
||||
|
+ hjci = 0.2 |
||||
|
* |
||||
|
*Base-Emitter diode currents |
||||
|
+ ibeis = 1.328e-019 |
||||
|
+ mbei = 1.027 |
||||
|
+ ireis = 1.5e-015 |
||||
|
+ mrei = 2 |
||||
|
+ ibeps = 1.26e-019 |
||||
|
+ mbep = 1.042 |
||||
|
+ ireps = 1.8e-015 |
||||
|
+ mrep = 1.8 |
||||
|
+ mcf = 1 |
||||
|
* |
||||
|
*Transit time for excess recombination current at b-c barrier |
||||
|
+ tbhrec = 1e-010 |
||||
|
* |
||||
|
*Base-Collector diode currents |
||||
|
+ ibcis = 4.603e-017 |
||||
|
+ mbci = 1.15 |
||||
|
+ ibcxs = 0 |
||||
|
+ mbcx = 1 |
||||
|
* |
||||
|
*Base-Emitter tunneling current |
||||
|
+ ibets = 0.02035 |
||||
|
+ abet = 24 |
||||
|
+ tunode = 1 |
||||
|
* |
||||
|
*Base-Collector avalanche current |
||||
|
+ favl = 18.96 |
||||
|
+ qavl = 5.092e-014 |
||||
|
+ alfav = -0.0024 |
||||
|
+ alqav = -0.0006284 |
||||
|
+ kavl = 0.0 |
||||
|
+ alkav = 0.0 |
||||
|
* |
||||
|
*Series resistances |
||||
|
+ rbi0 = 4.444 |
||||
|
+ rbx = 2.568 |
||||
|
+ fgeo = 0.7409 |
||||
|
+ fdqr0 = 0 |
||||
|
+ fcrbi = 0 |
||||
|
+ fqi = 1 |
||||
|
+ re = 1.511 |
||||
|
+ rcx = 2.483 |
||||
|
* |
||||
|
*Substrate transistor |
||||
|
+ itss = 1.143e-017 |
||||
|
+ msf = 1.056 |
||||
|
+ iscs = 4.60106e-015 |
||||
|
+ msc = 1.018 |
||||
|
+ tsf = 0 |
||||
|
* |
||||
|
*Intra-device substrate coupling |
||||
|
+ rsu = 500 |
||||
|
+ csu = 6.4e-014 |
||||
|
* |
||||
|
*Depletion Capacitances |
||||
|
+ cjei0 = 8.869e-015 |
||||
|
+ vdei = 0.714 |
||||
|
+ zei = 0.2489 |
||||
|
+ ajei = 1.65 |
||||
|
+ cjep0 = 2.178e-015 |
||||
|
+ vdep = 0.8501 |
||||
|
+ zep = 0.2632 |
||||
|
+ ajep = 1.6 |
||||
|
+ cjci0 = 3.58e-015 |
||||
|
+ vdci = 0.8201 |
||||
|
+ zci = 0.2857 |
||||
|
+ vptci = 1.79 |
||||
|
+ cjcx0 = 6.299e-015 |
||||
|
+ vdcx = 0.8201 |
||||
|
+ zcx = 0.2863 |
||||
|
+ vptcx = 1.977 |
||||
|
+ fbcpar = 0.3 |
||||
|
+ fbepar = 1 |
||||
|
+ cjs0 = 2.6e-014 |
||||
|
+ vds = 0.9997 |
||||
|
+ zs = 0.4295 |
||||
|
+ vpts = 100 |
||||
|
+ cscp0 = 1.4e-014 |
||||
|
+ vdsp = 0 |
||||
|
+ zsp = 0.35 |
||||
|
+ vptsp = 4 |
||||
|
* |
||||
|
*Diffusion Capacitances |
||||
|
+ t0 = 2.089e-013 |
||||
|
+ dt0h = 8e-014 |
||||
|
+ tbvl = 8.25e-014 |
||||
|
+ tef0 = 3.271e-013 |
||||
|
+ gtfe = 3.548 |
||||
|
+ thcs = 5.001e-012 |
||||
|
+ ahc = 0.05 |
||||
|
+ fthc = 0.7 |
||||
|
+ rci0 = 9.523 |
||||
|
+ vlim = 0.6999 |
||||
|
+ vces = 0.01 |
||||
|
+ vpt = 2 |
||||
|
+ aick = 1e-3 |
||||
|
+ delck = 2 |
||||
|
+ tr = 0 |
||||
|
+ vcbar = 0.04 |
||||
|
+ icbar = 0.01 |
||||
|
+ acbar = 1.5 |
||||
|
* |
||||
|
*Isolation Capacitances |
||||
|
+ cbepar = 2.609e-014 |
||||
|
+ cbcpar = 1.64512e-014 |
||||
|
* |
||||
|
*Non-quasi-static Effect |
||||
|
+ flnqs = 0 |
||||
|
+ alqf = 0.166667 |
||||
|
+ alit = 0.333333 |
||||
|
* |
||||
|
*Noise |
||||
|
+ kf = .3e-16 |
||||
|
+ af = .75 |
||||
|
+ cfbe = -1 |
||||
|
+ flcono = 0 |
||||
|
+ kfre = 0.0 |
||||
|
+ afre = 2.0 |
||||
|
* |
||||
|
*Lateral Geometry Scaling (at high current densities) |
||||
|
+ latb = 0.0 |
||||
|
+ latl = 0.0 |
||||
|
* |
||||
|
*Temperature dependence |
||||
|
+ vgb = 0.91 |
||||
|
+ alt0 = 0.004 |
||||
|
+ kt0 = 6.588e-005 |
||||
|
+ zetaci = 0.58 |
||||
|
+ alvs = 0.001 |
||||
|
+ alces = -0.2286 |
||||
|
+ zetarbi = 0.3002 |
||||
|
+ zetarbx = 0.06011 |
||||
|
+ zetarcx = -0.02768 |
||||
|
+ zetare = -0.9605 |
||||
|
+ zetacx = 0 |
||||
|
+ vge = 1.17 |
||||
|
+ vgc = 1.17 |
||||
|
+ vgs = 1.049 |
||||
|
+ f1vg = -0.000102377 |
||||
|
+ f2vg = 0.00043215 |
||||
|
+ zetact = 5 |
||||
|
+ zetabet = 4.892 |
||||
|
+ alb = 0 |
||||
|
+ dvgbe = 0 |
||||
|
+ zetahjei = -0.5 |
||||
|
+ zetavgbe = 0.7 |
||||
|
* |
||||
|
*Self-Heating |
||||
|
+ flsh = 0 |
||||
|
+ rth = 1113.4 |
||||
|
+ cth = 6.841e-012 |
||||
|
+ zetarth = 0 |
||||
|
+ alrth = 0.002 |
||||
|
* |
||||
|
*Compatibility with V2.1 |
||||
|
+ flcomp = 2.3 |
||||
|
* |
||||
|
*Circuit simulator specific parameters |
||||
|
+ tnom = 26.85 |
||||
|
*+ dt = 0 |
||||
@ -0,0 +1,41 @@ |
|||||
|
version: 0.2.{build} |
||||
|
clone_folder: c:\projects\cppduals |
||||
|
clone_depth: 3 |
||||
|
|
||||
|
image: |
||||
|
#- Visual Studio 2013 |
||||
|
#- Visual Studio 2015 |
||||
|
- Visual Studio 2017 |
||||
|
|
||||
|
configuration: |
||||
|
- Release |
||||
|
#- Debug # someone with a debugger please investigate this :) |
||||
|
|
||||
|
# Do not build feature branch with open Pull Requests |
||||
|
skip_branch_with_pr: true |
||||
|
|
||||
|
# skip unsupported combinations |
||||
|
init: |
||||
|
- echo %APPVEYOR_BUILD_WORKER_IMAGE% |
||||
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" ( set generator="Visual Studio 12 2013" ) |
||||
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" ( set generator="Visual Studio 14 2015" ) |
||||
|
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" ( set generator="Visual Studio 15 2017" ) |
||||
|
- echo %generator% |
||||
|
|
||||
|
before_build: |
||||
|
- cmd: |- |
||||
|
mkdir build |
||||
|
cd build |
||||
|
cmake --version |
||||
|
cmake .. -G %generator% -DCPPDUALS_TESTING=ON |
||||
|
pwd |
||||
|
ls |
||||
|
|
||||
|
build: |
||||
|
project: c:\projects\cppduals\build\cppduals.sln |
||||
|
verbosity: minimal |
||||
|
# parallel: true |
||||
|
|
||||
|
test_script: |
||||
|
- pwd |
||||
|
- ctest -C Debug -VV |
||||
@ -0,0 +1,18 @@ |
|||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
end_of_line = lf |
||||
|
insert_final_newline = true |
||||
|
charset = utf-8 |
||||
|
|
||||
|
[*.{cpp,hpp,h}] |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
|
|
||||
|
[{duals/**,tests/**}] |
||||
|
trim_trailing_whitespace = true |
||||
|
|
||||
|
[CMakeLists.txt] |
||||
|
trim_trailing_whitespace = true |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
@ -0,0 +1,87 @@ |
|||||
|
#image: ubuntu:19.04 |
||||
|
image: fedora:30 |
||||
|
|
||||
|
variables: |
||||
|
GIT_DEPTH: 3 |
||||
|
CTEST_OUTPUT_ON_FAILURE: y |
||||
|
|
||||
|
stages: |
||||
|
- build |
||||
|
- test |
||||
|
- cover |
||||
|
- publish |
||||
|
|
||||
|
before_script: |
||||
|
#- apt-get update --yes |
||||
|
#- apt-get install --yes cmake g++ git doxygen lcov graphviz |
||||
|
- dnf install -y gcc-c++ make cmake git doxygen lcov graphviz |
||||
|
|
||||
|
build: |
||||
|
stage: build |
||||
|
# variables: |
||||
|
# CC: clang |
||||
|
# CXX: clang++ |
||||
|
script: |
||||
|
- echo $CXX |
||||
|
- cmake -Bbuild -H. -DCPPDUALS_TESTING=ON |
||||
|
- cmake --build build |
||||
|
- cmake -Bbuild-latest -H. -DCPPDUALS_TESTING=ON -DCPPDUALS_EIGEN_LATEST=ON |
||||
|
- cmake --build build-latest |
||||
|
artifacts: |
||||
|
expire_in: 1 week |
||||
|
paths: |
||||
|
- build |
||||
|
- build-latest |
||||
|
|
||||
|
test: |
||||
|
stage: test |
||||
|
script: |
||||
|
- cmake --build build --target test |
||||
|
- cmake --build build-latest --target test |
||||
|
dependencies: |
||||
|
- build |
||||
|
|
||||
|
cover: |
||||
|
script: |
||||
|
- cmake -Bbuild-cov -H. -DCODE_COVERAGE=ON -DCPPDUALS_TESTING=ON |
||||
|
- cmake --build build-cov --target cov |
||||
|
- cmake --build build-cov --target cov-html |
||||
|
coverage: '/Total:|\w*\d+\.\d+/' |
||||
|
artifacts: |
||||
|
expire_in: 1 day |
||||
|
paths: |
||||
|
- build-cov |
||||
|
only: |
||||
|
- merge_requests |
||||
|
|
||||
|
pages: |
||||
|
script: |
||||
|
- cmake -Bbuild -H. -DCODE_COVERAGE=ON -DCPPDUALS_TESTING=ON |
||||
|
- cmake --build build --target cppduals_docs |
||||
|
- cmake --build build --target cov-html |
||||
|
- mv build/docs public/ |
||||
|
- mv build/coverage public/ |
||||
|
coverage: '/Total:|\w*\d+\.\d+/' |
||||
|
artifacts: |
||||
|
paths: |
||||
|
- public |
||||
|
only: |
||||
|
- master |
||||
|
|
||||
|
publish: |
||||
|
stage: publish |
||||
|
dependencies: |
||||
|
- build |
||||
|
environment: |
||||
|
name: publish |
||||
|
only: |
||||
|
- /^v\d+\.\d+\.\d+$/ |
||||
|
except: |
||||
|
- branches |
||||
|
before_script: |
||||
|
- dnf install -y python3-requests |
||||
|
script: |
||||
|
# - ln -s cppduals-h-${CI_BUILD_TAG#v} . |
||||
|
# - tar czvhf cppduals-h-${CI_BUILD_TAG#v}.tgz cppduals-h-${CI_BUILD_TAG#v}/duals cppduals-h-${CI_BUILD_TAG#v}/CMakeLists.txt |
||||
|
- tar czvf cppduals-h-${CI_BUILD_TAG#v}.tgz duals CMakeLists.txt |
||||
|
- ./doc/gitlab-release --message "Release ${CI_BUILD_TAG}" cppduals-h-${CI_BUILD_TAG#v}.tgz |
||||
@ -0,0 +1,223 @@ |
|||||
|
# |
||||
|
# CMake for cppduals |
||||
|
# |
||||
|
cmake_minimum_required (VERSION 3.1) |
||||
|
project (cppduals |
||||
|
VERSION 0.3.1 |
||||
|
LANGUAGES C CXX |
||||
|
) |
||||
|
include (GNUInstallDirs) |
||||
|
|
||||
|
set (CMAKE_CXX_STANDARD 11 CACHE STRING "Which C++ standard to test against.") |
||||
|
set (CMAKE_CXX_STANDARD_REQUIRED ON) |
||||
|
set (CMAKE_DISABLE_IN_SOURCE_BUILD ON) |
||||
|
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) |
||||
|
message (STATUS "Configuring cppduals for standalone build") |
||||
|
set (CPPDUALS_STANDALONE TRUE) |
||||
|
elseif () |
||||
|
message (STATUS "Configuring cppduals for subproject build") |
||||
|
set (CPPDUALS_STANDALONE FALSE) |
||||
|
endif () |
||||
|
if (CPPDUALS_STANDALONE AND |
||||
|
NOT CMAKE_CONFIGURATION_TYPES AND |
||||
|
NOT CMAKE_NO_BUILD_TYPE AND |
||||
|
NOT CMAKE_BUILD_TYPE |
||||
|
) |
||||
|
message (STATUS "Setting build type to 'RelWithDebInfo' since none specified") |
||||
|
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY VALUE RelWithDebInfo) |
||||
|
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY |
||||
|
STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" |
||||
|
) |
||||
|
endif () |
||||
|
if (CPPDUALS_STANDALONE AND |
||||
|
CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) |
||||
|
set (CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" |
||||
|
CACHE PATH "cppduals installation directory" |
||||
|
FORCE |
||||
|
) |
||||
|
message (STATUS "No install prefix specified; using '${CMAKE_INSTALL_PREFIX}'") |
||||
|
endif () |
||||
|
|
||||
|
set_property (CACHE CMAKE_CXX_STANDARD PROPERTY STRINGS 11 14 17 20) |
||||
|
|
||||
|
option (CPPDUALS_TESTING "Enable testing" OFF) |
||||
|
option (CPPDUALS_BENCHMARK "Enable benchmarking" OFF) |
||||
|
option (CPPDUALS_EIGEN_LATEST "Eigen latest" OFF) |
||||
|
option (CPPDUALS_USE_LIBCXX "When testing use flags for libc++" OFF) |
||||
|
set (EIGEN3_INCLUDE_DIRS "" CACHE PATH "Path to Eigen includes" ) |
||||
|
|
||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR |
||||
|
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") |
||||
|
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wpedantic") |
||||
|
endif () |
||||
|
|
||||
|
if (CPPDUALS_BENCHMARK) |
||||
|
set (CPPDUALS_TESTING ON) |
||||
|
endif (CPPDUALS_BENCHMARK) |
||||
|
|
||||
|
if (CPPDUALS_USE_LIBCXX) |
||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") |
||||
|
add_compile_options ("-stdlib=libc++") |
||||
|
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ ") # -lc++abi |
||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR |
||||
|
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") |
||||
|
# this is unfinished... |
||||
|
set (CPPDUALS_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") |
||||
|
message (WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS") |
||||
|
list (APPEND CPPDUALS_CXX_LINKER_FLAGS -nodefaultlibs) |
||||
|
list (APPEND CPPDUALS_CXX_LIBRARIES c++) |
||||
|
else () |
||||
|
message(FATAL_ERROR "-DCPPDUALS_USE_LIBCXX:BOOL=ON is not supported for this compiler") |
||||
|
endif () |
||||
|
endif (CPPDUALS_USE_LIBCXX) |
||||
|
|
||||
|
# |
||||
|
# Primary Library Target |
||||
|
# |
||||
|
add_library (cppduals_duals INTERFACE) |
||||
|
target_include_directories (cppduals_duals |
||||
|
INTERFACE |
||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}> |
||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> |
||||
|
) |
||||
|
set_target_properties (cppduals_duals |
||||
|
PROPERTIES |
||||
|
EXPORT_NAME duals |
||||
|
) |
||||
|
add_library (cppduals::duals ALIAS cppduals_duals) |
||||
|
|
||||
|
# |
||||
|
# Build external dependencies for testing & benchmarking |
||||
|
# |
||||
|
if (CPPDUALS_TESTING) |
||||
|
|
||||
|
cmake_minimum_required (VERSION 3.10) # need gtest_discover_tests |
||||
|
file (MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty") |
||||
|
|
||||
|
# generator name |
||||
|
if (NOT "${CMAKE_EXTRA_GENERATOR}" STREQUAL "") |
||||
|
set (GENERATOR_STRING "${CMAKE_EXTRA_GENERATOR} - ${CMAKE_GENERATOR}") |
||||
|
else () |
||||
|
set (GENERATOR_STRING "${CMAKE_GENERATOR}") |
||||
|
endif () |
||||
|
|
||||
|
# configure the thirdparty build dir |
||||
|
execute_process ( |
||||
|
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty" |
||||
|
COMMAND ${CMAKE_COMMAND} "-G${GENERATOR_STRING}" |
||||
|
"-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" |
||||
|
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" |
||||
|
"-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}" |
||||
|
"-DCPPDUALS_BENCHMARK=${CPPDUALS_BENCHMARK}" |
||||
|
"-DCPPDUALS_EIGEN_LATEST=${CPPDUALS_EIGEN_LATEST}" |
||||
|
"-DCPPDUALS_USE_LIBCXX=${CPPDUALS_USE_LIBCXX}" |
||||
|
"${PROJECT_SOURCE_DIR}/thirdparty" |
||||
|
RESULT_VARIABLE DEPS_CONFIG_RESULT |
||||
|
) |
||||
|
if (DEPS_CONFIG_RESULT) |
||||
|
message (FATAL_ERROR "Configuring dependencies failed: ${DEPS_CONFIG_RESULT}") |
||||
|
endif () |
||||
|
|
||||
|
# build the thirdparty |
||||
|
message ("***************************************************************") |
||||
|
message ("** Building '${PROJECT_BINARY_DIR}/thirdparty'...") |
||||
|
message ("***************************************************************") |
||||
|
execute_process ( |
||||
|
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/thirdparty" |
||||
|
COMMAND "${CMAKE_COMMAND}" --build . |
||||
|
RESULT_VARIABLE DEPS_BUILD_RESULT |
||||
|
) |
||||
|
message ("***************************************************************") |
||||
|
message ("*** Building thirdparty/ done.") |
||||
|
message ("***************************************************************") |
||||
|
if (DEPS_BUILD_RESULT) |
||||
|
message ("***************************************************************") |
||||
|
message (FATAL_ERROR "Building dependencies failed: ${DEPS_BUILD_RESULT}") |
||||
|
message ("***************************************************************") |
||||
|
endif () |
||||
|
|
||||
|
add_subdirectory (thirdparty) |
||||
|
|
||||
|
endif () |
||||
|
|
||||
|
# |
||||
|
# Code Coverage Configuration |
||||
|
# |
||||
|
add_library (cppduals_coverage_config INTERFACE) |
||||
|
option (CODE_COVERAGE "Enable coverage reporting" OFF) |
||||
|
if (CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") |
||||
|
# Add required flags (GCC & LLVM/Clang) |
||||
|
target_compile_options (cppduals_coverage_config INTERFACE |
||||
|
-O0 # no optimization |
||||
|
-g # generate debug info |
||||
|
--coverage # sets all required flags |
||||
|
) |
||||
|
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) |
||||
|
target_link_options (cppduals_coverage_config INTERFACE --coverage) |
||||
|
else () |
||||
|
target_link_libraries (cppduals_coverage_config INTERFACE --coverage) |
||||
|
endif () |
||||
|
endif () |
||||
|
|
||||
|
# |
||||
|
# Testing |
||||
|
# |
||||
|
if (CPPDUALS_TESTING) |
||||
|
enable_testing () |
||||
|
include (CTest) |
||||
|
add_subdirectory (tests) |
||||
|
endif (CPPDUALS_TESTING) |
||||
|
|
||||
|
# |
||||
|
# Documentation |
||||
|
# |
||||
|
find_program (DOXYGEN doxygen) |
||||
|
if (DOXYGEN) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/Doxyfile.in ${PROJECT_BINARY_DIR}/doc/Doxyfile) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/DoxygenLayout.xml ${PROJECT_BINARY_DIR}/doc/DoxygenLayout.xml COPYONLY) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/header.html ${PROJECT_BINARY_DIR}/doc/header.html COPYONLY) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/footer.html ${PROJECT_BINARY_DIR}/doc/footer.html COPYONLY) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/favicon.ico ${PROJECT_BINARY_DIR}/doc/favicon.ico COPYONLY) |
||||
|
configure_file (${PROJECT_SOURCE_DIR}/doc/customdoxygen.css ${PROJECT_BINARY_DIR}/doc/customdoxygen.css) |
||||
|
add_custom_target (cppduals_docs |
||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc |
||||
|
COMMAND cmake -E remove_directory ${PROJECT_BINARY_DIR}/docs |
||||
|
COMMAND ${DOXYGEN} Doxyfile |
||||
|
) |
||||
|
else () |
||||
|
add_custom_target (cppduals_docs |
||||
|
COMMAND echo "Please install doxygen and reconfigure to build the docs" |
||||
|
) |
||||
|
endif () |
||||
|
|
||||
|
# |
||||
|
# Installation |
||||
|
# |
||||
|
install (TARGETS cppduals_duals EXPORT cppduals_export) |
||||
|
install (EXPORT cppduals_export |
||||
|
FILE cppduals-config.cmake |
||||
|
NAMESPACE cppduals:: |
||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cppduals |
||||
|
) |
||||
|
install ( |
||||
|
DIRECTORY ${PROJECT_SOURCE_DIR}/duals |
||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} |
||||
|
PATTERN "*~" EXCLUDE |
||||
|
) |
||||
|
install ( |
||||
|
DIRECTORY ${PROJECT_BINARY_DIR}/docs/ # Trailing slash triggers rename |
||||
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/cppduals |
||||
|
OPTIONAL |
||||
|
) |
||||
|
|
||||
|
# |
||||
|
# etags |
||||
|
# |
||||
|
find_program (ETAGS etags) |
||||
|
if (ETAGS) |
||||
|
add_custom_target (cppduals_etags |
||||
|
COMMAND ${ETAGS} --language=c++ ${PROJECT_SOURCE_DIR}/duals/* |
||||
|
COMMAND ${ETAGS} --language=c++ --append ${PROJECT_SOURCE_DIR}/duals/arch/*/* |
||||
|
COMMAND ${ETAGS} --language=c++ --append `find ${PROJECT_BINARY_DIR}/thirdparty/eigenX/src/eigenX -type f` |
||||
|
) |
||||
|
endif (ETAGS) |
||||
@ -0,0 +1,373 @@ |
|||||
|
Mozilla Public License Version 2.0 |
||||
|
================================== |
||||
|
|
||||
|
1. Definitions |
||||
|
-------------- |
||||
|
|
||||
|
1.1. "Contributor" |
||||
|
means each individual or legal entity that creates, contributes to |
||||
|
the creation of, or owns Covered Software. |
||||
|
|
||||
|
1.2. "Contributor Version" |
||||
|
means the combination of the Contributions of others (if any) used |
||||
|
by a Contributor and that particular Contributor's Contribution. |
||||
|
|
||||
|
1.3. "Contribution" |
||||
|
means Covered Software of a particular Contributor. |
||||
|
|
||||
|
1.4. "Covered Software" |
||||
|
means Source Code Form to which the initial Contributor has attached |
||||
|
the notice in Exhibit A, the Executable Form of such Source Code |
||||
|
Form, and Modifications of such Source Code Form, in each case |
||||
|
including portions thereof. |
||||
|
|
||||
|
1.5. "Incompatible With Secondary Licenses" |
||||
|
means |
||||
|
|
||||
|
(a) that the initial Contributor has attached the notice described |
||||
|
in Exhibit B to the Covered Software; or |
||||
|
|
||||
|
(b) that the Covered Software was made available under the terms of |
||||
|
version 1.1 or earlier of the License, but not also under the |
||||
|
terms of a Secondary License. |
||||
|
|
||||
|
1.6. "Executable Form" |
||||
|
means any form of the work other than Source Code Form. |
||||
|
|
||||
|
1.7. "Larger Work" |
||||
|
means a work that combines Covered Software with other material, in |
||||
|
a separate file or files, that is not Covered Software. |
||||
|
|
||||
|
1.8. "License" |
||||
|
means this document. |
||||
|
|
||||
|
1.9. "Licensable" |
||||
|
means having the right to grant, to the maximum extent possible, |
||||
|
whether at the time of the initial grant or subsequently, any and |
||||
|
all of the rights conveyed by this License. |
||||
|
|
||||
|
1.10. "Modifications" |
||||
|
means any of the following: |
||||
|
|
||||
|
(a) any file in Source Code Form that results from an addition to, |
||||
|
deletion from, or modification of the contents of Covered |
||||
|
Software; or |
||||
|
|
||||
|
(b) any new file in Source Code Form that contains any Covered |
||||
|
Software. |
||||
|
|
||||
|
1.11. "Patent Claims" of a Contributor |
||||
|
means any patent claim(s), including without limitation, method, |
||||
|
process, and apparatus claims, in any patent Licensable by such |
||||
|
Contributor that would be infringed, but for the grant of the |
||||
|
License, by the making, using, selling, offering for sale, having |
||||
|
made, import, or transfer of either its Contributions or its |
||||
|
Contributor Version. |
||||
|
|
||||
|
1.12. "Secondary License" |
||||
|
means either the GNU General Public License, Version 2.0, the GNU |
||||
|
Lesser General Public License, Version 2.1, the GNU Affero General |
||||
|
Public License, Version 3.0, or any later versions of those |
||||
|
licenses. |
||||
|
|
||||
|
1.13. "Source Code Form" |
||||
|
means the form of the work preferred for making modifications. |
||||
|
|
||||
|
1.14. "You" (or "Your") |
||||
|
means an individual or a legal entity exercising rights under this |
||||
|
License. For legal entities, "You" includes any entity that |
||||
|
controls, is controlled by, or is under common control with You. For |
||||
|
purposes of this definition, "control" means (a) the power, direct |
||||
|
or indirect, to cause the direction or management of such entity, |
||||
|
whether by contract or otherwise, or (b) ownership of more than |
||||
|
fifty percent (50%) of the outstanding shares or beneficial |
||||
|
ownership of such entity. |
||||
|
|
||||
|
2. License Grants and Conditions |
||||
|
-------------------------------- |
||||
|
|
||||
|
2.1. Grants |
||||
|
|
||||
|
Each Contributor hereby grants You a world-wide, royalty-free, |
||||
|
non-exclusive license: |
||||
|
|
||||
|
(a) under intellectual property rights (other than patent or trademark) |
||||
|
Licensable by such Contributor to use, reproduce, make available, |
||||
|
modify, display, perform, distribute, and otherwise exploit its |
||||
|
Contributions, either on an unmodified basis, with Modifications, or |
||||
|
as part of a Larger Work; and |
||||
|
|
||||
|
(b) under Patent Claims of such Contributor to make, use, sell, offer |
||||
|
for sale, have made, import, and otherwise transfer either its |
||||
|
Contributions or its Contributor Version. |
||||
|
|
||||
|
2.2. Effective Date |
||||
|
|
||||
|
The licenses granted in Section 2.1 with respect to any Contribution |
||||
|
become effective for each Contribution on the date the Contributor first |
||||
|
distributes such Contribution. |
||||
|
|
||||
|
2.3. Limitations on Grant Scope |
||||
|
|
||||
|
The licenses granted in this Section 2 are the only rights granted under |
||||
|
this License. No additional rights or licenses will be implied from the |
||||
|
distribution or licensing of Covered Software under this License. |
||||
|
Notwithstanding Section 2.1(b) above, no patent license is granted by a |
||||
|
Contributor: |
||||
|
|
||||
|
(a) for any code that a Contributor has removed from Covered Software; |
||||
|
or |
||||
|
|
||||
|
(b) for infringements caused by: (i) Your and any other third party's |
||||
|
modifications of Covered Software, or (ii) the combination of its |
||||
|
Contributions with other software (except as part of its Contributor |
||||
|
Version); or |
||||
|
|
||||
|
(c) under Patent Claims infringed by Covered Software in the absence of |
||||
|
its Contributions. |
||||
|
|
||||
|
This License does not grant any rights in the trademarks, service marks, |
||||
|
or logos of any Contributor (except as may be necessary to comply with |
||||
|
the notice requirements in Section 3.4). |
||||
|
|
||||
|
2.4. Subsequent Licenses |
||||
|
|
||||
|
No Contributor makes additional grants as a result of Your choice to |
||||
|
distribute the Covered Software under a subsequent version of this |
||||
|
License (see Section 10.2) or under the terms of a Secondary License (if |
||||
|
permitted under the terms of Section 3.3). |
||||
|
|
||||
|
2.5. Representation |
||||
|
|
||||
|
Each Contributor represents that the Contributor believes its |
||||
|
Contributions are its original creation(s) or it has sufficient rights |
||||
|
to grant the rights to its Contributions conveyed by this License. |
||||
|
|
||||
|
2.6. Fair Use |
||||
|
|
||||
|
This License is not intended to limit any rights You have under |
||||
|
applicable copyright doctrines of fair use, fair dealing, or other |
||||
|
equivalents. |
||||
|
|
||||
|
2.7. Conditions |
||||
|
|
||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted |
||||
|
in Section 2.1. |
||||
|
|
||||
|
3. Responsibilities |
||||
|
------------------- |
||||
|
|
||||
|
3.1. Distribution of Source Form |
||||
|
|
||||
|
All distribution of Covered Software in Source Code Form, including any |
||||
|
Modifications that You create or to which You contribute, must be under |
||||
|
the terms of this License. You must inform recipients that the Source |
||||
|
Code Form of the Covered Software is governed by the terms of this |
||||
|
License, and how they can obtain a copy of this License. You may not |
||||
|
attempt to alter or restrict the recipients' rights in the Source Code |
||||
|
Form. |
||||
|
|
||||
|
3.2. Distribution of Executable Form |
||||
|
|
||||
|
If You distribute Covered Software in Executable Form then: |
||||
|
|
||||
|
(a) such Covered Software must also be made available in Source Code |
||||
|
Form, as described in Section 3.1, and You must inform recipients of |
||||
|
the Executable Form how they can obtain a copy of such Source Code |
||||
|
Form by reasonable means in a timely manner, at a charge no more |
||||
|
than the cost of distribution to the recipient; and |
||||
|
|
||||
|
(b) You may distribute such Executable Form under the terms of this |
||||
|
License, or sublicense it under different terms, provided that the |
||||
|
license for the Executable Form does not attempt to limit or alter |
||||
|
the recipients' rights in the Source Code Form under this License. |
||||
|
|
||||
|
3.3. Distribution of a Larger Work |
||||
|
|
||||
|
You may create and distribute a Larger Work under terms of Your choice, |
||||
|
provided that You also comply with the requirements of this License for |
||||
|
the Covered Software. If the Larger Work is a combination of Covered |
||||
|
Software with a work governed by one or more Secondary Licenses, and the |
||||
|
Covered Software is not Incompatible With Secondary Licenses, this |
||||
|
License permits You to additionally distribute such Covered Software |
||||
|
under the terms of such Secondary License(s), so that the recipient of |
||||
|
the Larger Work may, at their option, further distribute the Covered |
||||
|
Software under the terms of either this License or such Secondary |
||||
|
License(s). |
||||
|
|
||||
|
3.4. Notices |
||||
|
|
||||
|
You may not remove or alter the substance of any license notices |
||||
|
(including copyright notices, patent notices, disclaimers of warranty, |
||||
|
or limitations of liability) contained within the Source Code Form of |
||||
|
the Covered Software, except that You may alter any license notices to |
||||
|
the extent required to remedy known factual inaccuracies. |
||||
|
|
||||
|
3.5. Application of Additional Terms |
||||
|
|
||||
|
You may choose to offer, and to charge a fee for, warranty, support, |
||||
|
indemnity or liability obligations to one or more recipients of Covered |
||||
|
Software. However, You may do so only on Your own behalf, and not on |
||||
|
behalf of any Contributor. You must make it absolutely clear that any |
||||
|
such warranty, support, indemnity, or liability obligation is offered by |
||||
|
You alone, and You hereby agree to indemnify every Contributor for any |
||||
|
liability incurred by such Contributor as a result of warranty, support, |
||||
|
indemnity or liability terms You offer. You may include additional |
||||
|
disclaimers of warranty and limitations of liability specific to any |
||||
|
jurisdiction. |
||||
|
|
||||
|
4. Inability to Comply Due to Statute or Regulation |
||||
|
--------------------------------------------------- |
||||
|
|
||||
|
If it is impossible for You to comply with any of the terms of this |
||||
|
License with respect to some or all of the Covered Software due to |
||||
|
statute, judicial order, or regulation then You must: (a) comply with |
||||
|
the terms of this License to the maximum extent possible; and (b) |
||||
|
describe the limitations and the code they affect. Such description must |
||||
|
be placed in a text file included with all distributions of the Covered |
||||
|
Software under this License. Except to the extent prohibited by statute |
||||
|
or regulation, such description must be sufficiently detailed for a |
||||
|
recipient of ordinary skill to be able to understand it. |
||||
|
|
||||
|
5. Termination |
||||
|
-------------- |
||||
|
|
||||
|
5.1. The rights granted under this License will terminate automatically |
||||
|
if You fail to comply with any of its terms. However, if You become |
||||
|
compliant, then the rights granted under this License from a particular |
||||
|
Contributor are reinstated (a) provisionally, unless and until such |
||||
|
Contributor explicitly and finally terminates Your grants, and (b) on an |
||||
|
ongoing basis, if such Contributor fails to notify You of the |
||||
|
non-compliance by some reasonable means prior to 60 days after You have |
||||
|
come back into compliance. Moreover, Your grants from a particular |
||||
|
Contributor are reinstated on an ongoing basis if such Contributor |
||||
|
notifies You of the non-compliance by some reasonable means, this is the |
||||
|
first time You have received notice of non-compliance with this License |
||||
|
from such Contributor, and You become compliant prior to 30 days after |
||||
|
Your receipt of the notice. |
||||
|
|
||||
|
5.2. If You initiate litigation against any entity by asserting a patent |
||||
|
infringement claim (excluding declaratory judgment actions, |
||||
|
counter-claims, and cross-claims) alleging that a Contributor Version |
||||
|
directly or indirectly infringes any patent, then the rights granted to |
||||
|
You by any and all Contributors for the Covered Software under Section |
||||
|
2.1 of this License shall terminate. |
||||
|
|
||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all |
||||
|
end user license agreements (excluding distributors and resellers) which |
||||
|
have been validly granted by You or Your distributors under this License |
||||
|
prior to termination shall survive termination. |
||||
|
|
||||
|
************************************************************************ |
||||
|
* * |
||||
|
* 6. Disclaimer of Warranty * |
||||
|
* ------------------------- * |
||||
|
* * |
||||
|
* Covered Software is provided under this License on an "as is" * |
||||
|
* basis, without warranty of any kind, either expressed, implied, or * |
||||
|
* statutory, including, without limitation, warranties that the * |
||||
|
* Covered Software is free of defects, merchantable, fit for a * |
||||
|
* particular purpose or non-infringing. The entire risk as to the * |
||||
|
* quality and performance of the Covered Software is with You. * |
||||
|
* Should any Covered Software prove defective in any respect, You * |
||||
|
* (not any Contributor) assume the cost of any necessary servicing, * |
||||
|
* repair, or correction. This disclaimer of warranty constitutes an * |
||||
|
* essential part of this License. No use of any Covered Software is * |
||||
|
* authorized under this License except under this disclaimer. * |
||||
|
* * |
||||
|
************************************************************************ |
||||
|
|
||||
|
************************************************************************ |
||||
|
* * |
||||
|
* 7. Limitation of Liability * |
||||
|
* -------------------------- * |
||||
|
* * |
||||
|
* Under no circumstances and under no legal theory, whether tort * |
||||
|
* (including negligence), contract, or otherwise, shall any * |
||||
|
* Contributor, or anyone who distributes Covered Software as * |
||||
|
* permitted above, be liable to You for any direct, indirect, * |
||||
|
* special, incidental, or consequential damages of any character * |
||||
|
* including, without limitation, damages for lost profits, loss of * |
||||
|
* goodwill, work stoppage, computer failure or malfunction, or any * |
||||
|
* and all other commercial damages or losses, even if such party * |
||||
|
* shall have been informed of the possibility of such damages. This * |
||||
|
* limitation of liability shall not apply to liability for death or * |
||||
|
* personal injury resulting from such party's negligence to the * |
||||
|
* extent applicable law prohibits such limitation. Some * |
||||
|
* jurisdictions do not allow the exclusion or limitation of * |
||||
|
* incidental or consequential damages, so this exclusion and * |
||||
|
* limitation may not apply to You. * |
||||
|
* * |
||||
|
************************************************************************ |
||||
|
|
||||
|
8. Litigation |
||||
|
------------- |
||||
|
|
||||
|
Any litigation relating to this License may be brought only in the |
||||
|
courts of a jurisdiction where the defendant maintains its principal |
||||
|
place of business and such litigation shall be governed by laws of that |
||||
|
jurisdiction, without reference to its conflict-of-law provisions. |
||||
|
Nothing in this Section shall prevent a party's ability to bring |
||||
|
cross-claims or counter-claims. |
||||
|
|
||||
|
9. Miscellaneous |
||||
|
---------------- |
||||
|
|
||||
|
This License represents the complete agreement concerning the subject |
||||
|
matter hereof. If any provision of this License is held to be |
||||
|
unenforceable, such provision shall be reformed only to the extent |
||||
|
necessary to make it enforceable. Any law or regulation which provides |
||||
|
that the language of a contract shall be construed against the drafter |
||||
|
shall not be used to construe this License against a Contributor. |
||||
|
|
||||
|
10. Versions of the License |
||||
|
--------------------------- |
||||
|
|
||||
|
10.1. New Versions |
||||
|
|
||||
|
Mozilla Foundation is the license steward. Except as provided in Section |
||||
|
10.3, no one other than the license steward has the right to modify or |
||||
|
publish new versions of this License. Each version will be given a |
||||
|
distinguishing version number. |
||||
|
|
||||
|
10.2. Effect of New Versions |
||||
|
|
||||
|
You may distribute the Covered Software under the terms of the version |
||||
|
of the License under which You originally received the Covered Software, |
||||
|
or under the terms of any subsequent version published by the license |
||||
|
steward. |
||||
|
|
||||
|
10.3. Modified Versions |
||||
|
|
||||
|
If you create software not governed by this License, and you want to |
||||
|
create a new license for such software, you may create and use a |
||||
|
modified version of this License if you rename the license and remove |
||||
|
any references to the name of the license steward (except to note that |
||||
|
such modified license differs from this License). |
||||
|
|
||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary |
||||
|
Licenses |
||||
|
|
||||
|
If You choose to distribute Source Code Form that is Incompatible With |
||||
|
Secondary Licenses under the terms of this version of the License, the |
||||
|
notice described in Exhibit B of this License must be attached. |
||||
|
|
||||
|
Exhibit A - Source Code Form License Notice |
||||
|
------------------------------------------- |
||||
|
|
||||
|
This Source Code Form is subject to the terms of the Mozilla Public |
||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this |
||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
If it is not possible or desirable to put the notice in a particular |
||||
|
file, then You may include the notice in a location (such as a LICENSE |
||||
|
file in a relevant directory) where a recipient would be likely to look |
||||
|
for such a notice. |
||||
|
|
||||
|
You may add additional accurate notices of copyright ownership. |
||||
|
|
||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice |
||||
|
--------------------------------------------------------- |
||||
|
|
||||
|
This Source Code Form is "Incompatible With Secondary Licenses", as |
||||
|
defined by the Mozilla Public License, v. 2.0. |
||||
@ -0,0 +1,354 @@ |
|||||
|
cppduals |
||||
|
======== |
||||
|
|
||||
|
Header-only dual number library for C++11. The `dual<>` type can be |
||||
|
used for automatic (forward) differentiation. It can be used in |
||||
|
conjunction with Eigen to produced very fast vectorized computations |
||||
|
of real and complex matrix functions and their derivatives. |
||||
|
|
||||
|
There is a small paper on cppduals here: |
||||
|
[](https://doi.org/10.21105/joss.01487) |
||||
|
|
||||
|
Documentation |
||||
|
============= |
||||
|
|
||||
|
[Full documentation is here](https://tesch1.gitlab.io/cppduals/). |
||||
|
|
||||
|
The dual number space is closely related to the complex number space, |
||||
|
and as such, the dual class `duals::dual<>` is similar to |
||||
|
`std::complex<>`. |
||||
|
|
||||
|
When compiling with Eigen it is possible to disable the vectorization |
||||
|
templates by `#define CPPDUALS_DONT_VECTORIZE`. This may be useful if |
||||
|
your compiler is particularly good at optimizing Eigen expressions, I |
||||
|
have had mixed results, sometimes there are differences between the |
||||
|
compiler's best (GCC and Clang) and the vectorized code of 30% or |
||||
|
more, in either direction. |
||||
|
|
||||
|
Examples |
||||
|
======== |
||||
|
|
||||
|
Here we calculate a function $`f(x)`$, with its derivative $`f'(x)`$, |
||||
|
calculated explicitly as `df()`, and calculated by using the dual |
||||
|
class (`1_e` returns the dual number $`0 + 1 \epsilon`$, it is |
||||
|
equivalent to `dual<double>(0,1)`): |
||||
|
|
||||
|
```cpp |
||||
|
#include <duals/dual> |
||||
|
|
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
template <class T> T f(T x) { return pow(x,pow(x,x)); } |
||||
|
template <class T> T df(T x) { return pow(x,-1. + x + pow(x,x)) * (1. + x*log(x) + x*pow(log(x),2.)); } |
||||
|
template <class T> T ddf(T x) { return (pow(x,pow(x,x)) * pow(pow(x,x - 1.) + pow(x,x)*log(x)*(log(x) + 1.), 2.) + |
||||
|
pow(x,pow(x,x)) * (pow(x,x - 1.) * log(x) + |
||||
|
pow(x,x - 1.) * (log(x) + 1.) + |
||||
|
pow(x,x - 1.) * ((x - 1.)/x + log(x)) + |
||||
|
pow(x,x) * log(x) * pow(log(x) + 1., 2.) )); } |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
std::cout << " f(2.) = " << f(2.) << "\n"; |
||||
|
std::cout << " df(2.) = " << df(2.) << "\n"; |
||||
|
std::cout << "ddf(2.) = " << ddf(2.) << "\n"; |
||||
|
std::cout << " f(2+1_e) = " << f(2+1_e) << "\n"; |
||||
|
std::cout << " f(2+1_e).dpart() = " << f(2+1_e).dpart() << "\n"; |
||||
|
duals::hyperduald x(2+1_e,1+0_e); |
||||
|
std::cout << " f((2+1_e) + (1+0_e)_e).dpart().dpart() = " << f(x).dpart().dpart() << "\n"; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
Produces: |
||||
|
|
||||
|
``` |
||||
|
f(2.) = 16 |
||||
|
df(2.) = 107.11 |
||||
|
ddf(2.) = 958.755 |
||||
|
f(2+1_e) = (16+107.11_e) |
||||
|
f(2+1_e).dpart() = 107.11 |
||||
|
f((2+1_e) + (1+0_e)_e).dpart().dpart() = 958.755 |
||||
|
``` |
||||
|
|
||||
|
Installation |
||||
|
============ |
||||
|
|
||||
|
Copy the [duals/](./duals/) directory (or just [dual](./duals/dual) ) |
||||
|
somewhere your `#include`s can find it. Then just `#include |
||||
|
<duals/dual[_eigen]>` from your source. |
||||
|
|
||||
|
Alternatively, `cppduals` supports building with CMake. If using CMake v3.14+, |
||||
|
the ``FetchContent`` pattern is straightforward and enables using CMake targets |
||||
|
to specify library dependencies: |
||||
|
|
||||
|
```cmake |
||||
|
include(FetchContent) |
||||
|
|
||||
|
# Have CMake download the library |
||||
|
set (CPPDUALS_TAG v0.4.1) |
||||
|
set (CPPDUALS_MD5 7efe49496b8d0e3d3ffbcd3c68f542f3) |
||||
|
FetchContent_Declare (cppduals |
||||
|
URL https://gitlab.com/tesch1/cppduals/-/archive/${CPPDUALS_TAG}/cppduals-${CPPDUALS_TAG}.tar.bz2 |
||||
|
URL_HASH MD5=${CPPDUALS_MD5} |
||||
|
) |
||||
|
FetchContent_MakeAvailable (cppduals) |
||||
|
|
||||
|
# Link to cppduals |
||||
|
target_link_libraries (your_target PRIVATE cppduals::duals) |
||||
|
``` |
||||
|
|
||||
|
Older versions of CMake can achieve a similar result using the ``ExternalProject`` |
||||
|
family of commands and modifying the global preprocessor search path: |
||||
|
|
||||
|
```cmake |
||||
|
include(ExternalProject) |
||||
|
|
||||
|
# Have CMake download the library headers only |
||||
|
set (CPPDUALS_TAG v0.4.1) |
||||
|
set (CPPDUALS_MD5 7efe49496b8d0e3d3ffbcd3c68f542f3) |
||||
|
ExternalProject_Add (cppduals |
||||
|
URL https://gitlab.com/tesch1/cppduals/-/archive/${CPPDUALS_TAG}/cppduals-${CPPDUALS_TAG}.tar.bz2 |
||||
|
URL_HASH MD5=${CPPDUALS_MD5} |
||||
|
CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) |
||||
|
|
||||
|
# Make include directory globally visible |
||||
|
ExternalProject_Get_Property (cppduals source_dir) |
||||
|
include_directories (${source_dir}/) |
||||
|
``` |
||||
|
|
||||
|
Alternatively, `cppduals` supports installation and discovery via the |
||||
|
`find_package` utility. First, download and install the library to a |
||||
|
location of your choosing: |
||||
|
|
||||
|
```sh |
||||
|
CPPDUALS_PREFIX=<desired_install_location> |
||||
|
git clone https://gitlab.com/tesch1/cppduals.git && cd cppduals |
||||
|
mkdir build && cd build |
||||
|
cmake -DCMAKE_INSTALL_PREFIX="$CPPDUALS_PREFIX" .. |
||||
|
cmake --build . --target install |
||||
|
``` |
||||
|
|
||||
|
Then, in your project's `CMakeLists.txt`, find and link to the library in the |
||||
|
standard manner: |
||||
|
|
||||
|
```cmake |
||||
|
find_package(cppduals REQUIRED) |
||||
|
target_link_libraries(your_target PRIVATE cppduals::cppduals) |
||||
|
``` |
||||
|
|
||||
|
If you installed `cppduals` to a location that is not on `find_package`'s |
||||
|
default search path, you can specify the location by setting the `cppduals_DIR` |
||||
|
environment variable when configuring your project: |
||||
|
|
||||
|
```sh |
||||
|
cd your_build_dir |
||||
|
cppduals_DIR="${CPPDUALS_PREFIX}" cmake .. |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
Benchmarks |
||||
|
========== |
||||
|
|
||||
|
The benchmark compares cppduals against a local BLAS implementation, |
||||
|
by default OpenBLAS (whose development package is required; |
||||
|
RedHat-flavor: `openblas-devel`, Debian-flavor: `openblas-dev`). If |
||||
|
you wish to build the benchmarks against a different installation of |
||||
|
BLAS, the following CMake variables can be set at configuration time: |
||||
|
|
||||
|
- [BLA_VENDOR](https://cmake.org/cmake/help/latest/module/FindBLAS.html) |
||||
|
- BLAS_DIR |
||||
|
- LAPACK_DIR |
||||
|
|
||||
|
For example, to build and run the tests shown below: |
||||
|
|
||||
|
```sh |
||||
|
cmake -Bbuild-bench -H. -DCPPDUALS_BENCHMARK=ON -DBLAS_DIR=/opt/local -DLAPACK_DIR=/opt/local |
||||
|
cmake --build build-bench --target bench_gemm |
||||
|
./build-bench/tests/bench_gemm |
||||
|
``` |
||||
|
|
||||
|
The first performance goal of this project is to make the |
||||
|
`duals::dual<>` type at least as fast as `std::complex<>`. This is |
||||
|
considered to be an upper-bound for performance because complex math |
||||
|
operations are usually highly optimized for scientific computing and |
||||
|
have a similar algebraic structure. The second goal is to make the |
||||
|
compound type `std::complex<duals::dual<>>` as fast as possible for |
||||
|
use in calculation that require the derivative of complex functions |
||||
|
(ie comprising quantum-mechanical wave functions). |
||||
|
|
||||
|
The first goal is measured by comparing the speed of matrix-matrix |
||||
|
operations (nominally matrix multiplication) on `duals::dual<>`-valued |
||||
|
Eigen matrices with highly optimtimized BLAS implementations of |
||||
|
equivalent operations on complex-valued matrices. This can be done by |
||||
|
running the [./tests/bench_gemm](./tests/bench_gemm.cpp) program. In |
||||
|
the *ideal* case, the results of the `B_MatMat<dual{f,d}>` type should |
||||
|
be nearly as fast, or faster than equivalently sized |
||||
|
`B_MatMat<complex{f,d}>`, and double-sized |
||||
|
`B_MatMatBLAS<{float,double}>` operations. This is very difficult to |
||||
|
achieve in reality, as the BLAS libraries typically use hand-tuned |
||||
|
assembly, where the Eigen libraries must strive to express the |
||||
|
calculation in a general form that the compiler can turn into optimal |
||||
|
code. |
||||
|
|
||||
|
Comparing Eigen 3.3.7 and OpenBLAS 0.3.6 on an `Intel(R) Core(TM) |
||||
|
i7-7700 CPU @ 3.60GHz` is still sub-optimal, only achieving about half |
||||
|
the performance of the BLAS equivalent, and 90% of |
||||
|
`std::complex<float>`: |
||||
|
|
||||
|
B_MatMat<dualf,dualf>/32 5433 ns 5427 ns |
||||
|
B_MatMat<dualf,dualf>/64 38478 ns 38433 ns |
||||
|
B_MatMat<dualf,dualf>/128 299450 ns 298981 ns |
||||
|
B_MatMat<dualf,dualf>/256 2365347 ns 2361566 ns |
||||
|
B_MatMat<dualf,dualf>/512 18888220 ns 18857342 ns |
||||
|
B_MatMat<dualf,dualf>/1024 151079955 ns 150856120 ns |
||||
|
|
||||
|
B_MatMat<complexf,complexf>/32 4963 ns 4955 ns |
||||
|
B_MatMat<complexf,complexf>/64 36716 ns 36671 ns |
||||
|
B_MatMat<complexf,complexf>/128 280870 ns 280346 ns |
||||
|
B_MatMat<complexf,complexf>/256 2173791 ns 2170886 ns |
||||
|
B_MatMat<complexf,complexf>/512 17493222 ns 17459890 ns |
||||
|
B_MatMat<complexf,complexf>/1024 138498432 ns 138286283 ns |
||||
|
|
||||
|
B_MatMatBLAS<complexf>/32 4877 ns 4870 ns |
||||
|
B_MatMatBLAS<complexf>/64 27722 ns 27691 ns |
||||
|
B_MatMatBLAS<complexf>/128 177084 ns 176756 ns |
||||
|
B_MatMatBLAS<complexf>/256 1268715 ns 1266445 ns |
||||
|
B_MatMatBLAS<complexf>/512 9772184 ns 9726621 ns |
||||
|
B_MatMatBLAS<complexf>/1024 75915016 ns 75432354 ns |
||||
|
|
||||
|
|
||||
|
The second benchmark of interest measures how well the nested |
||||
|
specializations `std::complex<duals::dual<>>` perform as matrix values |
||||
|
relative to using a BLAS library with an extended matrix to compute |
||||
|
the same value function. This comparison is also made with the |
||||
|
[./tests/bench_gemm](./tests/bench_gemm.cpp) program. The relevant |
||||
|
measures are `B_MatMat<cdual{f,d}>` and `B_MatMatBLAS<complex{f,d}>` |
||||
|
of twice the size. |
||||
|
|
||||
|
On the same machine as above, using `std::complex<duals::dual<float>>` |
||||
|
(`cdualf`) shows a speed advantage over the BLAS approach, while using |
||||
|
only half the memory. However, notice that the advantage decreases as |
||||
|
the matrices get larger, which ideally should not happen: |
||||
|
|
||||
|
B_MatMat<cdualf,cdualf>/16 2810 ns 2808 ns |
||||
|
B_MatMat<cdualf,cdualf>/32 19900 ns 19878 ns |
||||
|
B_MatMat<cdualf,cdualf>/64 151837 ns 151646 ns |
||||
|
B_MatMat<cdualf,cdualf>/128 1174699 ns 1172931 ns |
||||
|
B_MatMat<cdualf,cdualf>/256 9122903 ns 9110123 ns |
||||
|
B_MatMat<cdualf,cdualf>/512 72575352 ns 72467264 ns |
||||
|
|
||||
|
B_MatMatBLAS<complexf>/32 4877 ns 4870 ns |
||||
|
B_MatMatBLAS<complexf>/64 27722 ns 27691 ns |
||||
|
B_MatMatBLAS<complexf>/128 177084 ns 176756 ns |
||||
|
B_MatMatBLAS<complexf>/256 1268715 ns 1266445 ns |
||||
|
B_MatMatBLAS<complexf>/512 9772184 ns 9726621 ns |
||||
|
B_MatMatBLAS<complexf>/1024 75915016 ns 75432354 ns |
||||
|
|
||||
|
|
||||
|
Contributions |
||||
|
============= |
||||
|
|
||||
|
Questions, bug reports, bug fixes, and contributions are welcome. |
||||
|
Simply submit an [Issue](https://gitlab.com/tesch1/cppduals/issues) |
||||
|
or [Merge Request](https://gitlab.com/tesch1/cppduals/merge_requests). |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
- [Nestor Demeure](https://gitlab.com/nestordemeure) |
||||
|
- [Jeff](https://github.com/flying-tiger) |
||||
|
|
||||
|
Compiler notes |
||||
|
============== |
||||
|
|
||||
|
XCode 11 (Apple Clang 11) is known to work. Also various version of |
||||
|
g++. Clang 8.0 appears to have some trouble with compiling the |
||||
|
optimized templates for Eigen, as evidenced by its propensity to |
||||
|
segfault when compiling the cppduals test programs. Please submit |
||||
|
issues if you experience similar problems, with specifics of your |
||||
|
compiler and compilation flags. |
||||
|
|
||||
|
License |
||||
|
======= |
||||
|
|
||||
|
The primary header file `duals/dual` and testing and benchmarking code |
||||
|
is licensed under the following: |
||||
|
|
||||
|
``` |
||||
|
Part of the cppduals project. |
||||
|
https://tesch1.gitlab.io/cppduals |
||||
|
|
||||
|
(c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
|
||||
|
See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for |
||||
|
license information. |
||||
|
|
||||
|
This Source Code Form is subject to the terms of the Mozilla |
||||
|
Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
``` |
||||
|
|
||||
|
Eigen-derived |
||||
|
------------- |
||||
|
|
||||
|
The support for Eigen vectorization, including `duals/dual_eigen` and |
||||
|
the architecture-specific vectorization files under `duals/arch` are |
||||
|
derived from the [Eigen |
||||
|
project](http://eigen.tuxfamily.org/index.php?title=Main_Page), and |
||||
|
thus licensed under [MPL-2](http://www.mozilla.org/MPL/2.0/FAQ.html) . |
||||
|
|
||||
|
ChangeLog |
||||
|
========= |
||||
|
|
||||
|
v0.4.1 |
||||
|
====== |
||||
|
|
||||
|
- changed constexpr to FMT_CONSTEXPR in the dual<> and complex<> |
||||
|
formatters to work with more compilers / lang standards. |
||||
|
|
||||
|
v0.4.0 |
||||
|
====== |
||||
|
|
||||
|
- cleaned-up release with fixes from v0.3.2. |
||||
|
- improved docs |
||||
|
|
||||
|
v0.3.3+ |
||||
|
======= |
||||
|
|
||||
|
- ignore these, will be, trying to cleanup release tarballs, next |
||||
|
stable will be v0.4.0 |
||||
|
|
||||
|
v0.3.2 |
||||
|
====== |
||||
|
|
||||
|
- not actually tagged release |
||||
|
- fixed a bug in the `{fmt}` support, added docs for the same. |
||||
|
- added benchmarking for `{fmt}` vs iostreams. |
||||
|
|
||||
|
v0.3.1 |
||||
|
====== |
||||
|
|
||||
|
- forgot to bump the CMakeLists package version number in 0.3.0. |
||||
|
|
||||
|
v0.3.0 |
||||
|
====== |
||||
|
|
||||
|
- vastly improved cmake support, thanks to |
||||
|
[Jeff](https://gitlab.com/flying-tiger). The improvements required |
||||
|
changing some CMake target names. |
||||
|
- Added basic optional [libfmt](https://github.com/fmtlib/fmt) support for |
||||
|
duals::dual<> and std::complex<>, enabled with `#define`\ s |
||||
|
|
||||
|
v0.2.0 |
||||
|
====== |
||||
|
|
||||
|
- fixed build on VS2017 |
||||
|
- save and restore signam and errno in {t,l}gamma |
||||
|
- fixes from Nestor D. for https://gitlab.com/tesch1/cppduals/issues/5 (spurious nan) |
||||
|
|
||||
|
Todo |
||||
|
==== |
||||
|
|
||||
|
- Add multi-variate differentiation capability. |
||||
|
- Non-x86_64 (CUDA/AltiVec/HIP/NEON/...) vectorization. |
||||
|
- Higher-order derivatives. |
||||
|
|
||||
2391
src/include/cppduals/doc/Doxyfile.in
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,195 @@ |
|||||
|
<doxygenlayout version="1.0"> |
||||
|
<!-- Generated by doxygen 1.8.14 --> |
||||
|
<!-- Navigation index tabs for HTML output --> |
||||
|
<navindex> |
||||
|
<tab type="mainpage" visible="yes" title=""/> |
||||
|
<tab type="user" url="https://gitlab.com/tesch1/cppduals" title="GitLab Repo"/> |
||||
|
<!-- tab type="pages" visible="yes" title="" intro=""/ --> |
||||
|
<tab type="modules" visible="yes" title="" intro=""/> |
||||
|
<tab type="namespaces" visible="yes" title=""> |
||||
|
<tab type="namespacelist" visible="yes" title="" intro=""/> |
||||
|
<tab type="namespacemembers" visible="yes" title="" intro=""/> |
||||
|
</tab> |
||||
|
<tab type="classes" visible="yes" title=""> |
||||
|
<tab type="classlist" visible="yes" title="" intro=""/> |
||||
|
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> |
||||
|
<tab type="hierarchy" visible="yes" title="" intro=""/> |
||||
|
<tab type="classmembers" visible="yes" title="" intro=""/> |
||||
|
</tab> |
||||
|
<tab type="files" visible="yes" title=""> |
||||
|
<tab type="filelist" visible="yes" title="" intro=""/> |
||||
|
<tab type="globals" visible="yes" title="" intro=""/> |
||||
|
</tab> |
||||
|
<tab type="examples" visible="yes" title="" intro=""/> |
||||
|
</navindex> |
||||
|
|
||||
|
<!-- Layout definition for a class page --> |
||||
|
<class> |
||||
|
<briefdescription visible="yes"/> |
||||
|
<includes visible="$SHOW_INCLUDE_FILES"/> |
||||
|
<inheritancegraph visible="$CLASS_GRAPH"/> |
||||
|
<collaborationgraph visible="$COLLABORATION_GRAPH"/> |
||||
|
<memberdecl> |
||||
|
<nestedclasses visible="yes" title=""/> |
||||
|
<publictypes title=""/> |
||||
|
<services title=""/> |
||||
|
<interfaces title=""/> |
||||
|
<publicslots title=""/> |
||||
|
<signals title=""/> |
||||
|
<publicmethods title=""/> |
||||
|
<publicstaticmethods title=""/> |
||||
|
<publicattributes title=""/> |
||||
|
<publicstaticattributes title=""/> |
||||
|
<protectedtypes title=""/> |
||||
|
<protectedslots title=""/> |
||||
|
<protectedmethods title=""/> |
||||
|
<protectedstaticmethods title=""/> |
||||
|
<protectedattributes title=""/> |
||||
|
<protectedstaticattributes title=""/> |
||||
|
<packagetypes title=""/> |
||||
|
<packagemethods title=""/> |
||||
|
<packagestaticmethods title=""/> |
||||
|
<packageattributes title=""/> |
||||
|
<packagestaticattributes title=""/> |
||||
|
<properties title=""/> |
||||
|
<events title=""/> |
||||
|
<privatetypes title=""/> |
||||
|
<privateslots title=""/> |
||||
|
<privatemethods title=""/> |
||||
|
<privatestaticmethods title=""/> |
||||
|
<privateattributes title=""/> |
||||
|
<privatestaticattributes title=""/> |
||||
|
<friends title=""/> |
||||
|
<related title="" subtitle=""/> |
||||
|
<membergroups visible="yes"/> |
||||
|
</memberdecl> |
||||
|
<detaileddescription title=""/> |
||||
|
<memberdef> |
||||
|
<inlineclasses title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<services title=""/> |
||||
|
<interfaces title=""/> |
||||
|
<constructors title=""/> |
||||
|
<functions title=""/> |
||||
|
<related title=""/> |
||||
|
<variables title=""/> |
||||
|
<properties title=""/> |
||||
|
<events title=""/> |
||||
|
</memberdef> |
||||
|
<allmemberslink visible="yes"/> |
||||
|
<usedfiles visible="$SHOW_USED_FILES"/> |
||||
|
<authorsection visible="yes"/> |
||||
|
</class> |
||||
|
|
||||
|
<!-- Layout definition for a namespace page --> |
||||
|
<namespace> |
||||
|
<briefdescription visible="yes"/> |
||||
|
<memberdecl> |
||||
|
<nestednamespaces visible="yes" title=""/> |
||||
|
<constantgroups visible="yes" title=""/> |
||||
|
<classes visible="yes" title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
<membergroups visible="yes"/> |
||||
|
</memberdecl> |
||||
|
<detaileddescription title=""/> |
||||
|
<memberdef> |
||||
|
<inlineclasses title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
</memberdef> |
||||
|
<authorsection visible="yes"/> |
||||
|
</namespace> |
||||
|
|
||||
|
<!-- Layout definition for a file page --> |
||||
|
<file> |
||||
|
<briefdescription visible="yes"/> |
||||
|
<includes visible="$SHOW_INCLUDE_FILES"/> |
||||
|
<includegraph visible="$INCLUDE_GRAPH"/> |
||||
|
<includedbygraph visible="$INCLUDED_BY_GRAPH"/> |
||||
|
<sourcelink visible="yes"/> |
||||
|
<memberdecl> |
||||
|
<classes visible="yes" title=""/> |
||||
|
<namespaces visible="yes" title=""/> |
||||
|
<constantgroups visible="yes" title=""/> |
||||
|
<defines title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
<membergroups visible="yes"/> |
||||
|
</memberdecl> |
||||
|
<detaileddescription title=""/> |
||||
|
<memberdef> |
||||
|
<inlineclasses title=""/> |
||||
|
<defines title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
</memberdef> |
||||
|
<authorsection/> |
||||
|
</file> |
||||
|
|
||||
|
<!-- Layout definition for a group page --> |
||||
|
<group> |
||||
|
<briefdescription visible="yes"/> |
||||
|
<groupgraph visible="$GROUP_GRAPHS"/> |
||||
|
<memberdecl> |
||||
|
<nestedgroups visible="yes" title=""/> |
||||
|
<dirs visible="yes" title=""/> |
||||
|
<files visible="yes" title=""/> |
||||
|
<namespaces visible="yes" title=""/> |
||||
|
<classes visible="yes" title=""/> |
||||
|
<defines title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<enumvalues title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
<signals title=""/> |
||||
|
<publicslots title=""/> |
||||
|
<protectedslots title=""/> |
||||
|
<privateslots title=""/> |
||||
|
<events title=""/> |
||||
|
<properties title=""/> |
||||
|
<friends title=""/> |
||||
|
<membergroups visible="yes"/> |
||||
|
</memberdecl> |
||||
|
<detaileddescription title=""/> |
||||
|
<memberdef> |
||||
|
<pagedocs/> |
||||
|
<inlineclasses title=""/> |
||||
|
<defines title=""/> |
||||
|
<typedefs title=""/> |
||||
|
<enums title=""/> |
||||
|
<enumvalues title=""/> |
||||
|
<functions title=""/> |
||||
|
<variables title=""/> |
||||
|
<signals title=""/> |
||||
|
<publicslots title=""/> |
||||
|
<protectedslots title=""/> |
||||
|
<privateslots title=""/> |
||||
|
<events title=""/> |
||||
|
<properties title=""/> |
||||
|
<friends title=""/> |
||||
|
</memberdef> |
||||
|
<authorsection visible="yes"/> |
||||
|
</group> |
||||
|
|
||||
|
<!-- Layout definition for a directory page --> |
||||
|
<directory> |
||||
|
<briefdescription visible="yes"/> |
||||
|
<directorygraph visible="yes"/> |
||||
|
<memberdecl> |
||||
|
<dirs visible="yes"/> |
||||
|
<files visible="yes"/> |
||||
|
</memberdecl> |
||||
|
<detaileddescription title=""/> |
||||
|
</directory> |
||||
|
</doxygenlayout> |
||||
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) --> |
||||
|
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="42.519684" height="53.149605" id="svg2"> |
||||
|
<defs id="defs4"/> |
||||
|
<g id="layer2" style="display:none"> |
||||
|
<rect width="31.949493" height="34.973034" ry="0.21325016" x="5.0068707" y="9.2631512" id="rect3211" style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.07031591;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/> |
||||
|
<rect width="42.519684" height="53.149605" ry="0.32408288" x="-3.1811524e-06" y="-1.6357421e-06" id="rect2383" style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/> |
||||
|
</g> |
||||
|
<g id="layer3" style="display:inline"> |
||||
|
<path d="M 11.632405,9.1085188 L 8.0202222,43.827366 L 12.558227,44.299504 L 13.502504,35.223494 L 31.250416,44.109226 L 32.657186,41.459326 L 13.835588,32.022025 L 14.68285,23.878481 L 32.430762,32.764213 L 33.837533,30.114312 L 15.015935,20.677012 L 15.821157,12.937537 L 33.330112,21.704152 L 34.736883,19.054251 L 16.154241,9.3902177 L 11.632405,9.1085188 z" id="rect2802" style="opacity:1;fill:#dcdccc;fill-opacity:1;fill-rule:nonzero;stroke:#dcdccc;stroke-width:0.11321644;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/> |
||||
|
</g> |
||||
|
</svg> |
||||
2059
src/include/cppduals/doc/customdoxygen.css
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,20 @@ |
|||||
|
<!-- HTML footer for doxygen 1.8.14--> |
||||
|
<!-- start footer part --> |
||||
|
<!--BEGIN GENERATE_TREEVIEW--> |
||||
|
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> |
||||
|
<ul> |
||||
|
$navpath |
||||
|
<li class="footer">$generatedby |
||||
|
<a href="http://www.doxygen.org/index.html"> |
||||
|
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<!--END GENERATE_TREEVIEW--> |
||||
|
<!--BEGIN !GENERATE_TREEVIEW--> |
||||
|
<hr class="footer"/><address class="footer"> |
||||
|
<small> |
||||
|
$generatedby  <a href="http://www.doxygen.org/index.html"> doxygen</a> |
||||
|
</small></address> |
||||
|
<!--END !GENERATE_TREEVIEW--> |
||||
|
</body> |
||||
|
</html> |
||||
@ -0,0 +1,200 @@ |
|||||
|
#!/usr/bin/env python3 |
||||
|
|
||||
|
# found on github, of all places, with an MIT license: |
||||
|
# MIT License |
||||
|
# |
||||
|
# Copyright (c) 2017 iNet Process |
||||
|
# |
||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
# of this software and associated documentation files (the "Software"), to deal |
||||
|
# in the Software without restriction, including without limitation the rights |
||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
# copies of the Software, and to permit persons to whom the Software is |
||||
|
# furnished to do so, subject to the following conditions: |
||||
|
# |
||||
|
# The above copyright notice and this permission notice shall be included in all |
||||
|
# copies or substantial portions of the Software. |
||||
|
# |
||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
|
# SOFTWARE. |
||||
|
|
||||
|
import argparse |
||||
|
import os |
||||
|
import sys |
||||
|
from distutils.version import LooseVersion |
||||
|
from urllib.parse import urljoin, quote_plus |
||||
|
import requests |
||||
|
|
||||
|
class GitlabReleaseError(RuntimeError): |
||||
|
pass |
||||
|
|
||||
|
class GitlabRelease: |
||||
|
def __init__(self, debug=False): |
||||
|
self.env = {} |
||||
|
self.fetch_all_env() |
||||
|
self.api_project_url = self.get_api_project_url() |
||||
|
self.debug = debug |
||||
|
|
||||
|
def fetch_env_var(self, name, msg): |
||||
|
if name not in self.env: |
||||
|
try: |
||||
|
self.env[name] = os.environ[name] |
||||
|
except KeyError: |
||||
|
raise GitlabReleaseError('Missing environment variable \'{}\': {}'.format(name, msg)) |
||||
|
return self.env[name] |
||||
|
|
||||
|
def is_gitlab_v9(self): |
||||
|
gl_version = self.fetch_env_var('CI_SERVER_VERSION', '') |
||||
|
return LooseVersion(gl_version) >= LooseVersion('9.0.0') |
||||
|
|
||||
|
def get_tag(self): |
||||
|
tag_env = 'CI_BUILD_TAG' |
||||
|
if self.is_gitlab_v9(): |
||||
|
tag_env = 'CI_COMMIT_TAG' |
||||
|
return self.fetch_env_var(tag_env, 'Releases can only be created on tag build.') |
||||
|
|
||||
|
def fetch_all_env(self): |
||||
|
env = { |
||||
|
'CI_PROJECT_URL': '', |
||||
|
'CI_PROJECT_ID': '', |
||||
|
'GITLAB_ACCESS_TOKEN': "You must specifiy the private token linked to your GitLab account.\n" |
||||
|
'You probably need to add a GITLAB_ACCESS_TOKEN variable to your project.', |
||||
|
} |
||||
|
for var, msg in env.items(): |
||||
|
self.fetch_env_var(var, msg) |
||||
|
|
||||
|
def get_api_project_url(self): |
||||
|
api_version = 'v3' |
||||
|
if self.is_gitlab_v9(): |
||||
|
api_version = 'v4' |
||||
|
return urljoin(self.env['CI_PROJECT_URL'], |
||||
|
'/api/{}/projects/{}'.format(api_version, self.env['CI_PROJECT_ID'])) |
||||
|
|
||||
|
def post_file(self, filename): |
||||
|
url = '/'.join((self.api_project_url, 'uploads')) |
||||
|
files = {'file': open(filename, 'rb')} |
||||
|
res = self.request('post', url, files=files) |
||||
|
return res.json()['markdown'] |
||||
|
|
||||
|
def fetch_links(self): |
||||
|
url = '/'.join((self.api_project_url, 'releases', self.get_tag(), 'assets/links')) |
||||
|
headers = {'Content-Type': 'application/json'} |
||||
|
res = self.request('get', url, headers=headers) |
||||
|
return res.json() |
||||
|
|
||||
|
def set_links(self, links, update=False): |
||||
|
url = '/'.join((self.api_project_url, 'releases', self.get_tag(), 'assets/links')) |
||||
|
headers = {'Content-Type': 'application/json'} |
||||
|
method = 'put' if update else 'post' |
||||
|
res = self.request(method, url, headers=headers, json=links) |
||||
|
return res.json() |
||||
|
|
||||
|
def set_release(self, message, update=False): |
||||
|
url = '/'.join((self.api_project_url, 'repository/tags', self.get_tag(), 'release')) |
||||
|
headers = {'Content-Type': 'application/json'} |
||||
|
body = {'description': message} |
||||
|
method = 'put' if update else 'post' |
||||
|
res = self.request(method, url, headers=headers, json=body) |
||||
|
return res.json() |
||||
|
|
||||
|
def fetch_release(self): |
||||
|
url = '/'.join((self.api_project_url, 'repository/tags', self.get_tag())) |
||||
|
res = self.request('get', url) |
||||
|
return res.json()['release'] |
||||
|
|
||||
|
def request(self, method, url, **kwargs): |
||||
|
if 'headers' not in kwargs: |
||||
|
kwargs['headers'] = {} |
||||
|
kwargs['headers']['PRIVATE-TOKEN'] = self.env['GITLAB_ACCESS_TOKEN'] |
||||
|
if self.debug: |
||||
|
print(url) |
||||
|
if 'body' in kwargs['headers']: |
||||
|
print(kwargs['headers']['body']) |
||||
|
res = requests.request(method, url, **kwargs) |
||||
|
res.raise_for_status() |
||||
|
if self.debug: |
||||
|
print(res.content) |
||||
|
return res |
||||
|
|
||||
|
def create_release(self, message, files): |
||||
|
links = ['* ' + self.post_file(filename) for filename in files] |
||||
|
links.insert(0, message) |
||||
|
existing_release = self.fetch_release() |
||||
|
update = False |
||||
|
if existing_release is not None: |
||||
|
links = [existing_release['description'], '---'] + links |
||||
|
update = True |
||||
|
return self.set_release("\n\n".join(links), update) |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=''' |
||||
|
This program is intended to be used in a GitLab CI job in a Runner with Docker. |
||||
|
|
||||
|
### 1. Configure your `.gitlab-ci.yml` |
||||
|
To make an automatic release you need to add something like this to the file |
||||
|
`.gitlab-ci.yml` in your project. |
||||
|
|
||||
|
```yaml |
||||
|
stages: |
||||
|
- build |
||||
|
- publish |
||||
|
build: |
||||
|
stage: build |
||||
|
script: |
||||
|
- my_build_command |
||||
|
artifacts: |
||||
|
expire_in: '1 hour' |
||||
|
paths: |
||||
|
- compiled-$CI_BUILD_TAG.exe |
||||
|
- doc-$CI_BUILD_TAG.pdf |
||||
|
publish: |
||||
|
image: inetprocess/gitlab-release |
||||
|
stage: publish |
||||
|
only: |
||||
|
- tags |
||||
|
script: |
||||
|
- gitlab-release compiled-$CI_BUILD_TAG.exe doc-$CI_BUILD_TAG.pdf |
||||
|
``` |
||||
|
|
||||
|
### 2. Generate a personnal access token |
||||
|
Generate a new [Personal Access Token] |
||||
|
(https://docs.gitlab.com/ee/api/README.html#personal-access-tokens) |
||||
|
from your user profile. |
||||
|
|
||||
|
### 3. Configure your project |
||||
|
Set a [secret variable](https://docs.gitlab.com/ce/ci/variables/#secret-variables) |
||||
|
in your project named `GITLAB_ACCESS_TOKEN` with the token you have generated in |
||||
|
the previous step. |
||||
|
''' |
||||
|
) |
||||
|
parser.add_argument('-m', '--message', default='', |
||||
|
help='Markdown message before the files list in the release note') |
||||
|
parser.add_argument('files', nargs='*', |
||||
|
help='Files to link in the release.') |
||||
|
parser.add_argument('-d', '--debug', action='store_true', |
||||
|
help='Print debug messages') |
||||
|
parser.add_argument('-l', '--links', action='store_true', |
||||
|
help='Print project links') |
||||
|
args = parser.parse_args() |
||||
|
#os.environ['CI_PROJECT_ID'] = 'tesch1%2Fcppduals' |
||||
|
#os.environ['CI_BUILD_TAG'] = 'v0.3.1' |
||||
|
#os.environ['CI_COMMIT_TAG'] = 'v0.3.1' |
||||
|
#os.environ['CI_PROJECT_URL'] = 'https://gitlab.com' |
||||
|
#os.environ['CI_SERVER_VERSION'] = '9.0.0' |
||||
|
#os.environ['GITLAB_ACCESS_TOKEN'] = '' |
||||
|
try: |
||||
|
release = GitlabRelease(args.debug) |
||||
|
#if args.links: |
||||
|
# print(release.fetch_links()) |
||||
|
# sys.exit(0) |
||||
|
info = release.create_release(args.message, args.files) |
||||
|
print("Release: {tag_name} created.\n{description}".format_map(info)) |
||||
|
except GitlabReleaseError as err: |
||||
|
print(err) |
||||
|
sys.exit(1) |
||||
@ -0,0 +1,57 @@ |
|||||
|
<!-- HTML header for doxygen 1.8.14--> |
||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
||||
|
<html xmlns="http://www.w3.org/1999/xhtml"> |
||||
|
<head> |
||||
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> |
||||
|
<meta http-equiv="X-UA-Compatible" content="IE=9"/> |
||||
|
<meta name="generator" content="Doxygen $doxygenversion"/> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/> |
||||
|
<link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" /> |
||||
|
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME--> |
||||
|
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME--> |
||||
|
<!--link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/--> |
||||
|
<script type="text/javascript" src="$relpath^jquery.js"></script> |
||||
|
<script type="text/javascript" src="$relpath^dynsections.js"></script> |
||||
|
$treeview |
||||
|
$search |
||||
|
$mathjax |
||||
|
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" /> |
||||
|
$extrastylesheet |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> |
||||
|
|
||||
|
<!--BEGIN TITLEAREA--> |
||||
|
<div id="titlearea"> |
||||
|
<table cellspacing="0" cellpadding="0"> |
||||
|
<tbody> |
||||
|
<tr style="height: 56px;"> |
||||
|
<!--BEGIN PROJECT_LOGO--> |
||||
|
<td id="projectlogo"><img alt="Logo" height="100" src="$relpath^$projectlogo"/></td> |
||||
|
<!--END PROJECT_LOGO--> |
||||
|
<!--BEGIN PROJECT_NAME--> |
||||
|
<td id="projectalign" style="padding-left: 0.5em;"> |
||||
|
<div id="projectname">$projectname |
||||
|
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER--> |
||||
|
</div> |
||||
|
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF--> |
||||
|
</td> |
||||
|
<!--END PROJECT_NAME--> |
||||
|
<!--BEGIN !PROJECT_NAME--> |
||||
|
<!--BEGIN PROJECT_BRIEF--> |
||||
|
<td style="padding-left: 0.5em;"> |
||||
|
<div id="projectbrief">$projectbrief</div> |
||||
|
</td> |
||||
|
<!--END PROJECT_BRIEF--> |
||||
|
<!--END !PROJECT_NAME--> |
||||
|
<!--BEGIN DISABLE_INDEX--> |
||||
|
<!--BEGIN SEARCHENGINE--> |
||||
|
<td>$searchbox</td> |
||||
|
<!--END SEARCHENGINE--> |
||||
|
<!--END DISABLE_INDEX--> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<!--END TITLEAREA--> |
||||
|
<!-- end header part --> |
||||
@ -0,0 +1,510 @@ |
|||||
|
// This file is part of Eigen, a lightweight C++ template library |
||||
|
// for linear algebra. |
||||
|
// |
||||
|
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
||||
|
// Copyright (C) 2019 Michael Tesch <tesch1@gmail.com> |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
#ifndef EIGEN_CDUAL_AVX_H |
||||
|
#define EIGEN_CDUAL_AVX_H |
||||
|
|
||||
|
namespace Eigen { |
||||
|
|
||||
|
namespace internal { |
||||
|
|
||||
|
#define vec8f_swizzle1(v,p,q,r,s) \ |
||||
|
(_mm256_permute_ps(v, ((s)<<6|(r)<<4|(q)<<2|(p)))) |
||||
|
|
||||
|
#ifdef __AVX2__ |
||||
|
#define vec4d_swizzle1(v,p,q,r,s) \ |
||||
|
(_mm256_permute4x64_pd(v,(s)<<6|(r)<<4|(q)<<2|(p))) |
||||
|
#else |
||||
|
//#error "TODO" |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
//---------- float ---------- |
||||
|
struct Packet2cdf |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2cdf() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet2cdf(const __m256 & a) : v(a) {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet2cdf(const Packet4df & a) : v(a.v) {} |
||||
|
//__m256 v; |
||||
|
Packet4df v; |
||||
|
}; |
||||
|
|
||||
|
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going |
||||
|
// to leverage AVX instructions. |
||||
|
#if !defined(CPPDUALS_DONT_VECTORIZE_CDUAL) |
||||
|
template<> struct packet_traits<std::complex<duals::dual<float> > > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet2cdf type; |
||||
|
typedef Packet1cdf half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 0, |
||||
|
size = 2, |
||||
|
HasHalfPacket = 1, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
#endif |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet2cdf> { |
||||
|
typedef std::complex<duals::dual<float> > type; |
||||
|
enum {size=2, alignment=Aligned32, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet1cdf half; |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf padd<Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_add_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf psub<Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_sub_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pnegate(const Packet2cdf& a) { return Packet2cdf(pnegate(a.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pconj(const Packet2cdf& a) |
||||
|
{ |
||||
|
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000,0x00000000,0x80000000,0x80000000, |
||||
|
0x00000000,0x00000000,0x80000000,0x80000000)); |
||||
|
return Packet2cdf(_mm256_xor_ps(a.v.v,mask)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > pfirst<Packet2cdf>(const Packet2cdf& a) |
||||
|
{ |
||||
|
EIGEN_ALIGN32 float res[8]; |
||||
|
_mm256_store_ps(res, a.v.v); |
||||
|
return std::complex<duals::dual<float> >(duals::dual<float>(res[0],res[1]), |
||||
|
duals::dual<float>(res[2],res[3])); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pmul<Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ |
||||
|
#ifdef __FMA__xx |
||||
|
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000,0x00000000,0xffffffff,0xffffffff, |
||||
|
0x00000000,0x00000000,0xffffffff,0xffffffff)); |
||||
|
Packet2cdf x(vec8f_swizzle1 |
||||
|
(_mm256_addsub_ps(_mm256_fmadd_ps(vec8f_swizzle1(a.v.v, 0, 0, 0, 0), |
||||
|
vec8f_swizzle1(b.v.v, 0, 2, 1, 3), |
||||
|
_mm256_and_ps(mask, |
||||
|
_mm256_mul_ps(vec8f_swizzle1(a.v.v, 0, 0, 1, 1), |
||||
|
vec8f_swizzle1(b.v.v, 0, 0, 0, 2)))), |
||||
|
_mm256_fmadd_ps(vec8f_swizzle1(a.v.v, 2, 2, 2, 2), |
||||
|
vec8f_swizzle1(b.v.v, 2, 0, 3, 1), |
||||
|
_mm256_and_ps(mask, |
||||
|
_mm256_mul_ps(vec8f_swizzle1(a.v.v, 0, 0, 3, 3), |
||||
|
vec8f_swizzle1(b.v.v, 0, 0, 2, 0))))), |
||||
|
0,2,1,3)); |
||||
|
return x; |
||||
|
#else |
||||
|
// help gcc |
||||
|
__m256 y0 = a.v.v; |
||||
|
__m256 y1 = _mm256_permute_ps(y0,0); |
||||
|
__m256 y2 = b.v.v; |
||||
|
__m256 y3 = _mm256_permute_ps(y2,216); |
||||
|
y1 = _mm256_mul_ps(y1,y3); |
||||
|
y3 = _mm256_permute_ps(y0,84); |
||||
|
__m256 y4 = _mm256_permute_ps(y2,132); |
||||
|
y3 = _mm256_mul_ps(y3,y4); |
||||
|
y4 = _mm256_setzero_ps(); |
||||
|
y3 = _mm256_blend_ps(y4,y3,204); |
||||
|
y1 = _mm256_add_ps(y1,y3); |
||||
|
y3 = _mm256_permute_ps(y0,170); |
||||
|
__m256 y5 = _mm256_permute_ps(y2,114); |
||||
|
y3 = _mm256_mul_ps(y3,y5); |
||||
|
y0 = _mm256_movehdup_ps(y0); |
||||
|
y2 = _mm256_permute_ps(y2,36); |
||||
|
y0 = _mm256_mul_ps(y0,y2); |
||||
|
y0 = _mm256_blend_ps(y4,y0,204); |
||||
|
y0 = _mm256_add_ps(y3,y0); |
||||
|
y0 = _mm256_addsub_ps(y1,y0); |
||||
|
y0 = _mm256_permute_ps(y0,216); |
||||
|
return Packet2cdf(y0); |
||||
|
|
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pand <Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_and_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf por <Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_or_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pxor <Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_xor_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pandnot<Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ return Packet2cdf(_mm256_andnot_ps(a.v.v,b.v.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pload <Packet2cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet2cdf(pload<Packet8f>((const float*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf ploadu<Packet2cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ |
||||
|
EIGEN_DEBUG_UNALIGNED_LOAD return Packet2cdf(_mm256_loadu_ps((float*)from)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pset1<Packet2cdf>(const std::complex<duals::dual<float> >& from) |
||||
|
{ |
||||
|
/* here we really have to use unaligned loads :( */ |
||||
|
const __m128 v = ploadu<Packet4f>((float *)&from); |
||||
|
return Packet2cdf(_mm256_insertf128_ps(_mm256_castps128_ps256(v),v,1)); |
||||
|
//return Packet2cdf(_mm256_set_m128(v,v)); // missing on older GCCs |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf ploaddup<Packet2cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ return pset1<Packet2cdf>(*from); } |
||||
|
|
||||
|
// FIXME force unaligned store, this is a temporary fix |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstore <std::complex<duals::dual<float> > >(std::complex<duals::dual<float> > * to, const Packet2cdf& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstore((float*)to, Packet8f(from.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstoreu<std::complex<duals::dual<float> > >(std::complex<duals::dual<float> > * to, const Packet2cdf& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu((float*)to, Packet8f(from.v.v)); } |
||||
|
|
||||
|
//template<> EIGEN_STRONG_INLINE void |
||||
|
//prefetch<std::complex<duals::dual<float> > >(const std::complex<duals::dual<float> > * addr) |
||||
|
//{ _mm256_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf preverse(const Packet2cdf& a) |
||||
|
{ |
||||
|
const __m256 result = _mm256_permute2f128_ps(a.v.v, a.v.v, 1); |
||||
|
return Packet2cdf(result); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > predux<Packet2cdf>(const Packet2cdf& a) |
||||
|
{ |
||||
|
return pfirst(Packet2cdf(_mm256_add_ps(a.v.v, _mm256_permute2f128_ps(a.v.v, a.v.v, 1)))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf preduxp<Packet2cdf>(const Packet2cdf* vecs) |
||||
|
{ |
||||
|
return vecs[0]; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > predux_mul<Packet2cdf>(const Packet2cdf& a) |
||||
|
{ |
||||
|
return pfirst(pmul(a, preverse(a))); |
||||
|
} |
||||
|
|
||||
|
#if 0 |
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet2cdf> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet2cdf& /*first*/, const Packet2cdf& /*second*/) |
||||
|
{ |
||||
|
// FIXME is it sure we never have to align a Packet2cdf? |
||||
|
// Even though a std::complex<duals::dual<float> > has 32 bytes, it is not necessarily aligned on a 32 byte boundary... |
||||
|
} |
||||
|
}; |
||||
|
#endif |
||||
|
|
||||
|
template<> struct conj_helper<Packet2cdf, Packet2cdf, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmadd(const Packet2cdf& x, const Packet2cdf& y, const Packet2cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmul(const Packet2cdf& a, const Packet2cdf& b) const |
||||
|
{ |
||||
|
//#ifdef EIGEN_VECTORIZE_SSE3 |
||||
|
return internal::pmul(a, pconj(b)); |
||||
|
//#else |
||||
|
// TODO for AVX |
||||
|
//const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0)); |
||||
|
//return Packet2cdf(_mm_add_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v.v, 0, 0), b.v), mask), |
||||
|
// _mm_mul_pd(vec2d_swizzle1(a.v, 1, 1), |
||||
|
// vec2d_swizzle1(b.v, 1, 0)))); |
||||
|
//#endif |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet2cdf, Packet2cdf, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmadd(const Packet2cdf& x, const Packet2cdf& y, const Packet2cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmul(const Packet2cdf& a, const Packet2cdf& b) const |
||||
|
{ |
||||
|
//#ifdef EIGEN_VECTORIZE_SSE3 |
||||
|
return internal::pmul(pconj(a), b); |
||||
|
//#else |
||||
|
//const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0)); |
||||
|
//return Packet2cdf(_mm_add_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), |
||||
|
// _mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1), |
||||
|
// vec2d_swizzle1(b.v, 1, 0)), mask))); |
||||
|
//#endif |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet2cdf, Packet2cdf, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmadd(const Packet2cdf& x, const Packet2cdf& y, const Packet2cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet2cdf pmul(const Packet2cdf& a, const Packet2cdf& b) const |
||||
|
{ |
||||
|
//#ifdef EIGEN_VECTORIZE_SSE3 |
||||
|
return pconj(internal::pmul(a, b)); |
||||
|
//#else |
||||
|
//const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0)); |
||||
|
//return Packet2cdf(_mm_sub_pd(_mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), mask), |
||||
|
// _mm_mul_pd(vec2d_swizzle1(a.v, 1, 1), |
||||
|
// vec2d_swizzle1(b.v, 1, 0)))); |
||||
|
//#endif |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
//TODO |
||||
|
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet2cdf,Packet4df) |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2cdf pdiv<Packet2cdf>(const Packet2cdf& a, const Packet2cdf& b) |
||||
|
{ |
||||
|
Packet2cdf res = conj_helper<Packet2cdf,Packet2cdf,false,true>().pmul(a,b); |
||||
|
Packet4df s = pmul(b.v, b.v); |
||||
|
return Packet2cdf(pdiv(res.v, |
||||
|
padd(s, Packet4df(_mm256_castpd_ps(_mm256_shuffle_pd(_mm256_castps_pd(s.v), |
||||
|
_mm256_castps_pd(s.v), 0x5)))))); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet2cdf pcplxflip/* <Packet2cdf> */(const Packet2cdf& x) |
||||
|
{ |
||||
|
return Packet2cdf(vec8f_swizzle1(x.v.v, 2, 3, 0, 1)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_DEVICE_FUNC inline void ptranspose(PacketBlock<Packet2cdf,2> & kernel) |
||||
|
{ |
||||
|
__m256d tmp = _mm256_permute2f128_pd(_mm256_castps_pd(kernel.packet[0].v.v), |
||||
|
_mm256_castps_pd(kernel.packet[1].v.v), 0+(2<<4)); |
||||
|
kernel.packet[1].v.v = _mm256_castpd_ps(_mm256_permute2f128_pd(_mm256_castps_pd(kernel.packet[0].v.v), |
||||
|
_mm256_castps_pd(kernel.packet[1].v.v), 1+(3<<4))); |
||||
|
kernel.packet[0].v.v = _mm256_castpd_ps(tmp); |
||||
|
} |
||||
|
|
||||
|
//---------- double ---------- |
||||
|
#ifdef __AVX2__ |
||||
|
|
||||
|
struct Packet1cdd |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdd() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet1cdd(const __m256d & a) : v(a) {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet1cdd(const Packet2dd & a) : v(a) {} |
||||
|
//__m256d v; |
||||
|
Packet2dd v; |
||||
|
}; |
||||
|
|
||||
|
#if !defined(CPPDUALS_DONT_VECTORIZE_CDUAL) |
||||
|
template<> struct packet_traits<std::complex<duals::dual<double> > > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet1cdd type; |
||||
|
typedef Packet1cdd half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 0, |
||||
|
size = 1, |
||||
|
HasHalfPacket = 0, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
#endif |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet1cdd> { |
||||
|
typedef std::complex<duals::dual<double> > type; |
||||
|
enum {size=1, alignment=Aligned32, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet1cdd half; |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd padd<Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_add_pd(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd psub<Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_sub_pd(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pnegate(const Packet1cdd& a) { return Packet1cdd(pnegate(a.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pconj(const Packet1cdd& a) |
||||
|
{ |
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_set_epi32(0x80000000,0x0,0x80000000,0x0,0x0,0x0,0x0,0x0)); |
||||
|
return Packet1cdd(_mm256_xor_pd(a.v.v,mask)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pmul<Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ |
||||
|
#ifndef __AVX2__ |
||||
|
// TODO |
||||
|
#error "no avx2, really?" |
||||
|
#endif |
||||
|
#ifdef __FMA__ |
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_setr_epi32(0x0,0x0,0x0,0x0, |
||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff)); |
||||
|
return Packet1cdd(vec4d_swizzle1 |
||||
|
(_mm256_addsub_pd(_mm256_fmadd_pd(_mm256_broadcastsd_pd(_mm256_castpd256_pd128(a.v.v)), |
||||
|
vec4d_swizzle1(b.v.v, 0, 2, 1, 3), |
||||
|
_mm256_and_pd(mask, |
||||
|
_mm256_mul_pd(vec4d_swizzle1(a.v.v, 0, 0, 1, 1), |
||||
|
vec4d_swizzle1(b.v.v, 0, 0, 0, 2)))), |
||||
|
_mm256_fmadd_pd(vec4d_swizzle1(a.v.v, 2, 2, 2, 2), |
||||
|
vec4d_swizzle1(b.v.v, 2, 0, 3, 1), |
||||
|
_mm256_and_pd(mask, |
||||
|
_mm256_mul_pd(vec4d_swizzle1(a.v.v, 0, 0, 3, 3), |
||||
|
vec4d_swizzle1(b.v.v, 0, 0, 2, 0))))), |
||||
|
0,2,1,3)); |
||||
|
#else |
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_setr_epi32(0x0,0x0,0x0,0x0, |
||||
|
0xffffffff,0xffffffff,0xffffffff,0xffffffff)); |
||||
|
return Packet1cdd(vec4d_swizzle1 |
||||
|
(_mm256_addsub_pd(_mm256_add_pd(_mm256_mul_pd(_mm256_broadcastsd_pd(_mm256_castpd256_pd128(a.v.v)), |
||||
|
vec4d_swizzle1(b.v.v, 0, 2, 1, 3)), |
||||
|
_mm256_and_pd(mask, |
||||
|
_mm256_mul_pd(vec4d_swizzle1(a.v.v, 0, 0, 1, 1), |
||||
|
vec4d_swizzle1(b.v.v, 0, 0, 0, 2)))), |
||||
|
_mm256_add_pd(_mm256_mul_pd(vec4d_swizzle1(a.v.v, 2, 2, 2, 2), |
||||
|
vec4d_swizzle1(b.v.v, 2, 0, 3, 1)), |
||||
|
_mm256_and_pd(mask, |
||||
|
_mm256_mul_pd(vec4d_swizzle1(a.v.v, 0, 0, 3, 3), |
||||
|
vec4d_swizzle1(b.v.v, 0, 0, 2, 0))))), |
||||
|
0,2,1,3)); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pand <Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_and_pd(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd por <Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_or_pd(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pxor <Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_xor_pd(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pandnot<Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ return Packet1cdd(_mm256_andnot_pd(a.v.v,b.v.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pload <Packet1cdd>(const std::complex<duals::dual<double> >* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet1cdd(ploadu<Packet4d>((const double*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd ploadu<Packet1cdd>(const std::complex<duals::dual<double> >* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet1cdd(ploadu<Packet4d>((const double*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pset1<Packet1cdd>(const std::complex<duals::dual<double> >& from) |
||||
|
{ /* here we really have to use unaligned loads :( */ return ploadu<Packet1cdd>(&from); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd ploaddup<Packet1cdd>(const std::complex<duals::dual<double> >* from) |
||||
|
{ return pset1<Packet1cdd>(*from); } |
||||
|
|
||||
|
// FIXME force unaligned store, this is a temporary fix |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstore <std::complex<duals::dual<double> > >(std::complex<duals::dual<double> > * to, const Packet1cdd& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstoreu((double*)to, from.v.v); } |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstoreu<std::complex<duals::dual<double> > >(std::complex<duals::dual<double> > * to, const Packet1cdd& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v.v); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
prefetch<std::complex<duals::dual<double> > >(const std::complex<duals::dual<double> > * addr) |
||||
|
{ _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<double> > pfirst<Packet1cdd>(const Packet1cdd& a) |
||||
|
{ |
||||
|
EIGEN_ALIGN16 double res[4]; |
||||
|
_mm256_store_pd(res, a.v.v); |
||||
|
return std::complex<duals::dual<double> >(duals::dual<double>(res[0],res[1]), |
||||
|
duals::dual<double>(res[2],res[3])); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd preverse(const Packet1cdd& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<double> > predux<Packet1cdd>(const Packet1cdd& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd preduxp<Packet1cdd>(const Packet1cdd* vecs) |
||||
|
{ |
||||
|
return vecs[0]; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<double> > predux_mul<Packet1cdd>(const Packet1cdd& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet1cdd> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet1cdd& /*first*/, const Packet1cdd& /*second*/) |
||||
|
{ |
||||
|
// FIXME is it sure we never have to align a Packet1cdd? |
||||
|
// Even though a std::complex<duals::dual<double> > has 16 bytes, it is not necessarily aligned on a 16 bytes boundary... |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdd, Packet1cdd, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmadd(const Packet1cdd& x, const Packet1cdd& y, const Packet1cdd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmul(const Packet1cdd& a, const Packet1cdd& b) const |
||||
|
{ |
||||
|
return internal::pmul(a, pconj(b)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdd, Packet1cdd, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmadd(const Packet1cdd& x, const Packet1cdd& y, const Packet1cdd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmul(const Packet1cdd& a, const Packet1cdd& b) const |
||||
|
{ |
||||
|
return internal::pmul(pconj(a), b); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdd, Packet1cdd, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmadd(const Packet1cdd& x, const Packet1cdd& y, const Packet1cdd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdd pmul(const Packet1cdd& a, const Packet1cdd& b) const |
||||
|
{ |
||||
|
return pconj(internal::pmul(a, b)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cdd,Packet2dd) |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdd pdiv<Packet1cdd>(const Packet1cdd& a, const Packet1cdd& b) |
||||
|
{ |
||||
|
//Packet2cd num = pmul(a, pconj(b)); |
||||
|
//__m256d tmp = _mm256_mul_pd(b.v, b.v); |
||||
|
//__m256d denom = _mm256_hadd_pd(tmp, tmp); |
||||
|
//return Packet2cd(_mm256_div_pd(num.v, denom)); |
||||
|
|
||||
|
Packet1cdd num = conj_helper<Packet1cdd,Packet1cdd,false,true>().pmul(a,b); |
||||
|
Packet2dd tmp = pmul(b.v, b.v); |
||||
|
Packet2dd denom ( _mm256_add_pd(tmp.v, |
||||
|
_mm256_permute2f128_pd(tmp.v,tmp.v, 1))); |
||||
|
return Packet1cdd(pdiv(num.v, denom)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdd pcplxflip/* <Packet1cdd> */(const Packet1cdd& x) |
||||
|
{ |
||||
|
return Packet1cdd(_mm256_permute2f128_pd(x.v.v,x.v.v, 1)); |
||||
|
} |
||||
|
#else |
||||
|
#warning "AVX2 disabled: not vectorizing std::complex<dual<double>>" |
||||
|
#endif |
||||
|
|
||||
|
} // end namespace internal |
||||
|
|
||||
|
} // end namespace Eigen |
||||
|
|
||||
|
#endif // EIGEN_CDUAL_AVX_H |
||||
@ -0,0 +1,548 @@ |
|||||
|
// This file is part of Eigen, a lightweight C++ template library |
||||
|
// for linear algebra. |
||||
|
// |
||||
|
// Copyright (C) 2014 Benoit Steiner (benoit.steiner.goog@gmail.com) |
||||
|
// Copyright (C) 2019 Michael Tesch <tesch1@gmail.com> |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
#ifndef EIGEN_DUAL_AVX_H |
||||
|
#define EIGEN_DUAL_AVX_H |
||||
|
|
||||
|
namespace Eigen { |
||||
|
|
||||
|
namespace internal { |
||||
|
|
||||
|
//---------- float ---------- |
||||
|
struct Packet4df |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet4df() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet4df(const __m256& a) : v(a) {} |
||||
|
__m256 v; |
||||
|
}; |
||||
|
|
||||
|
template<> struct packet_traits<duals::dual<float> > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet4df type; |
||||
|
typedef Packet2df half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 1, |
||||
|
size = 4, |
||||
|
HasHalfPacket = 1, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet4df> { |
||||
|
typedef duals::dual<float> type; |
||||
|
enum {size=4, alignment=Aligned32, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet2df half; |
||||
|
}; |
||||
|
|
||||
|
//template<> EIGEN_STRONG_INLINE Packet4df pzero(const Packet4df& /*a*/) { return Packet4df(_mm256_setzero_ps()); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df padd<Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_add_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df psub<Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_sub_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pnegate(const Packet4df& a) |
||||
|
{ |
||||
|
return Packet4df(pnegate(a.v)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pdconj(const Packet4df& a) |
||||
|
{ |
||||
|
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000, |
||||
|
0x00000000,0x80000000,0x00000000,0x80000000)); |
||||
|
return Packet4df(_mm256_xor_ps(a.v,mask)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pconj(const Packet4df& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pmul<Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ |
||||
|
#ifdef xx__FMA__ |
||||
|
__m256 result = _mm256_fmadd_ps(_mm256_moveldup_ps(a.v), |
||||
|
b.v, |
||||
|
_mm256_blend_ps(_mm256_setzero_ps(), |
||||
|
_mm256_mul_ps(_mm256_moveldup_ps(b.v), a.v), 0xaa)); |
||||
|
return Packet4df(result); |
||||
|
#else |
||||
|
__m256 result = _mm256_add_ps(_mm256_mul_ps(_mm256_moveldup_ps(a.v), b.v), |
||||
|
_mm256_blend_ps(_mm256_setzero_ps(), |
||||
|
_mm256_mul_ps(_mm256_moveldup_ps(b.v), a.v), 0xaa)); |
||||
|
#endif |
||||
|
return Packet4df(result); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pand <Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_and_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df por <Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_or_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pxor <Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_xor_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pandnot<Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ return Packet4df(_mm256_andnot_ps(a.v,b.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pload1<Packet4df>(const duals::dual<float>* from) |
||||
|
{ |
||||
|
return Packet4df(_mm256_castpd_ps(_mm256_broadcast_sd((const double*)(const void*)from))); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pload <Packet4df>(const duals::dual<float>* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet4df(pload<Packet8f>(&numext::real_ref(*from))); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet4df ploadu<Packet4df>(const duals::dual<float>* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet4df(ploadu<Packet8f>(&numext::real_ref(*from))); } |
||||
|
|
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pset1<Packet4df>(const duals::dual<float>& from) |
||||
|
{ |
||||
|
return Packet4df(_mm256_castpd_ps(_mm256_broadcast_sd((const double*)(const void*)&from))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df ploaddup<Packet4df>(const duals::dual<float>* from) |
||||
|
{ |
||||
|
// FIXME The following might be optimized using _mm256_movedup_pd |
||||
|
Packet2df a = ploaddup<Packet2df>(from); |
||||
|
Packet2df b = ploaddup<Packet2df>(from+1); |
||||
|
return Packet4df(_mm256_insertf128_ps(_mm256_castps128_ps256(a.v), b.v, 1)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void pstore <duals::dual<float> >(duals::dual<float>* to, const Packet4df& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstore(&numext::real_ref(*to), from.v); } |
||||
|
template<> EIGEN_STRONG_INLINE void pstoreu<duals::dual<float> >(duals::dual<float>* to, const Packet4df& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), from.v); } |
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline Packet4df pgather<duals::dual<float>, Packet4df>(const duals::dual<float>* from, |
||||
|
Index stride) |
||||
|
{ |
||||
|
return Packet4df(_mm256_set_ps(duals::dpart(from[3*stride]), duals::rpart(from[3*stride]), |
||||
|
duals::dpart(from[2*stride]), duals::rpart(from[2*stride]), |
||||
|
duals::dpart(from[1*stride]), duals::rpart(from[1*stride]), |
||||
|
duals::dpart(from[0*stride]), duals::rpart(from[0*stride]))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline void pscatter<duals::dual<float>, Packet4df>(duals::dual<float>* to, |
||||
|
const Packet4df& from, Index stride) |
||||
|
{ |
||||
|
__m128 low = _mm256_extractf128_ps(from.v, 0); |
||||
|
to[stride*0] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 0)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(low, low, 1))); |
||||
|
to[stride*1] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(low, low, 2)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(low, low, 3))); |
||||
|
|
||||
|
__m128 high = _mm256_extractf128_ps(from.v, 1); |
||||
|
to[stride*2] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 0)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(high, high, 1))); |
||||
|
to[stride*3] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(high, high, 2)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(high, high, 3))); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> pfirst<Packet4df>(const Packet4df& a) |
||||
|
{ |
||||
|
return pfirst(Packet2df(_mm256_castps256_ps128(a.v))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df preverse(const Packet4df& a) { |
||||
|
__m128 low = _mm256_extractf128_ps(a.v, 0); |
||||
|
__m128 high = _mm256_extractf128_ps(a.v, 1); |
||||
|
__m128d lowd = _mm_castps_pd(low); |
||||
|
__m128d highd = _mm_castps_pd(high); |
||||
|
low = _mm_castpd_ps(_mm_shuffle_pd(lowd,lowd,0x1)); |
||||
|
high = _mm_castpd_ps(_mm_shuffle_pd(highd,highd,0x1)); |
||||
|
__m256 result = _mm256_setzero_ps(); |
||||
|
result = _mm256_insertf128_ps(result, low, 1); |
||||
|
result = _mm256_insertf128_ps(result, high, 0); |
||||
|
return Packet4df(result); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> predux<Packet4df>(const Packet4df& a) |
||||
|
{ |
||||
|
return predux(padd(Packet2df(_mm256_extractf128_ps(a.v,0)), |
||||
|
Packet2df(_mm256_extractf128_ps(a.v,1)))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df preduxp<Packet4df>(const Packet4df* vecs) |
||||
|
{ |
||||
|
Packet8f t0 = _mm256_shuffle_ps(vecs[0].v, vecs[0].v, _MM_SHUFFLE(3, 1, 2 ,0)); |
||||
|
Packet8f t1 = _mm256_shuffle_ps(vecs[1].v, vecs[1].v, _MM_SHUFFLE(3, 1, 2 ,0)); |
||||
|
t0 = _mm256_hadd_ps(t0,t1); |
||||
|
Packet8f t2 = _mm256_shuffle_ps(vecs[2].v, vecs[2].v, _MM_SHUFFLE(3, 1, 2 ,0)); |
||||
|
Packet8f t3 = _mm256_shuffle_ps(vecs[3].v, vecs[3].v, _MM_SHUFFLE(3, 1, 2 ,0)); |
||||
|
t2 = _mm256_hadd_ps(t2,t3); |
||||
|
|
||||
|
t1 = _mm256_permute2f128_ps(t0,t2, 0 + (2<<4)); |
||||
|
t3 = _mm256_permute2f128_ps(t0,t2, 1 + (3<<4)); |
||||
|
|
||||
|
return Packet4df(_mm256_add_ps(t1,t3)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> predux_mul<Packet4df>(const Packet4df& a) |
||||
|
{ |
||||
|
return predux_mul(pmul(Packet2df(_mm256_extractf128_ps(a.v, 0)), |
||||
|
Packet2df(_mm256_extractf128_ps(a.v, 1)))); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet4df> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet4df& first, const Packet4df& second) |
||||
|
{ |
||||
|
if (Offset==0) return; |
||||
|
palign_impl<Offset*2,Packet8f>::run(first.v, second.v); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#if 0 // TODO |
||||
|
template<> struct dconj_helper<Packet4df, Packet4df, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet4df pmadd(const Packet4df& x, const Packet4df& y, const Packet4df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet4df pmul(const Packet4df& a, const Packet4df& b) const |
||||
|
{ return internal::pmul(a, pdconj(b)); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet4df, Packet4df, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet4df pmadd(const Packet4df& x, const Packet4df& y, const Packet4df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet4df pmul(const Packet4df& a, const Packet4df& b) const |
||||
|
{ return internal::pmul(pdconj(a), b); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet4df, Packet4df, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet4df pmadd(const Packet4df& x, const Packet4df& y, const Packet4df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet4df pmul(const Packet4df& a, const Packet4df& b) const |
||||
|
{ return pdconj(internal::pmul(a, b)); } |
||||
|
}; |
||||
|
EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL(Packet4df,Packet8f) |
||||
|
#endif |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pdiv<Packet4df>(const Packet4df& a, const Packet4df& b) |
||||
|
{ |
||||
|
#if 0 |
||||
|
// approxer, but faster? |
||||
|
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0x00000000,0xffffffff,0x00000000,0xffffffff, |
||||
|
0x00000000,0xffffffff,0x00000000,0xffffffff)); |
||||
|
__m256 xr = _mm256_moveldup_ps(b.v); |
||||
|
__m256 num = _mm256_sub_ps(_mm256_mul_ps(a.v, xr), |
||||
|
_mm256_and_ps(mask, |
||||
|
_mm256_mul_ps(b.v, _mm256_moveldup_ps(a.v)))); |
||||
|
return Packet4df(_mm256_div_ps(num, |
||||
|
_mm256_mul_ps(xr,xr))); |
||||
|
#else |
||||
|
const __m256 mask = _mm256_castsi256_ps(_mm256_setr_epi32(0xffffffff,0x00000000,0xffffffff,0x00000000, |
||||
|
0xffffffff,0x00000000,0xffffffff,0x00000000)); |
||||
|
__m256 xr = _mm256_moveldup_ps(b.v); |
||||
|
__m256 r = _mm256_div_ps(_mm256_add_ps(_mm256_and_ps(mask, a.v), |
||||
|
_mm256_andnot_ps(mask, |
||||
|
_mm256_sub_ps(_mm256_mul_ps(a.v, xr), |
||||
|
_mm256_mul_ps(b.v, _mm256_moveldup_ps(a.v))))), |
||||
|
_mm256_add_ps(_mm256_and_ps(mask, b.v), |
||||
|
_mm256_andnot_ps(mask, |
||||
|
_mm256_mul_ps(xr,xr)))); |
||||
|
return Packet4df(r); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
//---------- double ---------- |
||||
|
struct Packet2dd |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2dd() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet2dd(const __m256d& a) : v(a) {} |
||||
|
__m256d v; |
||||
|
}; |
||||
|
|
||||
|
template<> struct packet_traits<duals::dual<double> > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet2dd type; |
||||
|
#if EIGEN_VERSION_AT_LEAST(3, 3, 8) |
||||
|
// sometime after 3.3.7 gebp_traits cant deal with this |
||||
|
#define TWODD_NOHALF |
||||
|
#endif |
||||
|
#ifdef TWODD_NOHALF |
||||
|
typedef Packet2dd half; |
||||
|
#else |
||||
|
typedef Packet1dd half; |
||||
|
#endif |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 0, |
||||
|
size = 2, |
||||
|
#ifdef TWODD_NOHALF |
||||
|
HasHalfPacket = 0, |
||||
|
#else |
||||
|
HasHalfPacket = 1, |
||||
|
#endif |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet2dd> { |
||||
|
typedef duals::dual<double> type; |
||||
|
enum {size=2, alignment=Aligned32, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
#ifdef TWODD_NOHALF |
||||
|
typedef Packet2dd half; |
||||
|
#else |
||||
|
typedef Packet1dd half; |
||||
|
#endif |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd padd<Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_add_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd psub<Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_sub_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pnegate(const Packet2dd& a) { return Packet2dd(pnegate(a.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pdconj(const Packet2dd& a) |
||||
|
{ |
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_set_epi32(0x80000000,0x0,0x0,0x0,0x80000000,0x0,0x0,0x0)); |
||||
|
return Packet2dd(_mm256_xor_pd(a.v,mask)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pconj(const Packet2dd& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pmul<Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ |
||||
|
#if 0 |
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_set_epi32(0xffffffff,0xffffffff,0x0,0x0, |
||||
|
0xffffffff,0xffffffff,0x0,0x0)); |
||||
|
return Packet2dd(_mm256_add_pd(_mm256_and_pd(mask, |
||||
|
_mm256_mul_pd(a.v, _mm256_shuffle_pd(b.v,b.v,0x0))), |
||||
|
_mm256_mul_pd(b.v, _mm256_shuffle_pd(a.v,a.v,0x0)))); |
||||
|
#else |
||||
|
#ifdef __FMA__ // not sure if this is actually faster. |
||||
|
return Packet2dd(_mm256_fmadd_pd(b.v, |
||||
|
_mm256_movedup_pd(a.v), |
||||
|
_mm256_blend_pd(_mm256_setzero_pd(), |
||||
|
_mm256_mul_pd(a.v, _mm256_movedup_pd(b.v)), |
||||
|
0xa))); |
||||
|
#else |
||||
|
return Packet2dd(_mm256_add_pd(_mm256_mul_pd(b.v,_mm256_movedup_pd(a.v)), |
||||
|
_mm256_blend_pd(_mm256_setzero_pd(), |
||||
|
_mm256_mul_pd(a.v, _mm256_movedup_pd(b.v)), |
||||
|
0xa))); |
||||
|
#endif |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pand <Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_and_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd por <Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_or_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pxor <Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_xor_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pandnot<Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ return Packet2dd(_mm256_andnot_pd(a.v,b.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pload <Packet2dd>(const duals::dual<double>* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet2dd(pload<Packet4d>((const double*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd ploadu<Packet2dd>(const duals::dual<double>* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet2dd(ploadu<Packet4d>((const double*)from)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pset1<Packet2dd>(const duals::dual<double>& from) |
||||
|
{ |
||||
|
// in case casting to a __m128d* is really not safe, then we can still fallback to this version: (much slower though) |
||||
|
// return Packet2dd(_mm256_loadu2_m128d((const double*)&from,(const double*)&from)); |
||||
|
return Packet2dd(_mm256_broadcast_pd((const __m128d*)(const void*)&from)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd ploaddup<Packet2dd>(const duals::dual<double>* from) |
||||
|
{ return pset1<Packet2dd>(*from); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void pstore <duals::dual<double> >(duals::dual<double> * to, const Packet2dd& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, from.v); } |
||||
|
template<> EIGEN_STRONG_INLINE void pstoreu<duals::dual<double> >(duals::dual<double> * to, const Packet2dd& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, from.v); } |
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline Packet2dd pgather<duals::dual<double>, Packet2dd>(const duals::dual<double>* from, |
||||
|
Index stride) |
||||
|
{ |
||||
|
return Packet2dd(_mm256_set_pd(duals::dpart(from[1*stride]), duals::rpart(from[1*stride]), |
||||
|
duals::dpart(from[0*stride]), duals::rpart(from[0*stride]))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline void pscatter<duals::dual<double>, Packet2dd>(duals::dual<double>* to, |
||||
|
const Packet2dd& from, Index stride) |
||||
|
{ |
||||
|
__m128d low = _mm256_extractf128_pd(from.v, 0); |
||||
|
to[stride*0] = duals::dual<double>(_mm_cvtsd_f64(low), _mm_cvtsd_f64(_mm_shuffle_pd(low, low, 1))); |
||||
|
__m128d high = _mm256_extractf128_pd(from.v, 1); |
||||
|
to[stride*1] = duals::dual<double>(_mm_cvtsd_f64(high), _mm_cvtsd_f64(_mm_shuffle_pd(high, high, 1))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> pfirst<Packet2dd>(const Packet2dd& a) |
||||
|
{ |
||||
|
__m128d low = _mm256_extractf128_pd(a.v, 0); |
||||
|
EIGEN_ALIGN16 double res[2]; |
||||
|
_mm_store_pd(res, low); |
||||
|
return duals::dual<double>(res[0],res[1]); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd preverse(const Packet2dd& a) { |
||||
|
__m256d result = _mm256_permute2f128_pd(a.v, a.v, 1); |
||||
|
return Packet2dd(result); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> predux<Packet2dd>(const Packet2dd& a) |
||||
|
{ |
||||
|
return predux(padd(Packet1dd(_mm256_extractf128_pd(a.v,0)), |
||||
|
Packet1dd(_mm256_extractf128_pd(a.v,1)))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd preduxp<Packet2dd>(const Packet2dd* vecs) |
||||
|
{ |
||||
|
Packet4d t0 = _mm256_permute2f128_pd(vecs[0].v,vecs[1].v, 0 + (2<<4)); |
||||
|
Packet4d t1 = _mm256_permute2f128_pd(vecs[0].v,vecs[1].v, 1 + (3<<4)); |
||||
|
|
||||
|
return Packet2dd(_mm256_add_pd(t0,t1)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> predux_mul<Packet2dd>(const Packet2dd& a) |
||||
|
{ |
||||
|
return pfirst(pmul(Packet1dd(_mm256_extractf128_pd(a.v,0)), |
||||
|
Packet1dd(_mm256_extractf128_pd(a.v,1)))); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet2dd> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet2dd& first, const Packet2dd& second) |
||||
|
{ |
||||
|
if (Offset==0) return; |
||||
|
palign_impl<Offset*2,Packet4d>::run(first.v, second.v); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#if 0 // TODO |
||||
|
template<> struct dconj_helper<Packet2dd, Packet2dd, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmadd(const Packet2dd& x, const Packet2dd& y, const Packet2dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmul(const Packet2dd& a, const Packet2dd& b) const |
||||
|
{ return internal::pmul(a, pdconj(b)); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet2dd, Packet2dd, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmadd(const Packet2dd& x, const Packet2dd& y, const Packet2dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmul(const Packet2dd& a, const Packet2dd& b) const |
||||
|
{ return internal::pmul(pdconj(a), b); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet2dd, Packet2dd, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmadd(const Packet2dd& x, const Packet2dd& y, const Packet2dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2dd pmul(const Packet2dd& a, const Packet2dd& b) const |
||||
|
{ return pdconj(internal::pmul(a, b)); } |
||||
|
}; |
||||
|
EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL(Packet2dd,Packet4d) |
||||
|
#endif |
||||
|
|
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pdiv<Packet2dd>(const Packet2dd& a, const Packet2dd& b) |
||||
|
{ |
||||
|
#if 1 |
||||
|
// help gcc to not use 12 registers :P |
||||
|
__m256d y1 = _mm256_setzero_pd(); |
||||
|
__m256d y2 = _mm256_blend_pd(a.v, y1, 0xa); |
||||
|
__m256d y4 = _mm256_movedup_pd(b.v); |
||||
|
y4 = _mm256_mul_pd(a.v, y4); |
||||
|
__m256d y0 = _mm256_movedup_pd(a.v); |
||||
|
y0 = _mm256_mul_pd(b.v, y0); |
||||
|
y0 = _mm256_sub_pd(y4, y0); |
||||
|
y0 = _mm256_blend_pd(y1, y0, 0xa); |
||||
|
y0 = _mm256_add_pd(y2, y0); |
||||
|
y2 = _mm256_blend_pd(b.v, y1, 0xa); |
||||
|
__m256d y3 = _mm256_mul_pd(b.v, b.v); |
||||
|
y1 = _mm256_unpacklo_pd(y1, y3); |
||||
|
y1 = _mm256_add_pd(y2, y1); |
||||
|
return Packet2dd(_mm256_div_pd(y0, y1)); |
||||
|
#else |
||||
|
|
||||
|
const __m256d mask = _mm256_castsi256_pd(_mm256_setr_epi32(0xffffffff,0xffffffff,0x00000000,0x00000000, |
||||
|
0xffffffff,0xffffffff,0x00000000,0x00000000)); |
||||
|
return Packet2dd(_mm256_div_pd |
||||
|
(_mm256_add_pd(_mm256_and_pd(mask, a.v), |
||||
|
_mm256_andnot_pd(mask, |
||||
|
_mm256_sub_pd(_mm256_mul_pd(a.v, |
||||
|
_mm256_shuffle_pd(b.v,b.v,0x0)), |
||||
|
_mm256_mul_pd(b.v, |
||||
|
_mm256_shuffle_pd(a.v,a.v,0x0))))), |
||||
|
_mm256_add_pd(_mm256_and_pd(mask, b.v), |
||||
|
_mm256_andnot_pd(mask, |
||||
|
_mm256_mul_pd(_mm256_shuffle_pd(b.v,b.v,0x0), |
||||
|
_mm256_shuffle_pd(b.v,b.v,0x0)))))); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
EIGEN_DEVICE_FUNC inline void |
||||
|
ptranspose(PacketBlock<Packet4df,4>& kernel) { |
||||
|
__m256d P0 = _mm256_castps_pd(kernel.packet[0].v); |
||||
|
__m256d P1 = _mm256_castps_pd(kernel.packet[1].v); |
||||
|
__m256d P2 = _mm256_castps_pd(kernel.packet[2].v); |
||||
|
__m256d P3 = _mm256_castps_pd(kernel.packet[3].v); |
||||
|
__m256d T0 = _mm256_shuffle_pd(P0, P1, 15); |
||||
|
__m256d T1 = _mm256_shuffle_pd(P0, P1, 0); |
||||
|
__m256d T2 = _mm256_shuffle_pd(P2, P3, 15); |
||||
|
__m256d T3 = _mm256_shuffle_pd(P2, P3, 0); |
||||
|
kernel.packet[1].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 32)); |
||||
|
kernel.packet[3].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T0, T2, 49)); |
||||
|
kernel.packet[0].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 32)); |
||||
|
kernel.packet[2].v = _mm256_castpd_ps(_mm256_permute2f128_pd(T1, T3, 49)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_DEVICE_FUNC inline void |
||||
|
ptranspose(PacketBlock<Packet2dd,2>& kernel) { |
||||
|
__m256d tmp = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 0+(2<<4)); |
||||
|
kernel.packet[1].v = _mm256_permute2f128_pd(kernel.packet[0].v, kernel.packet[1].v, 1+(3<<4)); |
||||
|
kernel.packet[0].v = tmp; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pinsertfirst(const Packet4df& a, duals::dual<float> b) |
||||
|
{ |
||||
|
return Packet4df(_mm256_blend_ps(a.v,pset1<Packet4df>(b).v,1|2)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pinsertfirst(const Packet2dd& a, duals::dual<double> b) |
||||
|
{ |
||||
|
return Packet2dd(_mm256_blend_pd(a.v,pset1<Packet2dd>(b).v,1|2)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet4df pinsertlast(const Packet4df& a, duals::dual<float> b) |
||||
|
{ |
||||
|
return Packet4df(_mm256_blend_ps(a.v,pset1<Packet4df>(b).v,(1<<7)|(1<<6))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2dd pinsertlast(const Packet2dd& a, duals::dual<double> b) |
||||
|
{ |
||||
|
return Packet2dd(_mm256_blend_pd(a.v,pset1<Packet2dd>(b).v,(1<<3)|(1<<2))); |
||||
|
} |
||||
|
|
||||
|
} // end namespace internal |
||||
|
|
||||
|
} // end namespace Eigen |
||||
|
|
||||
|
#endif // EIGEN_DUAL_AVX_H |
||||
@ -0,0 +1,229 @@ |
|||||
|
// This file is part of Eigen, a lightweight C++ template library |
||||
|
// for linear algebra. |
||||
|
// |
||||
|
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
||||
|
// Copyright (C) 2019 Michael Tesch <tesch1@gmail.com> |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
#ifndef EIGEN_CDUAL_SSE_H |
||||
|
#define EIGEN_CDUAL_SSE_H |
||||
|
|
||||
|
namespace Eigen { |
||||
|
|
||||
|
namespace internal { |
||||
|
|
||||
|
//---------- float ---------- |
||||
|
struct Packet1cdf |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdf() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet1cdf(const __m128 & a) : v(a) {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet1cdf(const Packet2df & a) : v(a) {} |
||||
|
//__m128 v; |
||||
|
Packet2df v; |
||||
|
}; |
||||
|
|
||||
|
// Use the packet_traits defined in AVX/ComplexDual.h instead if we're |
||||
|
// going to leverage AVX instructions. |
||||
|
#if !defined(CPPDUALS_DONT_VECTORIZE_CDUAL) |
||||
|
#if !defined(EIGEN_VECTORIZE_AVX) |
||||
|
template<> struct packet_traits<std::complex<duals::dual<float> > > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet1cdf type; |
||||
|
typedef Packet1cdf half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 0, |
||||
|
size = 1, |
||||
|
HasHalfPacket = 0, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet1cdf> { |
||||
|
typedef std::complex<duals::dual<float> > type; |
||||
|
enum {size=1, alignment=Aligned16, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet1cdf half; |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf padd<Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_add_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf psub<Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_sub_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pnegate(const Packet1cdf& a) { return Packet1cdf(pnegate(a.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pconj(const Packet1cdf& a) |
||||
|
{ |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_set_epi32(0x80000000,0x80000000,0x0,0x0)); |
||||
|
return Packet1cdf(_mm_xor_ps(a.v.v,mask)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pmul<Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ |
||||
|
#if 1 // defined(EIGEN_VECTORIZE_SSE3) |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x00000000,0xffffffff,0xffffffff)); |
||||
|
return Packet1cdf(vec4f_swizzle1 |
||||
|
(_mm_addsub_ps(_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 0, 0, 0), |
||||
|
vec4f_swizzle1(b.v.v, 0, 2, 1, 3)), |
||||
|
_mm_and_ps(mask, |
||||
|
_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 0, 1, 1), |
||||
|
vec4f_swizzle1(b.v.v, 0, 0, 0, 2)))), |
||||
|
_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v.v, 2, 2, 2, 2), |
||||
|
vec4f_swizzle1(b.v.v, 2, 0, 3, 1)), |
||||
|
_mm_and_ps(mask, |
||||
|
_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 0, 3, 3), |
||||
|
vec4f_swizzle1(b.v.v, 0, 0, 2, 0))))), |
||||
|
0,2,1,3)); |
||||
|
#else |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0xffffffff,0x00000000,0xffffffff)); |
||||
|
const __m128 nega = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x00000000,0x00000000)); |
||||
|
return Packet1cdf(_mm_add_ps(_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 0, 0, 0), |
||||
|
vec4f_swizzle1(b.v.v, 0, 1, 2, 3)), |
||||
|
_mm_and_ps(mask, |
||||
|
_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 1, 0, 1), |
||||
|
vec4f_swizzle1(b.v.v, 0, 0, 0, 2)))), |
||||
|
_mm_xor_ps |
||||
|
(nega, |
||||
|
_mm_add_ps(_mm_mul_ps(vec4f_swizzle1(a.v.v, 2, 2, 2, 2), |
||||
|
vec4f_swizzle1(b.v.v, 2, 3, 0, 1)), |
||||
|
_mm_and_ps(mask, |
||||
|
_mm_mul_ps(vec4f_swizzle1(a.v.v, 0, 3, 0, 3), |
||||
|
vec4f_swizzle1(b.v.v, 0, 2, 0, 0))))))); |
||||
|
#endif |
||||
|
return a; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pand <Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_and_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf por <Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_or_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pxor <Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_xor_ps(a.v.v,b.v.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pandnot<Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ return Packet1cdf(_mm_andnot_ps(a.v.v,b.v.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pload <Packet1cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet1cdf(ploadu<Packet4f>((const float*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf ploadu<Packet1cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet1cdf(ploadu<Packet4f>((const float*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pset1<Packet1cdf>(const std::complex<duals::dual<float> >& from) |
||||
|
{ /* here we really have to use unaligned loads :( */ return ploadu<Packet1cdf>(&from); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf ploaddup<Packet1cdf>(const std::complex<duals::dual<float> >* from) |
||||
|
{ return pset1<Packet1cdf>(*from); } |
||||
|
|
||||
|
// FIXME force unaligned store, this is a temporary fix |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstore <std::complex<duals::dual<float> > >(std::complex<duals::dual<float> > * to, const Packet1cdf& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstoreu((float*)to, from.v.v); } |
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
pstoreu<std::complex<duals::dual<float> > >(std::complex<duals::dual<float> > * to, const Packet1cdf& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu((float*)to, from.v.v); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void |
||||
|
prefetch<std::complex<duals::dual<float> > >(const std::complex<duals::dual<float> > * addr) |
||||
|
{ _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > pfirst<Packet1cdf>(const Packet1cdf& a) |
||||
|
{ |
||||
|
EIGEN_ALIGN16 float res[4]; |
||||
|
_mm_store_ps(res, a.v.v); |
||||
|
return std::complex<duals::dual<float> >(duals::dual<float>(res[0],res[1]), |
||||
|
duals::dual<float>(res[2],res[3])); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf preverse(const Packet1cdf& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > predux<Packet1cdf>(const Packet1cdf& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf preduxp<Packet1cdf>(const Packet1cdf* vecs) |
||||
|
{ |
||||
|
return vecs[0]; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE std::complex<duals::dual<float> > predux_mul<Packet1cdf>(const Packet1cdf& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet1cdf> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet1cdf& /*first*/, const Packet1cdf& /*second*/) |
||||
|
{ |
||||
|
// FIXME is it sure we never have to align a Packet1cdf? |
||||
|
// Even though a std::complex<duals::dual<float> > has 16 bytes, it is not necessarily aligned on a 16 bytes boundary... |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdf, Packet1cdf, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmadd(const Packet1cdf& x, const Packet1cdf& y, const Packet1cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmul(const Packet1cdf& a, const Packet1cdf& b) const |
||||
|
{ |
||||
|
return internal::pmul(a, pconj(b)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdf, Packet1cdf, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmadd(const Packet1cdf& x, const Packet1cdf& y, const Packet1cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmul(const Packet1cdf& a, const Packet1cdf& b) const |
||||
|
{ |
||||
|
return internal::pmul(pconj(a), b); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<> struct conj_helper<Packet1cdf, Packet1cdf, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmadd(const Packet1cdf& x, const Packet1cdf& y, const Packet1cdf& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdf pmul(const Packet1cdf& a, const Packet1cdf& b) const |
||||
|
{ |
||||
|
return pconj(internal::pmul(a, b)); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
//TODO |
||||
|
EIGEN_MAKE_CONJ_HELPER_CPLX_REAL(Packet1cdf,Packet2df) |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1cdf pdiv<Packet1cdf>(const Packet1cdf& a, const Packet1cdf& b) |
||||
|
{ |
||||
|
Packet1cdf res = conj_helper<Packet1cdf,Packet1cdf,false,true>().pmul(a,b); |
||||
|
Packet2df s = pmul(b.v, b.v); |
||||
|
return Packet1cdf(pdiv(res.v, |
||||
|
padd(s, Packet2df(_mm_castpd_ps(_mm_shuffle_pd(_mm_castps_pd(s.v), |
||||
|
_mm_castps_pd(s.v), 0x1)))))); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE Packet1cdf pcplxflip/* <Packet1cdf> */(const Packet1cdf& x) |
||||
|
{ |
||||
|
return Packet1cdf(vec4f_swizzle1(x.v.v, 2, 3, 0, 1)); |
||||
|
} |
||||
|
|
||||
|
} // end namespace internal |
||||
|
|
||||
|
} // end namespace Eigen |
||||
|
|
||||
|
#endif // EIGEN_CDUAL_SSE_H |
||||
@ -0,0 +1,459 @@ |
|||||
|
// This file is part of Eigen, a lightweight C++ template library |
||||
|
// for linear algebra. |
||||
|
// |
||||
|
// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> |
||||
|
// Copyright (C) 2019 Michael Tesch <tesch1@gmail.com> |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
#ifndef EIGEN_DUAL_SSE_H |
||||
|
#define EIGEN_DUAL_SSE_H |
||||
|
|
||||
|
namespace Eigen { |
||||
|
|
||||
|
namespace internal { |
||||
|
|
||||
|
//---------- float ---------- |
||||
|
struct Packet2df |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2df() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet2df(const __m128& a) : v(a) {} |
||||
|
__m128 v; |
||||
|
}; |
||||
|
|
||||
|
// Use the packet_traits defined in AVX/Dual.h instead if we're going |
||||
|
// to leverage AVX instructions. |
||||
|
#ifndef EIGEN_VECTORIZE_AVX |
||||
|
template<> struct packet_traits<duals::dual<float> > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet2df type; |
||||
|
typedef Packet2df half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 1, |
||||
|
size = 2, |
||||
|
HasHalfPacket = 0, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0, |
||||
|
HasBlend = 1 |
||||
|
}; |
||||
|
}; |
||||
|
#endif |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet2df> { |
||||
|
typedef duals::dual<float> type; |
||||
|
enum {size=2, alignment=Aligned16, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet2df half; |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df padd<Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_add_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df psub<Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_sub_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pnegate(const Packet2df& a) |
||||
|
{ |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x80000000,0x80000000,0x80000000,0x80000000)); |
||||
|
return Packet2df(_mm_xor_ps(a.v,mask)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pdconj(const Packet2df& a) |
||||
|
{ |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0x80000000,0x00000000,0x80000000)); |
||||
|
return Packet2df(_mm_xor_ps(a.v,mask)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pconj(const Packet2df& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pmul<Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ |
||||
|
#if defined(EIGEN_VECTORIZE_SSE3) |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0xffffffff,0x00000000,0xffffffff)); |
||||
|
return Packet2df(_mm_add_ps(_mm_and_ps(mask, _mm_mul_ps(a.v, _mm_moveldup_ps(b.v))), |
||||
|
_mm_mul_ps(b.v, _mm_moveldup_ps(a.v)))); |
||||
|
#else |
||||
|
//TODO-use avx instructions instead? |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0x00000000,0xffffffff,0x00000000,0xffffffff)); |
||||
|
return Packet2df(_mm_add_ps(_mm_and_ps(mask, _mm_mul_ps(a.v, _mm_moveldup_ps(b.v))), |
||||
|
_mm_mul_ps(b.v, _mm_moveldup_ps(a.v)))); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pand <Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_and_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df por <Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_or_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pxor <Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_xor_ps(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pandnot<Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ return Packet2df(_mm_andnot_ps(a.v,b.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pload <Packet2df>(const duals::dual<float>* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet2df(pload<Packet4f>(&numext::real_ref(*from))); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet2df ploadu<Packet2df>(const duals::dual<float>* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet2df(ploadu<Packet4f>(&numext::real_ref(*from))); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pset1<Packet2df>(const duals::dual<float>& from) |
||||
|
{ |
||||
|
Packet2df res; |
||||
|
#if EIGEN_GNUC_AT_MOST(4,2) |
||||
|
// Workaround annoying "may be used uninitialized in this function" warning with gcc 4.2 |
||||
|
res.v = _mm_loadl_pi(_mm_set1_ps(0.0f), reinterpret_cast<const __m64*>(&from)); |
||||
|
#elif EIGEN_GNUC_AT_LEAST(4,6) |
||||
|
// Suppress annoying "may be used uninitialized in this function" warning with gcc >= 4.6 |
||||
|
#pragma GCC diagnostic push |
||||
|
#pragma GCC diagnostic ignored "-Wuninitialized" |
||||
|
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" |
||||
|
res.v = _mm_loadl_pi(res.v, (const __m64*)&from); |
||||
|
#pragma GCC diagnostic pop |
||||
|
#else |
||||
|
res.v = _mm_loadl_pi(res.v, (const __m64*)&from); |
||||
|
#endif |
||||
|
return Packet2df(_mm_movelh_ps(res.v,res.v)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df ploaddup<Packet2df>(const duals::dual<float>* from) |
||||
|
{ return pset1<Packet2df>(*from); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void pstore <duals::dual<float> >(duals::dual<float> * to, const Packet2df& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstore(&numext::real_ref(*to), Packet4f(from.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE void pstoreu<duals::dual<float> >(duals::dual<float> * to, const Packet2df& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu(&numext::real_ref(*to), Packet4f(from.v)); } |
||||
|
|
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline Packet2df pgather<duals::dual<float>, Packet2df>(const duals::dual<float>* from, |
||||
|
Index stride) |
||||
|
{ |
||||
|
return Packet2df(_mm_set_ps(duals::dpart(from[1*stride]), duals::rpart(from[1*stride]), |
||||
|
duals::dpart(from[0*stride]), duals::rpart(from[0*stride]))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_DEVICE_FUNC inline void pscatter<duals::dual<float>, Packet2df>(duals::dual<float>* to, |
||||
|
const Packet2df& from, Index stride) |
||||
|
{ |
||||
|
to[stride*0] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 0)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 1))); |
||||
|
to[stride*1] = duals::dual<float>(_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 2)), |
||||
|
_mm_cvtss_f32(_mm_shuffle_ps(from.v, from.v, 3))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void prefetch<duals::dual<float> >(const duals::dual<float> * addr) |
||||
|
{ _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> pfirst<Packet2df>(const Packet2df& a) |
||||
|
{ |
||||
|
#if EIGEN_GNUC_AT_MOST(4,3) |
||||
|
// Workaround gcc 4.2 ICE - this is not performance wise ideal, but who cares... |
||||
|
// This workaround also fix invalid code generation with gcc 4.3 |
||||
|
EIGEN_ALIGN16 duals::dual<float> res[2]; |
||||
|
_mm_store_ps((float*)res, a.v); |
||||
|
return res[0]; |
||||
|
#else |
||||
|
duals::dual<float> res; |
||||
|
_mm_storel_pi((__m64*)&res, a.v); |
||||
|
return res; |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df preverse(const Packet2df& a) |
||||
|
{ return Packet2df(_mm_castpd_ps(preverse(Packet2d(_mm_castps_pd(a.v))))); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> predux<Packet2df>(const Packet2df& a) |
||||
|
{ |
||||
|
return pfirst(Packet2df(_mm_add_ps(a.v, _mm_movehl_ps(a.v,a.v)))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df preduxp<Packet2df>(const Packet2df* vecs) |
||||
|
{ |
||||
|
return Packet2df(_mm_add_ps(_mm_movelh_ps(vecs[0].v,vecs[1].v), |
||||
|
_mm_movehl_ps(vecs[1].v,vecs[0].v))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<float> predux_mul<Packet2df>(const Packet2df& a) |
||||
|
{ |
||||
|
return pfirst(pmul(a, Packet2df(_mm_movehl_ps(a.v,a.v)))); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet2df> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet2df& first, const Packet2df& second) |
||||
|
{ |
||||
|
if (Offset==1) |
||||
|
{ |
||||
|
first.v = _mm_movehl_ps(first.v, first.v); |
||||
|
first.v = _mm_movelh_ps(first.v, second.v); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#if 0 // TODO |
||||
|
template<> struct dconj_helper<Packet2df, Packet2df, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2df pmadd(const Packet2df& x, const Packet2df& y, const Packet2df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2df pmul(const Packet2df& a, const Packet2df& b) const |
||||
|
{ return internal::pmul(a, pdconj(b)); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet2df, Packet2df, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2df pmadd(const Packet2df& x, const Packet2df& y, const Packet2df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2df pmul(const Packet2df& a, const Packet2df& b) const |
||||
|
{ return internal::pmul(pdconj(a), b); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet2df, Packet2df, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet2df pmadd(const Packet2df& x, const Packet2df& y, const Packet2df& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet2df pmul(const Packet2df& a, const Packet2df& b) const |
||||
|
{ return pdconj(internal::pmul(a, b)); } |
||||
|
}; |
||||
|
EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL(Packet2df,Packet4f) |
||||
|
#endif |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pdiv<Packet2df>(const Packet2df& a, const Packet2df& b) |
||||
|
{ |
||||
|
// TODO optimize it for SSE3 and 4 |
||||
|
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0xffffffff,0x00000000,0xffffffff,0x00000000)); |
||||
|
return Packet2df(_mm_div_ps(_mm_add_ps(_mm_and_ps(mask, a.v), |
||||
|
_mm_andnot_ps(mask, |
||||
|
_mm_sub_ps(_mm_mul_ps(a.v, vec4f_swizzle1(b.v, 0, 0, 2, 2)), |
||||
|
_mm_mul_ps(b.v, vec4f_swizzle1(a.v, 0, 0, 2, 2))))), |
||||
|
_mm_add_ps(_mm_and_ps(mask, b.v), |
||||
|
_mm_andnot_ps(mask, |
||||
|
_mm_mul_ps(vec4f_swizzle1(b.v, 0, 0, 2, 2), |
||||
|
vec4f_swizzle1(b.v, 0, 0, 2, 2)))))); |
||||
|
} |
||||
|
|
||||
|
//---------- double ---------- |
||||
|
struct Packet1dd |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1dd() {} |
||||
|
EIGEN_STRONG_INLINE explicit Packet1dd(const __m128d& a) : v(a) {} |
||||
|
__m128d v; |
||||
|
}; |
||||
|
|
||||
|
// Use the packet_traits defined in AVX/PacketMath.h instead if we're going |
||||
|
// to leverage AVX instructions. |
||||
|
#ifndef EIGEN_VECTORIZE_AVX |
||||
|
template<> struct packet_traits<duals::dual<double> > : default_packet_traits |
||||
|
{ |
||||
|
typedef Packet1dd type; |
||||
|
typedef Packet1dd half; |
||||
|
enum { |
||||
|
Vectorizable = 1, |
||||
|
AlignedOnScalar = 0, |
||||
|
size = 1, |
||||
|
HasHalfPacket = 0, |
||||
|
|
||||
|
HasAdd = 1, |
||||
|
HasSub = 1, |
||||
|
HasMul = 1, |
||||
|
HasDiv = 1, |
||||
|
HasNegate = 1, |
||||
|
HasAbs = 0, |
||||
|
HasAbs2 = 0, |
||||
|
HasMin = 0, |
||||
|
HasMax = 0, |
||||
|
HasSetLinear = 0 |
||||
|
}; |
||||
|
}; |
||||
|
#endif |
||||
|
|
||||
|
template<> struct unpacket_traits<Packet1dd> { |
||||
|
typedef duals::dual<double> type; |
||||
|
enum {size=1, alignment=Aligned16, masked_load_available=false, masked_store_available=false, vectorizable=true}; |
||||
|
typedef Packet1dd half; |
||||
|
}; |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd padd<Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_add_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd psub<Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_sub_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pnegate(const Packet1dd& a) { return Packet1dd(pnegate(Packet2d(a.v))); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pdconj(const Packet1dd& a) |
||||
|
{ |
||||
|
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x80000000,0x0,0x0,0x0)); |
||||
|
return Packet1dd(_mm_xor_pd(a.v,mask)); |
||||
|
} |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pconj(const Packet1dd& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pmul<Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ |
||||
|
//#ifdef EIGEN_VECTORIZE_SSE3 |
||||
|
//TODO |
||||
|
const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0xffffffff,0xffffffff,0x00000000,0x00000000)); |
||||
|
return Packet1dd(_mm_add_pd(_mm_and_pd(mask, |
||||
|
_mm_mul_pd(vec2d_swizzle1(a.v, 0, 1), |
||||
|
vec2d_swizzle1(b.v, 0, 0))), |
||||
|
_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), |
||||
|
vec2d_swizzle1(b.v, 0, 1)))); |
||||
|
//#else |
||||
|
//#endif |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pand <Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_and_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd por <Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_or_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pxor <Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_xor_pd(a.v,b.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pandnot<Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ return Packet1dd(_mm_andnot_pd(a.v,b.v)); } |
||||
|
|
||||
|
// FIXME force unaligned load, this is a temporary fix |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pload <Packet1dd>(const duals::dual<double>* from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_LOAD return Packet1dd(pload<Packet2d>((const double*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd ploadu<Packet1dd>(const duals::dual<double>* from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_LOAD return Packet1dd(ploadu<Packet2d>((const double*)from)); } |
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pset1<Packet1dd>(const duals::dual<double>& from) |
||||
|
{ /* here we really have to use unaligned loads :( */ return ploadu<Packet1dd>(&from); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd ploaddup<Packet1dd>(const duals::dual<double>* from) |
||||
|
{ return pset1<Packet1dd>(*from); } |
||||
|
|
||||
|
// FIXME force unaligned store, this is a temporary fix |
||||
|
template<> EIGEN_STRONG_INLINE void pstore <duals::dual<double> >(duals::dual<double> * to, const Packet1dd& from) |
||||
|
{ EIGEN_DEBUG_ALIGNED_STORE pstore((double*)to, Packet2d(from.v)); } |
||||
|
template<> EIGEN_STRONG_INLINE void pstoreu<duals::dual<double> >(duals::dual<double> * to, const Packet1dd& from) |
||||
|
{ EIGEN_DEBUG_UNALIGNED_STORE pstoreu((double*)to, Packet2d(from.v)); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE void prefetch<duals::dual<double> >(const duals::dual<double> * addr) |
||||
|
{ _mm_prefetch((SsePrefetchPtrType)(addr), _MM_HINT_T0); } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> pfirst<Packet1dd>(const Packet1dd& a) |
||||
|
{ |
||||
|
EIGEN_ALIGN16 double res[2]; |
||||
|
_mm_store_pd(res, a.v); |
||||
|
return duals::dual<double>(res[0],res[1]); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd preverse(const Packet1dd& a) { return a; } |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> predux<Packet1dd>(const Packet1dd& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd preduxp<Packet1dd>(const Packet1dd* vecs) |
||||
|
{ |
||||
|
return vecs[0]; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE duals::dual<double> predux_mul<Packet1dd>(const Packet1dd& a) |
||||
|
{ |
||||
|
return pfirst(a); |
||||
|
} |
||||
|
|
||||
|
template<int Offset> |
||||
|
struct palign_impl<Offset,Packet1dd> |
||||
|
{ |
||||
|
static EIGEN_STRONG_INLINE void run(Packet1dd& /*first*/, const Packet1dd& /*second*/) |
||||
|
{ |
||||
|
// FIXME is it sure we never have to align a Packet1dd? |
||||
|
// Even though a duals::dual<double> has 16 bytes, it is not necessarily aligned on a 16 bytes boundary... |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
#if 0 // TODO |
||||
|
template<> struct dconj_helper<Packet1dd, Packet1dd, false,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmadd(const Packet1dd& x, const Packet1dd& y, const Packet1dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmul(const Packet1dd& a, const Packet1dd& b) const |
||||
|
{ return internal::pmul(a, pdconj(b)); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet1dd, Packet1dd, true,false> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmadd(const Packet1dd& x, const Packet1dd& y, const Packet1dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmul(const Packet1dd& a, const Packet1dd& b) const |
||||
|
{ return internal::pmul(pdconj(a), b); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_helper<Packet1dd, Packet1dd, true,true> |
||||
|
{ |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmadd(const Packet1dd& x, const Packet1dd& y, const Packet1dd& c) const |
||||
|
{ return padd(pmul(x,y),c); } |
||||
|
EIGEN_STRONG_INLINE Packet1dd pmul(const Packet1dd& a, const Packet1dd& b) const |
||||
|
{ return pdconj(internal::pmul(a, b)); } |
||||
|
}; |
||||
|
EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL(Packet1dd,Packet2d) |
||||
|
#endif |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pdiv<Packet1dd>(const Packet1dd& a, const Packet1dd& b) |
||||
|
{ |
||||
|
// TODO optimize it for SSE3 and 4 |
||||
|
//const __m128d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0)); |
||||
|
//return Packet1cd(_mm_add_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), b.v), |
||||
|
// _mm_xor_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 1, 1), |
||||
|
// vec2d_swizzle1(b.v, 1, 0)), mask))); |
||||
|
// TODO optimize it for SSE3 and 4 |
||||
|
const __m128d mask = _mm_castsi128_pd(_mm_setr_epi32(0xffffffff,0xffffffff,0x00000000,0x00000000)); |
||||
|
return Packet1dd(_mm_div_pd(_mm_add_pd(_mm_and_pd(mask, a.v), |
||||
|
_mm_andnot_pd(mask, |
||||
|
_mm_sub_pd(_mm_mul_pd(vec2d_swizzle1(a.v, 0, 1), |
||||
|
vec2d_swizzle1(b.v, 0, 0)), |
||||
|
_mm_mul_pd(vec2d_swizzle1(a.v, 0, 0), |
||||
|
vec2d_swizzle1(b.v, 0, 1))))), |
||||
|
_mm_add_pd(_mm_and_pd(mask, b.v), |
||||
|
_mm_andnot_pd(mask, |
||||
|
_mm_mul_pd(vec2d_swizzle1(b.v, 0, 0), |
||||
|
vec2d_swizzle1(b.v, 0, 0)))))); |
||||
|
} |
||||
|
|
||||
|
EIGEN_DEVICE_FUNC inline void |
||||
|
ptranspose(PacketBlock<Packet2df,2>& kernel) { |
||||
|
__m128d w1 = _mm_castps_pd(kernel.packet[0].v); |
||||
|
__m128d w2 = _mm_castps_pd(kernel.packet[1].v); |
||||
|
|
||||
|
__m128 tmp = _mm_castpd_ps(_mm_unpackhi_pd(w1, w2)); |
||||
|
kernel.packet[0].v = _mm_castpd_ps(_mm_unpacklo_pd(w1, w2)); |
||||
|
kernel.packet[1].v = tmp; |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pblend(const Selector<2>& ifPacket, |
||||
|
const Packet2df& thenPacket, |
||||
|
const Packet2df& elsePacket) |
||||
|
{ |
||||
|
__m128d result = pblend<Packet2d>(ifPacket, _mm_castps_pd(thenPacket.v), _mm_castps_pd(elsePacket.v)); |
||||
|
return Packet2df(_mm_castpd_ps(result)); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pinsertfirst(const Packet2df& a, duals::dual<float> b) |
||||
|
{ |
||||
|
return Packet2df(_mm_loadl_pi(a.v, reinterpret_cast<const __m64*>(&b))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pinsertfirst(const Packet1dd&, duals::dual<double> b) |
||||
|
{ |
||||
|
return pset1<Packet1dd>(b); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet2df pinsertlast(const Packet2df& a, duals::dual<float> b) |
||||
|
{ |
||||
|
return Packet2df(_mm_loadh_pi(a.v, reinterpret_cast<const __m64*>(&b))); |
||||
|
} |
||||
|
|
||||
|
template<> EIGEN_STRONG_INLINE Packet1dd pinsertlast(const Packet1dd&, duals::dual<double> b) |
||||
|
{ |
||||
|
return pset1<Packet1dd>(b); |
||||
|
} |
||||
|
|
||||
|
} // end namespace internal |
||||
|
|
||||
|
} // end namespace Eigen |
||||
|
|
||||
|
#endif // EIGEN_COMPLEX_SSE_H |
||||
1384
src/include/cppduals/duals/dual
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,774 @@ |
|||||
|
//===-- duals/dual_eigen - wrapp dual number type for Eigen -----*- C++ -*-===// |
||||
|
// |
||||
|
// Part of the cppduals project. |
||||
|
// https://gitlab.com/tesch1/cppduals |
||||
|
// |
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for |
||||
|
// license information. |
||||
|
// |
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
// |
||||
|
// Some code fragments are adapted from Eigen's Complex.h files, which |
||||
|
// carry the following license: |
||||
|
// |
||||
|
// Copyright (C) 2014 Benoit Steiner (benoit.steiner.goog@gmail.com) |
||||
|
// |
||||
|
// This Source Code Form is subject to the terms of the Mozilla |
||||
|
// Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
#ifndef CPPDUALS_DUAL_EIGEN |
||||
|
#define CPPDUALS_DUAL_EIGEN |
||||
|
|
||||
|
#include "dual" |
||||
|
|
||||
|
#ifndef PARSED_BY_DOXYGEN |
||||
|
#include <complex> |
||||
|
#include <Eigen/Core> |
||||
|
#endif |
||||
|
|
||||
|
#if !EIGEN_VERSION_AT_LEAST(3, 3, 0) |
||||
|
#error "Eigen too old for cppduals. Upgrade." |
||||
|
#endif |
||||
|
|
||||
|
/** \file dual_eigen |
||||
|
\brief Nestable, vectorizable Dual numbers for Eigen |
||||
|
|
||||
|
Include this file to enable use of the `duals::dual<>` class as a |
||||
|
scalar type in Eigen. Some optimizations are performed using |
||||
|
Eigen's vectorization facilities, which is particularly noticeable |
||||
|
for multiplication and division. In certain cases the |
||||
|
vectorization can be worse than the compiler's code, thus it can |
||||
|
be disabled by `#define CPPDUALS_DONT_VECTORIZE`. |
||||
|
|
||||
|
There is some also vectorization for dual-ized complex's |
||||
|
(`std::complex<duals::dual<T>>`), which can be disabled by |
||||
|
`#define CPPDUALS_DONT_VECTORIZE_CDUAL`. |
||||
|
|
||||
|
The same type promotion that exists for `duals::dual<T>`: an |
||||
|
operation between a 'scalar' T and dual<T> is promoted to dual<T>. |
||||
|
This is enabled for Eigen matrices by default: multiplying an |
||||
|
`Eigen::Matrix<float>` by `1_ef` results in an expression with a |
||||
|
basic POD type of `Eigen::Matrix<duals::dual<float>,..>`. This |
||||
|
type of type promotion can be disabled (ie for correctness |
||||
|
checking or to speed compilation) by #define |
||||
|
`CPPDUALS_NO_EIGEN_PROMOTION`. |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
namespace duals { |
||||
|
|
||||
|
/** template unary functor to get the real part of a matrix |
||||
|
* use it like this: m2 = m1.unaryExpr(CwiseRpartOp<double>()); |
||||
|
* or just call m2 = rpart(m1); |
||||
|
*/ |
||||
|
template<typename ScalarSrc> |
||||
|
struct CwiseRpartOp { |
||||
|
typedef decltype(rpart(ScalarSrc())) ScalarDst; |
||||
|
typedef ScalarDst result_type; |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
EIGEN_STRONG_INLINE ScalarDst operator()(const ScalarSrc & x) const { return rpart(x); } |
||||
|
}; |
||||
|
|
||||
|
/** template unary functor to get the dual part of a matrix |
||||
|
* use it like this: m2 = m1.unaryExpr(CwiseDpartOp<double>()); |
||||
|
* or just call m2 = dpart(m1); |
||||
|
*/ |
||||
|
template<typename ScalarSrc> |
||||
|
struct CwiseDpartOp { |
||||
|
typedef decltype(dpart(ScalarSrc())) ScalarDst; |
||||
|
typedef ScalarDst result_type; |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
EIGEN_STRONG_INLINE ScalarDst operator()(const ScalarSrc & x) const { return dpart(x); } |
||||
|
}; |
||||
|
|
||||
|
/** template unary functor to dual-conjugate a matrix of duals |
||||
|
* use it like this: m2 = m1.unaryExpr(CwiseDconjOp<double>()); |
||||
|
* or just call m2 = dconj(m1); |
||||
|
*/ |
||||
|
template<typename Scalar> |
||||
|
struct CwiseDconjOp { |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
EIGEN_STRONG_INLINE Scalar operator()(const Scalar & x) const { return dconj(x); } |
||||
|
}; |
||||
|
|
||||
|
/// Extract the "real part" of a dual-valued matrix. |
||||
|
#ifdef PARSED_BY_DOXYGEN |
||||
|
template <typename XprType> const RealType |
||||
|
#else |
||||
|
template <typename XprType> |
||||
|
const Eigen::CwiseUnaryOp<CwiseRpartOp<typename XprType::Scalar>, const XprType > |
||||
|
#endif |
||||
|
rpart(const Eigen::EigenBase<XprType> & x) |
||||
|
{ |
||||
|
return x.derived().unaryExpr(CwiseRpartOp<typename XprType::Scalar>()); |
||||
|
} |
||||
|
|
||||
|
/// Extract the "dual part" of a dual-valued matrix. |
||||
|
#ifdef PARSED_BY_DOXYGEN |
||||
|
template <typename XprType> const RealType |
||||
|
#else |
||||
|
template <typename XprType> |
||||
|
const Eigen::CwiseUnaryOp<CwiseDpartOp<typename XprType::Scalar>, const XprType > |
||||
|
#endif |
||||
|
dpart(const Eigen::EigenBase<XprType> & x) |
||||
|
{ |
||||
|
return x.derived().unaryExpr(CwiseDpartOp<typename XprType::Scalar>()); |
||||
|
} |
||||
|
|
||||
|
/// Dual-conjugate a dual-valued matrix. |
||||
|
#ifdef PARSED_BY_DOXYGEN |
||||
|
template <typename XprType> const XprType |
||||
|
#else |
||||
|
template <typename XprType> |
||||
|
const Eigen::CwiseUnaryOp<CwiseDconjOp<typename XprType::Scalar>, const XprType > |
||||
|
#endif |
||||
|
dconj(const Eigen::EigenBase<XprType> & x) |
||||
|
{ |
||||
|
return x.derived().unaryExpr(CwiseDconjOp<typename XprType::Scalar>()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} // namespace duals |
||||
|
|
||||
|
namespace Eigen { |
||||
|
|
||||
|
template<typename T> |
||||
|
struct NumTraits<duals::dual<T> > : GenericNumTraits<T> |
||||
|
{ |
||||
|
typedef typename NumTraits<T>::Real ReallyReal; |
||||
|
typedef duals::dual<T> Real; |
||||
|
typedef duals::dual<T> Literal; |
||||
|
typedef duals::dual<T> Nested; |
||||
|
|
||||
|
enum { |
||||
|
IsInteger = NumTraits<T>::IsInteger, |
||||
|
IsSigned = NumTraits<T>::IsSigned, |
||||
|
IsComplex = 0, |
||||
|
RequireInitialization = NumTraits<T>::RequireInitialization, |
||||
|
ReadCost = 2 * NumTraits<T>::ReadCost, |
||||
|
AddCost = 2 * NumTraits<T>::AddCost, |
||||
|
MulCost = 3 * NumTraits<T>::MulCost + 1 * NumTraits<T>::AddCost |
||||
|
}; |
||||
|
|
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline Real epsilon() { return Real(NumTraits<T>::epsilon()); } |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline ReallyReal dummy_precision() { return NumTraits<T>::dummy_precision(); } |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline ReallyReal highest() { return NumTraits<T>::highest(); } |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline ReallyReal lowest() { return NumTraits<T>::lowest(); } |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline ReallyReal digits10() { return NumTraits<T>::digits10(); } |
||||
|
}; |
||||
|
|
||||
|
#if !defined(CPPDUALS_NO_EIGEN_PROMOTION) |
||||
|
template<typename T, typename BinaryOp> |
||||
|
struct ScalarBinaryOpTraits<duals::dual<T>,duals::dual<T>,BinaryOp> |
||||
|
: public duals::can_promote<duals::dual<T>,duals::dual<T>>::wrap {}; |
||||
|
|
||||
|
template<typename T, typename BinaryOp> |
||||
|
struct ScalarBinaryOpTraits<duals::dual<T>,T,BinaryOp> |
||||
|
: public duals::can_promote<duals::dual<T>,T>::wrap {}; |
||||
|
template<typename T, typename BinaryOp> |
||||
|
struct ScalarBinaryOpTraits<T,duals::dual<T>,BinaryOp> |
||||
|
: public duals::can_promote<duals::dual<T>,T>::wrap {}; |
||||
|
|
||||
|
#if 0 // until Eigen doesnt make assumptions about complex return types :P |
||||
|
template<typename T, typename BinaryOp> |
||||
|
struct ScalarBinaryOpTraits<std::complex<T>,duals::dual<T>,BinaryOp> |
||||
|
: public duals::can_promote<std::complex<T>,duals::dual<T>>::wrap {}; |
||||
|
template<typename T, typename BinaryOp> |
||||
|
struct ScalarBinaryOpTraits<duals::dual<T>,std::complex<T>,BinaryOp> |
||||
|
: public duals::can_promote<std::complex<T>,duals::dual<T>>::wrap {}; |
||||
|
#endif |
||||
|
|
||||
|
#ifndef PARSED_BY_DOXYGEN |
||||
|
|
||||
|
// Special cases for nested complex<dual<>> and reals |
||||
|
#define CPPDUALS_CD_SBOTS_REALS(U) \ |
||||
|
template<typename T, typename BinaryOp> \ |
||||
|
struct ScalarBinaryOpTraits<std::complex<duals::dual<T>>,U,BinaryOp> \ |
||||
|
: public duals::can_promote<std::complex<duals::dual<T>>,U>::wrap {}; \ |
||||
|
template<typename T, typename BinaryOp> \ |
||||
|
struct ScalarBinaryOpTraits<U,std::complex<duals::dual<T>>,BinaryOp> \ |
||||
|
: public duals::can_promote<std::complex<duals::dual<T>>,U>::wrap {} |
||||
|
CPPDUALS_CD_SBOTS_REALS(int); |
||||
|
CPPDUALS_CD_SBOTS_REALS(float); |
||||
|
CPPDUALS_CD_SBOTS_REALS(double); |
||||
|
CPPDUALS_CD_SBOTS_REALS(std::complex<T>); |
||||
|
|
||||
|
#endif // PARSED_BY_DOXYGEN |
||||
|
|
||||
|
#endif // CPPDUALS_NO_EIGEN_PROMOTION |
||||
|
|
||||
|
#ifndef PARSED_BY_DOXYGEN |
||||
|
|
||||
|
namespace numext { |
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dconj; |
||||
|
} |
||||
|
|
||||
|
namespace internal { |
||||
|
|
||||
|
template<typename T> |
||||
|
struct real_impl<duals::dual<T> > |
||||
|
{ |
||||
|
typedef T RealScalar; |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline T run(const duals::dual<T>& x) |
||||
|
{ |
||||
|
return x.rpart(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<typename Scalar> |
||||
|
struct real_ref_impl<duals::dual<Scalar>> |
||||
|
{ |
||||
|
typedef typename NumTraits<Scalar>::Real RealScalar; |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline RealScalar & run(duals::dual<Scalar> & x) |
||||
|
{ |
||||
|
return reinterpret_cast<RealScalar*>(&x)[0]; |
||||
|
} |
||||
|
EIGEN_DEVICE_FUNC |
||||
|
static inline const RealScalar & run(const duals::dual<Scalar> & x) |
||||
|
{ |
||||
|
return reinterpret_cast<const RealScalar *>(&x)[0]; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
template<typename Scalar> |
||||
|
struct real_ref_retval<duals::dual<Scalar>> |
||||
|
{ |
||||
|
typedef typename NumTraits<Scalar>::Real & type; |
||||
|
}; |
||||
|
|
||||
|
template<typename T> struct scalar_random_op<duals::dual<T>> |
||||
|
{ |
||||
|
EIGEN_EMPTY_STRUCT_CTOR(scalar_random_op) |
||||
|
inline const duals::dual<T> operator() () const { return duals::random<duals::dual<T>>(); } |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// // stuff for gebp_* |
||||
|
|
||||
|
template<typename Packet> EIGEN_DEVICE_FUNC inline Packet |
||||
|
pdconj(const Packet& a) { return numext::dconj(a); } |
||||
|
|
||||
|
template<bool Conjugate> struct dconj_if; |
||||
|
template<> struct dconj_if<true> { |
||||
|
template<typename T> inline T operator()(const T& x) const { return numext::dconj(x); } |
||||
|
template<typename T> inline T pdconj(const T& x) const { return internal::pdconj(x); } |
||||
|
}; |
||||
|
|
||||
|
template<> struct dconj_if<false> { |
||||
|
template<typename T> inline const T& operator()(const T& x) const { return x; } |
||||
|
template<typename T> inline const T& pdconj(const T& x) const { return x; } |
||||
|
}; |
||||
|
|
||||
|
// Generic implementation for custom dual types. |
||||
|
template<typename LhsScalar, typename RhsScalar, bool ConjLhs, bool ConjRhs> |
||||
|
struct dconj_helper |
||||
|
{ |
||||
|
typedef typename ScalarBinaryOpTraits<LhsScalar,RhsScalar>::ReturnType Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const LhsScalar& x, const RhsScalar& y, const Scalar& c) const |
||||
|
{ return padd(c, pmul(x,y)); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const LhsScalar& x, const RhsScalar& y) const |
||||
|
{ return dconj_if<ConjLhs>()(x) * dconj_if<ConjRhs>()(y); } |
||||
|
}; |
||||
|
|
||||
|
template<typename Scalar> struct dconj_helper<Scalar,Scalar,false,false> |
||||
|
{ |
||||
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const |
||||
|
{ return internal::pmadd(x,y,c); } |
||||
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const |
||||
|
{ return internal::pmul(x,y); } |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar> struct dconj_helper<duals::dual<RealScalar>, duals::dual<RealScalar>, false,true> |
||||
|
{ |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const |
||||
|
{ return c + pmul(x,y); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const |
||||
|
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), |
||||
|
numext::imag(x)*numext::real(y) - numext::real(x)*numext::imag(y)); } |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar> struct dconj_helper<duals::dual<RealScalar>, duals::dual<RealScalar>, true,false> |
||||
|
{ |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const |
||||
|
{ return c + pmul(x,y); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const |
||||
|
{ return Scalar(numext::real(x)*numext::real(y) + numext::imag(x)*numext::imag(y), |
||||
|
numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); } |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar> struct dconj_helper<duals::dual<RealScalar>, duals::dual<RealScalar>, true,true> |
||||
|
{ |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const Scalar& y, const Scalar& c) const |
||||
|
{ return c + pmul(x,y); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const Scalar& y) const |
||||
|
{ return Scalar(numext::real(x)*numext::real(y) - numext::imag(x)*numext::imag(y), |
||||
|
-numext::real(x)*numext::imag(y) - numext::imag(x)*numext::real(y)); } |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar,bool Conj> struct dconj_helper<duals::dual<RealScalar>, RealScalar, Conj,false> |
||||
|
{ |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const Scalar& x, const RealScalar& y, const Scalar& c) const |
||||
|
{ return padd(c, pmul(x,y)); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const Scalar& x, const RealScalar& y) const |
||||
|
{ return dconj_if<Conj>()(x)*y; } |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar,bool Conj> struct dconj_helper<RealScalar, duals::dual<RealScalar>, false,Conj> |
||||
|
{ |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
EIGEN_STRONG_INLINE Scalar pmadd(const RealScalar& x, const Scalar& y, const Scalar& c) const |
||||
|
{ return padd(c, pmul(x,y)); } |
||||
|
EIGEN_STRONG_INLINE Scalar pmul(const RealScalar& x, const Scalar& y) const |
||||
|
{ return x*dconj_if<Conj>()(y); } |
||||
|
}; |
||||
|
|
||||
|
} // namespace internal |
||||
|
|
||||
|
#endif // PARSED_BY_DOXYGEN |
||||
|
|
||||
|
} // namespace Eigen |
||||
|
|
||||
|
#if !defined(CPPDUALS_DONT_VECTORIZE) |
||||
|
#ifndef PARSED_BY_DOXYGEN |
||||
|
|
||||
|
// first thing Eigen does: stop the compiler from committing suicide |
||||
|
#include "Eigen/src/Core/util/DisableStupidWarnings.h" |
||||
|
|
||||
|
#define EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL(PACKET_DUAL, PACKET_REAL) \ |
||||
|
template<> struct dconj_helper<PACKET_REAL, PACKET_DUAL, false,false> { \ |
||||
|
EIGEN_STRONG_INLINE PACKET_DUAL pmadd(const PACKET_REAL& x, const PACKET_DUAL& y, const PACKET_DUAL& c) const \ |
||||
|
{ return padd(c, pmul(x,y)); } \ |
||||
|
EIGEN_STRONG_INLINE PACKET_DUAL pmul(const PACKET_REAL& x, const PACKET_DUAL& y) const \ |
||||
|
{ return PACKET_DUAL(Eigen::internal::pmul<PACKET_REAL>(x, PACKET_REAL(y.v))); } \ |
||||
|
}; \ |
||||
|
\ |
||||
|
template<> struct dconj_helper<PACKET_DUAL, PACKET_REAL, false,false> { \ |
||||
|
EIGEN_STRONG_INLINE PACKET_DUAL pmadd(const PACKET_DUAL& x, const PACKET_REAL& y, const PACKET_DUAL& c) const \ |
||||
|
{ return padd(c, pmul(x,y)); } \ |
||||
|
EIGEN_STRONG_INLINE PACKET_DUAL pmul(const PACKET_DUAL& x, const PACKET_REAL& y) const \ |
||||
|
{ return PACKET_DUAL(Eigen::internal::pmul<PACKET_REAL>(PACKET_REAL(x.v), y)); } \ |
||||
|
}; |
||||
|
|
||||
|
#if defined EIGEN_VECTORIZE_AVX512 |
||||
|
#include "duals/arch/SSE/Dual.h" |
||||
|
#include "duals/arch/AVX/Dual.h" |
||||
|
#include "duals/arch/SSE/ComplexDual.h" |
||||
|
#include "duals/arch/AVX/ComplexDual.h" |
||||
|
#elif defined EIGEN_VECTORIZE_AVX |
||||
|
#include "duals/arch/SSE/Dual.h" |
||||
|
#include "duals/arch/AVX/Dual.h" |
||||
|
#include "duals/arch/SSE/ComplexDual.h" |
||||
|
#include "duals/arch/AVX/ComplexDual.h" |
||||
|
#elif defined EIGEN_VECTORIZE_SSE |
||||
|
#include "duals/arch/SSE/Dual.h" |
||||
|
#include "duals/arch/SSE/ComplexDual.h" |
||||
|
#elif defined(EIGEN_VECTORIZE_ALTIVEC) || defined(EIGEN_VECTORIZE_VSX) |
||||
|
// #include "duals/arch/AltiVec/Dual.h" // TODO |
||||
|
#elif defined EIGEN_VECTORIZE_NEON |
||||
|
//#include "duals/arch/NEON/Dual.h" // TODO |
||||
|
#elif defined EIGEN_VECTORIZE_ZVECTOR |
||||
|
// #include "duals/arch/ZVector/Dual.h" // TODO |
||||
|
#endif |
||||
|
|
||||
|
#undef EIGEN_MAKE_DCONJ_HELPER_DUAL_REAL |
||||
|
|
||||
|
// reallow compiler seppuku |
||||
|
#include "Eigen/src/Core/util/ReenableStupidWarnings.h" |
||||
|
|
||||
|
#endif // PARSED_BY_DOXYGEN |
||||
|
|
||||
|
//////// gepb for duals::dual |
||||
|
#if 0 // TODO |
||||
|
|
||||
|
namespace Eigen { namespace internal { |
||||
|
|
||||
|
template<typename RealScalar, bool _ConjLhs> |
||||
|
class gebp_traits<duals::dual<RealScalar>, RealScalar, _ConjLhs, false> |
||||
|
{ |
||||
|
public: |
||||
|
typedef duals::dual<RealScalar> LhsScalar; |
||||
|
typedef RealScalar RhsScalar; |
||||
|
typedef typename ScalarBinaryOpTraits<LhsScalar, RhsScalar>::ReturnType ResScalar; |
||||
|
|
||||
|
enum { |
||||
|
ConjLhs = _ConjLhs, |
||||
|
ConjRhs = false, |
||||
|
Vectorizable = packet_traits<LhsScalar>::Vectorizable && packet_traits<RhsScalar>::Vectorizable, |
||||
|
LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1, |
||||
|
RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1, |
||||
|
ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1, |
||||
|
|
||||
|
NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS, |
||||
|
nr = 4, |
||||
|
#if defined(EIGEN_HAS_SINGLE_INSTRUCTION_MADD) && !defined(EIGEN_VECTORIZE_ALTIVEC) && !defined(EIGEN_VECTORIZE_VSX) |
||||
|
// we assume 16 registers |
||||
|
mr = 3*LhsPacketSize, |
||||
|
#else |
||||
|
mr = (EIGEN_PLAIN_ENUM_MIN(16,NumberOfRegisters)/2/nr)*LhsPacketSize, |
||||
|
#endif |
||||
|
|
||||
|
LhsProgress = LhsPacketSize, |
||||
|
RhsProgress = 1 |
||||
|
}; |
||||
|
|
||||
|
typedef typename packet_traits<LhsScalar>::type _LhsPacket; |
||||
|
typedef typename packet_traits<RhsScalar>::type _RhsPacket; |
||||
|
typedef typename packet_traits<ResScalar>::type _ResPacket; |
||||
|
|
||||
|
typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket; |
||||
|
typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket; |
||||
|
typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket; |
||||
|
|
||||
|
typedef ResPacket AccPacket; |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void initAcc(AccPacket& p) |
||||
|
{ |
||||
|
p = pset1<ResPacket>(ResScalar(0)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, RhsPacket& dest) const |
||||
|
{ |
||||
|
dest = pset1<RhsPacket>(*b); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, RhsPacket& dest) const |
||||
|
{ |
||||
|
dest = pset1<RhsPacket>(*b); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = pload<LhsPacket>(a); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadLhsUnaligned(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = ploadu<LhsPacket>(a); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, RhsPacket& b0, RhsPacket& b1, RhsPacket& b2, RhsPacket& b3) |
||||
|
{ |
||||
|
pbroadcast4(b, b0, b1, b2, b3); |
||||
|
} |
||||
|
|
||||
|
// EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, RhsPacket& b0, RhsPacket& b1) |
||||
|
// { |
||||
|
// pbroadcast2(b, b0, b1); |
||||
|
// } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp) const |
||||
|
{ |
||||
|
madd_impl(a, b, c, tmp, typename conditional<Vectorizable,true_type,false_type>::type()); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd_impl(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp, const true_type&) const |
||||
|
{ |
||||
|
//std::cerr << CYELLOW "%" << CRESET; |
||||
|
//duals::dual<RealScalar>, RealScalar |
||||
|
// accpacket=lhspacket |
||||
|
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD |
||||
|
EIGEN_UNUSED_VARIABLE(tmp); |
||||
|
c.v = pmadd(a.v,b,c.v); |
||||
|
#else |
||||
|
tmp = b; tmp = pmul(RhsPacket(a.v),tmp); c = AccPacket(padd(RhsPacket(c.v),tmp)); |
||||
|
#endif |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd_impl(const LhsScalar& a, const RhsScalar& b, ResScalar& c, RhsScalar& /*tmp*/, const false_type&) const |
||||
|
{ |
||||
|
c += a * b; |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void acc(const AccPacket& c, const ResPacket& alpha, ResPacket& r) const |
||||
|
{ |
||||
|
r = cj.pmadd(c,alpha,r); |
||||
|
} |
||||
|
|
||||
|
protected: |
||||
|
dconj_helper<ResPacket,ResPacket,ConjLhs,false> cj; |
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar, bool _ConjLhs, bool _ConjRhs> |
||||
|
class gebp_traits<duals::dual<RealScalar>, duals::dual<RealScalar>, _ConjLhs, _ConjRhs > |
||||
|
{ |
||||
|
public: |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
typedef duals::dual<RealScalar> LhsScalar; |
||||
|
typedef duals::dual<RealScalar> RhsScalar; |
||||
|
typedef duals::dual<RealScalar> ResScalar; |
||||
|
|
||||
|
enum { |
||||
|
ConjLhs = _ConjLhs, |
||||
|
ConjRhs = _ConjRhs, |
||||
|
Vectorizable = packet_traits<RealScalar>::Vectorizable |
||||
|
&& packet_traits<Scalar>::Vectorizable, |
||||
|
RealPacketSize = Vectorizable ? packet_traits<RealScalar>::size : 1, |
||||
|
ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1, |
||||
|
LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1, |
||||
|
RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1, |
||||
|
|
||||
|
// FIXME: should depend on NumberOfRegisters |
||||
|
nr = 4, |
||||
|
mr = ResPacketSize, |
||||
|
|
||||
|
LhsProgress = ResPacketSize, |
||||
|
RhsProgress = 1 |
||||
|
}; |
||||
|
|
||||
|
typedef typename packet_traits<RealScalar>::type RealPacket; |
||||
|
typedef typename packet_traits<Scalar>::type ScalarPacket; |
||||
|
typedef DoublePacket<RealPacket> DoublePacketType; |
||||
|
|
||||
|
typedef typename conditional<Vectorizable,RealPacket, Scalar>::type LhsPacket; |
||||
|
typedef typename conditional<Vectorizable,DoublePacketType,Scalar>::type RhsPacket; |
||||
|
typedef typename conditional<Vectorizable,ScalarPacket,Scalar>::type ResPacket; |
||||
|
typedef typename conditional<Vectorizable,DoublePacketType,Scalar>::type AccPacket; |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void initAcc(Scalar& p) { p = Scalar(0); } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void initAcc(DoublePacketType& p) |
||||
|
{ |
||||
|
p.first = pset1<RealPacket>(RealScalar(0)); |
||||
|
p.second = pset1<RealPacket>(RealScalar(0)); |
||||
|
} |
||||
|
|
||||
|
// Scalar path |
||||
|
EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, ResPacket& dest) const |
||||
|
{ |
||||
|
dest = pset1<ResPacket>(*b); |
||||
|
} |
||||
|
|
||||
|
// Vectorized path |
||||
|
EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, DoublePacketType& dest) const |
||||
|
{ |
||||
|
dest.first = pset1<RealPacket>(rpart(*b)); |
||||
|
dest.second = pset1<RealPacket>(dpart(*b)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, ResPacket& dest) const |
||||
|
{ |
||||
|
loadRhs(b,dest); |
||||
|
} |
||||
|
EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, DoublePacketType& dest) const |
||||
|
{ |
||||
|
eigen_internal_assert(unpacket_traits<ScalarPacket>::size<=4); |
||||
|
loadRhs(b,dest); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, RhsPacket& b0, RhsPacket& b1, RhsPacket& b2, RhsPacket& b3) |
||||
|
{ |
||||
|
// FIXME not sure that's the best way to implement it! |
||||
|
loadRhs(b+0, b0); |
||||
|
loadRhs(b+1, b1); |
||||
|
loadRhs(b+2, b2); |
||||
|
loadRhs(b+3, b3); |
||||
|
} |
||||
|
|
||||
|
// Vectorized path |
||||
|
EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, DoublePacketType& b0, DoublePacketType& b1) |
||||
|
{ |
||||
|
// FIXME not sure that's the best way to implement it! |
||||
|
loadRhs(b+0, b0); |
||||
|
loadRhs(b+1, b1); |
||||
|
} |
||||
|
|
||||
|
// Scalar path |
||||
|
EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, RhsScalar& b0, RhsScalar& b1) |
||||
|
{ |
||||
|
// FIXME not sure that's the best way to implement it! |
||||
|
loadRhs(b+0, b0); |
||||
|
loadRhs(b+1, b1); |
||||
|
} |
||||
|
|
||||
|
// nothing special here |
||||
|
EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = pload<LhsPacket>((const typename unpacket_traits<LhsPacket>::type*)(a)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadLhsUnaligned(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = ploadu<LhsPacket>((const typename unpacket_traits<LhsPacket>::type*)(a)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, DoublePacketType& c, RhsPacket& /*tmp*/) const |
||||
|
{ |
||||
|
c.first = padd(pmul(a,b.first), c.first); |
||||
|
c.second = padd(pmul(a,b.second),c.second); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, ResPacket& c, RhsPacket& /*tmp*/) const |
||||
|
{ |
||||
|
c = cj.pmadd(a,b,c); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void acc(const Scalar& c, const Scalar& alpha, Scalar& r) const { r += alpha * c; } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void acc(const DoublePacketType& c, const ResPacket& alpha, ResPacket& r) const |
||||
|
{ |
||||
|
// assemble c |
||||
|
ResPacket tmp; |
||||
|
if((!ConjLhs)&&(!ConjRhs)) |
||||
|
{ |
||||
|
tmp = pcplxflip(pconj(ResPacket(c.second))); |
||||
|
tmp = padd(ResPacket(c.first),tmp); |
||||
|
} |
||||
|
else if((!ConjLhs)&&(ConjRhs)) |
||||
|
{ |
||||
|
tmp = pconj(pcplxflip(ResPacket(c.second))); |
||||
|
tmp = padd(ResPacket(c.first),tmp); |
||||
|
} |
||||
|
else if((ConjLhs)&&(!ConjRhs)) |
||||
|
{ |
||||
|
tmp = pcplxflip(ResPacket(c.second)); |
||||
|
tmp = padd(pconj(ResPacket(c.first)),tmp); |
||||
|
} |
||||
|
else if((ConjLhs)&&(ConjRhs)) |
||||
|
{ |
||||
|
tmp = pcplxflip(ResPacket(c.second)); |
||||
|
tmp = psub(pconj(ResPacket(c.first)),tmp); |
||||
|
} |
||||
|
|
||||
|
r = pmadd(tmp,alpha,r); |
||||
|
} |
||||
|
protected: |
||||
|
dconj_helper<LhsScalar,RhsScalar,ConjLhs,ConjRhs> cj; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
template<typename RealScalar, bool _ConjRhs> |
||||
|
class gebp_traits<RealScalar, duals::dual<RealScalar>, false, _ConjRhs > |
||||
|
{ |
||||
|
public: |
||||
|
typedef duals::dual<RealScalar> Scalar; |
||||
|
typedef RealScalar LhsScalar; |
||||
|
typedef Scalar RhsScalar; |
||||
|
typedef Scalar ResScalar; |
||||
|
|
||||
|
enum { |
||||
|
ConjLhs = false, |
||||
|
ConjRhs = _ConjRhs, |
||||
|
Vectorizable = packet_traits<RealScalar>::Vectorizable |
||||
|
&& packet_traits<Scalar>::Vectorizable, |
||||
|
LhsPacketSize = Vectorizable ? packet_traits<LhsScalar>::size : 1, |
||||
|
RhsPacketSize = Vectorizable ? packet_traits<RhsScalar>::size : 1, |
||||
|
ResPacketSize = Vectorizable ? packet_traits<ResScalar>::size : 1, |
||||
|
|
||||
|
NumberOfRegisters = EIGEN_ARCH_DEFAULT_NUMBER_OF_REGISTERS, |
||||
|
// FIXME: should depend on NumberOfRegisters |
||||
|
nr = 4, |
||||
|
mr = (EIGEN_PLAIN_ENUM_MIN(16,NumberOfRegisters)/2/nr)*ResPacketSize, |
||||
|
|
||||
|
LhsProgress = ResPacketSize, |
||||
|
RhsProgress = 1 |
||||
|
}; |
||||
|
|
||||
|
typedef typename packet_traits<LhsScalar>::type _LhsPacket; |
||||
|
typedef typename packet_traits<RhsScalar>::type _RhsPacket; |
||||
|
typedef typename packet_traits<ResScalar>::type _ResPacket; |
||||
|
|
||||
|
typedef typename conditional<Vectorizable,_LhsPacket,LhsScalar>::type LhsPacket; |
||||
|
typedef typename conditional<Vectorizable,_RhsPacket,RhsScalar>::type RhsPacket; |
||||
|
typedef typename conditional<Vectorizable,_ResPacket,ResScalar>::type ResPacket; |
||||
|
|
||||
|
typedef ResPacket AccPacket; |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void initAcc(AccPacket& p) |
||||
|
{ |
||||
|
p = pset1<ResPacket>(ResScalar(0)); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadRhs(const RhsScalar* b, RhsPacket& dest) const |
||||
|
{ |
||||
|
dest = pset1<RhsPacket>(*b); |
||||
|
} |
||||
|
|
||||
|
void broadcastRhs(const RhsScalar* b, RhsPacket& b0, RhsPacket& b1, RhsPacket& b2, RhsPacket& b3) |
||||
|
{ |
||||
|
pbroadcast4(b, b0, b1, b2, b3); |
||||
|
} |
||||
|
|
||||
|
// EIGEN_STRONG_INLINE void broadcastRhs(const RhsScalar* b, RhsPacket& b0, RhsPacket& b1) |
||||
|
// { |
||||
|
// // FIXME not sure that's the best way to implement it! |
||||
|
// b0 = pload1<RhsPacket>(b+0); |
||||
|
// b1 = pload1<RhsPacket>(b+1); |
||||
|
// } |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadLhs(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = ploaddup<LhsPacket>(a); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadRhsQuad(const RhsScalar* b, RhsPacket& dest) const |
||||
|
{ |
||||
|
eigen_internal_assert(unpacket_traits<RhsPacket>::size<=4); |
||||
|
loadRhs(b,dest); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void loadLhsUnaligned(const LhsScalar* a, LhsPacket& dest) const |
||||
|
{ |
||||
|
dest = ploaddup<LhsPacket>(a); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp) const |
||||
|
{ |
||||
|
madd_impl(a, b, c, tmp, typename conditional<Vectorizable,true_type,false_type>::type()); |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd_impl(const LhsPacket& a, const RhsPacket& b, AccPacket& c, RhsPacket& tmp, const true_type&) const |
||||
|
{ |
||||
|
//std::cerr << CYELLOW "*" << CRESET; |
||||
|
//RealScalar, duals::dual<RealScalar> |
||||
|
#ifdef EIGEN_HAS_SINGLE_INSTRUCTION_MADD |
||||
|
EIGEN_UNUSED_VARIABLE(tmp); |
||||
|
c.v = pmadd(a,b.v,c.v); |
||||
|
#else |
||||
|
tmp = b; tmp = RhsPacket(pmul(a,LhsPacket(tmp.v))); c = padd(c,tmp); |
||||
|
#endif |
||||
|
|
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void madd_impl(const LhsScalar& a, const RhsScalar& b, ResScalar& c, RhsScalar& /*tmp*/, const false_type&) const |
||||
|
{ |
||||
|
c += a * b; |
||||
|
} |
||||
|
|
||||
|
EIGEN_STRONG_INLINE void acc(const AccPacket& c, const ResPacket& alpha, ResPacket& r) const |
||||
|
{ |
||||
|
r = cj.pmadd(alpha,c,r); |
||||
|
} |
||||
|
|
||||
|
protected: |
||||
|
dconj_helper<ResPacket,ResPacket,false,ConjRhs> cj; |
||||
|
}; |
||||
|
|
||||
|
} } // Eigen::internal |
||||
|
|
||||
|
#endif // gebp_traits |
||||
|
//////// |
||||
|
|
||||
|
|
||||
|
|
||||
|
#endif // CPPDUALS_DONT_VECTORIZE |
||||
|
|
||||
|
#endif // CPPDUALS_DUAL_EIGEN |
||||
|
After Width: 610 | Height: 219 | Size: 15 KiB |
@ -0,0 +1,86 @@ |
|||||
|
% |
||||
|
% biber --tool --output_align --output_indent=2 --output_fieldcase=lower paper.bib |
||||
|
% |
||||
|
@misc{eigenweb, |
||||
|
author = {Guennebaud, Gaël and Jacob, Benoît and others}, |
||||
|
date = {2010}, |
||||
|
howpublished = {\url{http://eigen.tuxfamily.org}}, |
||||
|
title = {Eigen v3}, |
||||
|
} |
||||
|
|
||||
|
@misc{autodiff, |
||||
|
author = {Leal, Allan}, |
||||
|
date = {2019}, |
||||
|
howpublished = {\url{https://github.com/autodiff/autodiff}}, |
||||
|
title = {Autodiff}, |
||||
|
} |
||||
|
|
||||
|
@misc{autodifforg, |
||||
|
author = {Bücker, Martin and Hovland, Paul}, |
||||
|
date = {2019}, |
||||
|
howpublished = {\url{http://www.autodiff.org}}, |
||||
|
title = {autodiff.org}, |
||||
|
} |
||||
|
|
||||
|
@misc{spindrops, |
||||
|
author = {Tesch, Michael and Glaser, Niklas and Glaser, Steffen J.}, |
||||
|
date = {2019}, |
||||
|
howpublished = {\url{https://spindrops.org/}}, |
||||
|
title = {SpinDrops 2.0}, |
||||
|
} |
||||
|
|
||||
|
@inproceedings{openblas, |
||||
|
address = {Denver, Colorado}, |
||||
|
author = {Wang, Qian and Zhang, Xianyi and Zhang, Yunquan and Yi, Qing}, |
||||
|
booktitle = {Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis ({SC13})}, |
||||
|
doi = {10.1145/2503210.2503219}, |
||||
|
isbn = {978-1-4503-2378-9}, |
||||
|
language = {en}, |
||||
|
pages = {1-12}, |
||||
|
publisher = {{ACM Press}}, |
||||
|
title = {{AUGEM}: Automatically Generate High Performance Dense Linear Algebra Kernels on {X86 CPUs}}, |
||||
|
year = {2013} |
||||
|
} |
||||
|
|
||||
|
@incollection{FAD, |
||||
|
abstract = {This work deals with an implementation of automatic differentiation of C++ computer programs in forward mode using operator overloading and expression templates. In conjunction with a careful reuse of data, this technique also improves performance of programs involving linear algebra computations mixed or not with automatic differentiation. We give a broad view of implementation and explain some important concepts regarding code optimization. We conclude with some benchmarks applied to our optimal control software.}, |
||||
|
author = {Aubert, Pierre and Di C{é}sar{é}, Nicolas}, |
||||
|
editor = {Corliss, George and Faure, Christ{è}le and Griewank, Andreas and Hasco{ë}t, Laurent and Naumann, Uwe}, |
||||
|
location = {New York, NY}, |
||||
|
publisher = {Springer}, |
||||
|
booktitle = {Automatic Differentiation of Algorithms: From Simulation to Optimization}, |
||||
|
chapter = {37}, |
||||
|
crossref = {Corliss2002ADo}, |
||||
|
doi = {10.1007/978-1-4613-0075-5}, |
||||
|
date = {2002}, |
||||
|
pages = {311--315}, |
||||
|
series = {Computer and Information Science}, |
||||
|
title = {Expression Templates and Forward Mode Automatic Differentiation}, |
||||
|
} |
||||
|
|
||||
|
@misc{audi, |
||||
|
abstract = {Header only, C++ library (and the Python pyaudi package) implementing the algebra of Taylor truncated polynomials and a few algorithms useful for its applications (Differential Intelligence, automatic differentiation, Taylor Models, etc.)}, |
||||
|
author = {Izzo, Dario and Biscani, Francesco and Sánchez, Carlos and Müller, Jörg and Heddes, Mike}, |
||||
|
date = {2019-05}, |
||||
|
doi = {10.5281/zenodo.2677671}, |
||||
|
howpublished = {Zenodo}, |
||||
|
shorttitle = {Darioizzo/Audi}, |
||||
|
title = {Darioizzo/Audi: {{Update}} Third Party Dependencies}, |
||||
|
} |
||||
|
|
||||
|
@inproceedings{adolc, |
||||
|
author = {Walther, Andrea}, |
||||
|
booktitle = {Combinatorial Scientific Computing}, |
||||
|
editor = {Uwe Naumann and Olaf Schenk}, |
||||
|
publisher = {Chapman-Hall CRC Computational Science}, |
||||
|
year = {2012}, |
||||
|
title = {Getting started with {ADOL-C}}, |
||||
|
isbn = {9781439827352}, |
||||
|
} |
||||
|
|
||||
|
@misc{ceres, |
||||
|
author = {Agarwal, Sameer and Mierle, Keir and others}, |
||||
|
howpublished = {\url{http://ceres-solver.org}}, |
||||
|
title = {Ceres Solver}, |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,164 @@ |
|||||
|
--- |
||||
|
title: 'cppduals: a nestable vectorized templated dual number library for C++11' |
||||
|
tags: |
||||
|
- C++ |
||||
|
- dual numbers |
||||
|
- autodiff |
||||
|
- differentiation |
||||
|
- vectorization |
||||
|
- Eigen |
||||
|
authors: |
||||
|
- name: Michael Tesch |
||||
|
orcid: 0000-0003-4096-1562 |
||||
|
affiliation: "1" |
||||
|
affiliations: |
||||
|
- name: Department of Chemistry, Technische Universität München, 85747 Garching, Germany |
||||
|
index: 1 |
||||
|
date: 09 May 2019 |
||||
|
bibliography: paper.bib |
||||
|
--- |
||||
|
|
||||
|
# Summary |
||||
|
|
||||
|
Mathematical algorithms in the field of optimization often require the |
||||
|
simultaneous computation of a function and its derivative. The |
||||
|
derivative of many functions can be found automatically, a process |
||||
|
referred to as automatic differentiation. Dual numbers, close |
||||
|
relatives of the complex numbers, are of particular use in automatic |
||||
|
differentiation. This library provides an extremely fast |
||||
|
implementation of dual numbers for C++, ``duals::dual<>``, which, when |
||||
|
replacing scalar types, can be used to automatically calculate a |
||||
|
derivative. |
||||
|
|
||||
|
A real function's value can be made to carry the derivative of the |
||||
|
function with respect to a real argument by replacing the real |
||||
|
argument with a dual number having a unit dual part. This property is |
||||
|
recursive: replacing the real part of a dual number with more dual |
||||
|
numbers results in the dual part's dual part holding the function's |
||||
|
second derivative. The ``dual<>`` type in this library allows this |
||||
|
nesting (although we note here that it may not be the fastest solution |
||||
|
for calculating higher order derivatives.) |
||||
|
|
||||
|
There are a large number of automatic differentiation libraries and |
||||
|
classes for C++: adolc [@adolc], FAD [@FAD], autodiff [@autodiff], |
||||
|
ceres [@ceres], AuDi [@audi], to name a few, with another 30-some |
||||
|
listed at [autodiff.org @autodifforg]. But there were no simple |
||||
|
single-file stand-alone header libraries that were explicitly |
||||
|
vectorized. *Cppduals* can be copied and used as a single header file |
||||
|
``duals/dual`` with no dependencies other than the standard library, |
||||
|
and the vectorization support is contained in a small number of |
||||
|
additional auxiliary files. The interface generally follows the |
||||
|
conventions of the C++11 standard library's ``std::complex`` type, and |
||||
|
has very liberal licensing. |
||||
|
|
||||
|
In order to fully utilize the computing resources of modern CPUs it is |
||||
|
often necessary to use their special data-parallel capabilities. |
||||
|
However, compilers often struggle to find the best sequence of |
||||
|
instructions to achieve maximum performance due to difficulties in |
||||
|
automatically detecting parallel data operations in programs and then |
||||
|
mapping those parallel operations onto the CPU's data-parallel |
||||
|
instructions. Some intervention from the programmer to exploit these |
||||
|
special data-parallel instructions, combined with cache-optimized |
||||
|
algorithms, can improve program execution speed significantly. This |
||||
|
is done by *cppduals* through providing template specializations for |
||||
|
selected C++ data types. |
||||
|
|
||||
|
Template specializations that map the dual arithmetic directly to |
||||
|
vector machine language are provided for the types typically used to |
||||
|
calculate first-order derivatives: ``dual<float>``, ``dual<double>``, |
||||
|
``std::complex<dual<float>>``, and ``std::complex<dual<double>>``. |
||||
|
These types and their algebras are expressed in hand-coded assembly |
||||
|
for use with the Eigen [@eigenweb] matrix library. The vector |
||||
|
operations for the ``dual<>`` type are then picked up automatically by |
||||
|
Eigen's cache-optimized algorithms. The integration lets us achieve |
||||
|
extremely fast performance for automatic forward, first-order |
||||
|
differentiation of matrix expressions. Furthermore, by piggy-backing |
||||
|
on Eigen's algorithms, the library inherits future improvements and |
||||
|
adaptations to other hardware platforms. The vector specializations |
||||
|
are currently available for the x86_64 SSE and AVX instruction sets, |
||||
|
though support for other vector machine architectures (such as GPUs) |
||||
|
can easily be added. |
||||
|
|
||||
|
# Mathematics |
||||
|
|
||||
|
A dual number has a *real part* and a *dual part*, the *dual part* is |
||||
|
multiplied by the dual unit $\epsilon$, with the property that |
||||
|
$\epsilon^2 = 0$. Formally the dual space, $\mathbb{D} = \{ x = a + b |
||||
|
\epsilon \; | \; a, b \in \mathbb{R}, \epsilon^2 = 0 \}$. |
||||
|
|
||||
|
The property can be used to differentiate functions of real values by |
||||
|
expanding $f(x)$ as its Taylor series at $a$: |
||||
|
|
||||
|
$$f(x) = f(a) + f'(a)(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \frac{f'''(a)}{3!}(x-a)^3 + ... $$ |
||||
|
|
||||
|
Setting $x = a + b\epsilon$ in this expansion gives |
||||
|
|
||||
|
$$\begin{split} |
||||
|
f(a + b \epsilon) &= f(a) + f'(a)(b \epsilon) + \frac{f''(a)}{2!}(b \epsilon)^2 |
||||
|
+ \frac{f'''(a)}{3!}(b \epsilon)^3 + ...\\ |
||||
|
&= f(a) + f'(a)(b \epsilon) |
||||
|
\end{split}$$ |
||||
|
|
||||
|
Because the $\epsilon^2$ terms are zero, the Taylor expansion |
||||
|
truncates after the $f'$ term. Thus to evaluate $f'(a)$: set $x = a + |
||||
|
b\epsilon$ with $b=1$, and take the dual part of the evaluated |
||||
|
function $\mathfrak{Du}(f(x))$. |
||||
|
|
||||
|
A matrix representation of the dual numbers is $\bigl( |
||||
|
\begin{smallmatrix}a & b \\ 0 & a\end{smallmatrix}\bigr)$. This form |
||||
|
can be used to calculate Fréchet derivatives of matrix functions $D_B |
||||
|
f(\mathbf{A})$ by doubling the size of the calculation and embedding |
||||
|
the parameter ($A$) and with-regard-to parts ($B$) into this doubled |
||||
|
matrix, zeroing the lower left quadrant: $D_B f(\mathbf{A}) = C$ where |
||||
|
$f\bigl( \begin{smallmatrix}A & B \\ 0 & A\end{smallmatrix}\bigr) = |
||||
|
\bigl( \begin{smallmatrix}F & C \\ 0 & F\end{smallmatrix}\bigr)$. |
||||
|
|
||||
|
# Benchmarks |
||||
|
|
||||
|
The above blocking method of computing matrix function derivatives |
||||
|
requires twice as much memory as using dual numbers, and furthermore |
||||
|
does not take advantage of the relative sparsity of dual number |
||||
|
arithmetic. However, the blocking method *does* permit the use of |
||||
|
highly optimized complex-valued BLAS libraries, which are often |
||||
|
significantly faster than "regularly" compiled code, being hand-tuned |
||||
|
for a specific CPU architecture and memory heirarchy. We compared |
||||
|
using ``dual<>`` to calculate the derivative of the matrix-matrix |
||||
|
product with using the blocking method implemented with OpenBLAS |
||||
|
[@openblas]. All benchmarks were performed single-threaded on an |
||||
|
*Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz* running *Fedora 30*, using |
||||
|
*Eigen v3.3.7*, *OpenBLAS v0.3.6*, and compiled using *clang v8.0.0*. |
||||
|
|
||||
|
The *cppduals* vectorized type reduced the time of a 32x32 |
||||
|
matrix-multiplication derivative by 40% over the 2Nx2N (in this case |
||||
|
64x64) multiplication performed by OpenBLAS (even with a suspected |
||||
|
performance bug in Eigen's GEMM algorithm, described below). In the |
||||
|
current implementation, this advantage diminishes as the matrix size |
||||
|
grows, as shown in Figure 1 , we suspect |
||||
|
this is due to a bug in Eigen's cache optimization for non-scalar |
||||
|
valued matrix-matrix multiplication. We note that the Eigen |
||||
|
scalar-valued matrix multiplications are roughly as fast as OpenBLAS, |
||||
|
demonstrating the validity of Eigen's approach to optimization, but |
||||
|
complex-valued multiplications take roughly twice as much time as |
||||
|
their OpenBLAS equivalents, indicating a performance bug in Eigen's |
||||
|
current optimizations, though only for complex-valued (and |
||||
|
consequently, dual-valued) matrices. |
||||
|
|
||||
|
We hope to achieve further speed improvements with tuning and more |
||||
|
debugging of the integration with Eigen. In general, dual-valued |
||||
|
operations should be marginally faster than corresponding |
||||
|
complex-valued operations, as they require slightly fewer floating |
||||
|
point operations. |
||||
|
|
||||
|
# Usage |
||||
|
|
||||
|
*Cppduals* is used in the SpinDrops [@spindrops] NMR and quantum |
||||
|
computing software for optimization of pulse quality functions. |
||||
|
|
||||
|
# Acknowledgments |
||||
|
|
||||
|
We acknowledge first of all the Eigen project and its contributors, |
||||
|
upon which the vectorization was based. Some funding was provided by |
||||
|
the TUM School of Education. |
||||
|
|
||||
|
# References |
||||
|
|
||||
@ -0,0 +1,240 @@ |
|||||
|
# |
||||
|
# Part of the cppduals Project |
||||
|
# |
||||
|
# (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
# |
||||
|
# See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for |
||||
|
# license information. |
||||
|
# |
||||
|
# This Source Code Form is subject to the terms of the Mozilla |
||||
|
# Public License v. 2.0. If a copy of the MPL was not distributed |
||||
|
# with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
||||
|
|
||||
|
# gtest_discover_tests requires 3.10 |
||||
|
cmake_minimum_required (VERSION 3.10) |
||||
|
|
||||
|
# Configure google-test as a downloadable library. |
||||
|
include (GoogleTest) |
||||
|
|
||||
|
if (WIN32) |
||||
|
add_definitions (-D_USE_MATH_DEFINES) |
||||
|
endif () |
||||
|
include_directories ("${CMAKE_SOURCE_DIR}") |
||||
|
include_directories ("${DEPS_ROOT}/include") |
||||
|
include_directories ("${EIGEN3_INCLUDE_DIRS}") |
||||
|
#include_directories ("${MPFR_INCLUDES}") |
||||
|
include_directories ("${EXPOKIT_INCLUDE_DIR}") |
||||
|
|
||||
|
set (IOFORMAT "IOFormat(FullPrecision, DontAlignCols, \", \", \"\\$<SEMICOLON>\\n\", \"\", \"\", \"[\", \"]\")") |
||||
|
add_definitions (-DEIGEN_DEFAULT_IO_FORMAT=${IOFORMAT}) |
||||
|
#add_definitions (-DEIGEN_DEFAULT_IO_FORMAT=EIGEN_IO_FORMAT_OCTAVE) |
||||
|
|
||||
|
# |
||||
|
# Correctness & Coverage |
||||
|
# |
||||
|
if (NOT MSVC) |
||||
|
set (OPT_FLAGS "-O2") |
||||
|
set (OPT_FLAGS "-O3;-msse3") |
||||
|
set (OPT_FLAGS "-O3;-mavx2;-mfma") |
||||
|
set (OPT_FLAGS "-O3;-march=native") |
||||
|
else () |
||||
|
set (OPT_FLAGS "/arch:IA32") |
||||
|
set (OPT_FLAGS "/arch:SSE") |
||||
|
set (OPT_FLAGS "/arch:SSE2") |
||||
|
set (OPT_FLAGS "/arch:AVX2") |
||||
|
endif () |
||||
|
|
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-fsanitize=address;-fno-omit-frame-pointer") |
||||
|
set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_VECTORIZE_CDUAL") |
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_DONT_VECTORIZE") |
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-DEIGEN_DONT_VECTORIZE") |
||||
|
|
||||
|
set (ALL_TESTS |
||||
|
test_dual test_funcs test_eigen test_packets |
||||
|
test_vectorize test_solve test_expm test_1 test_fmt |
||||
|
example |
||||
|
) |
||||
|
set (ALL_TEST_BINS ) |
||||
|
foreach (TEST_ ${ALL_TESTS}) |
||||
|
foreach (PHASE 1 2 3 4 5) |
||||
|
# check if file has phase defined |
||||
|
file (READ ${TEST_}.cpp TMPTXT) |
||||
|
string (FIND "${TMPTXT}" "PHASE_${PHASE}" hasphase) |
||||
|
if ((${hasphase} EQUAL -1) AND NOT (${PHASE} EQUAL 1)) |
||||
|
continue () |
||||
|
endif () |
||||
|
|
||||
|
set (TEST ${TEST_}_${PHASE}) |
||||
|
message ("Adding test ${TEST}") |
||||
|
set (ALL_TEST_BINS ${ALL_TEST_BINS} ${TEST}) |
||||
|
|
||||
|
add_executable (${TEST} ${TEST_}.cpp) |
||||
|
set (PHASE_FLAGS ${OPT_FLAGS} -DPHASE_${PHASE}) |
||||
|
string (REPLACE ";" ", " L2 "${CMAKE_CXX_FLAGS}") |
||||
|
target_compile_options (${TEST} PUBLIC ${PHASE_FLAGS}) |
||||
|
target_compile_definitions (${TEST} PRIVATE "OPT_FLAGS=${L2}") |
||||
|
target_link_libraries (${TEST} gtest_main cppduals_coverage_config) |
||||
|
#target_link_libraries (${TEST} -lasan) |
||||
|
add_dependencies (${TEST} eigenX expokitX) |
||||
|
gtest_discover_tests (${TEST} TEST_LIST ${TEST}_targets) |
||||
|
set_tests_properties (${${TEST}_targets} PROPERTIES TIMEOUT 10) |
||||
|
# -ftest-coverage |
||||
|
endforeach (PHASE) |
||||
|
endforeach (TEST_) |
||||
|
|
||||
|
# special for fmt |
||||
|
target_compile_features (test_fmt_1 PUBLIC cxx_std_14) |
||||
|
target_link_libraries (test_fmt_1 fmt::fmt) |
||||
|
|
||||
|
if (CPPDUALS_BENCHMARK) |
||||
|
# |
||||
|
# Benchmarks |
||||
|
# |
||||
|
|
||||
|
message ("searching: ${DEPS_ROOT} for google benchmark libs") |
||||
|
find_library (BENCHMARK_LIBRARY benchmark PATHS ${DEPS_ROOT}/lib) |
||||
|
find_library (BENCHMARKM_LIBRARY benchmark_main PATHS ${DEPS_ROOT}/lib) |
||||
|
#find_library (PTHREAD_LIBRARY pthread) |
||||
|
message ("BENCHMARK_LIBRARY: ${BENCHMARK_LIBRARY}") |
||||
|
include_directories ("${BENCHMARK_INC_DIR}") |
||||
|
if (Boost_FOUND AND NO) |
||||
|
add_definitions (-DHAVE_BOOST=1) |
||||
|
include_directories ("${Boost_INCLUDE_DIRS}") |
||||
|
include_directories ("${PIRANHA_INCLUDE_DIR}") |
||||
|
include_directories ("${AUDI_INCLUDE_DIR}") |
||||
|
endif (Boost_FOUND AND NO) |
||||
|
|
||||
|
if (NOT APPLE AND NOT BLA_VENDOR) |
||||
|
if (NOT BLA_STATIC) |
||||
|
# default to static |
||||
|
set (BLA_STATIC OFF) |
||||
|
endif (NOT BLA_STATIC) |
||||
|
set (BLA_VENDOR OpenBLAS) |
||||
|
endif (NOT APPLE AND NOT BLA_VENDOR) |
||||
|
find_package (BLAS REQUIRED) |
||||
|
#find_package (LAPACK REQUIRED) |
||||
|
add_definitions (-DHAVE_BLAS) |
||||
|
#add_definitions (-DEIGEN_USE_BLAS) |
||||
|
|
||||
|
# find lapacke.h cblas.h |
||||
|
set (CBLAS_HINTS ${BLAS_DIR} ${LAPACK_DIR} /usr /usr/local /opt /opt/local) |
||||
|
set (CBLAS_PATHS |
||||
|
/usr |
||||
|
/usr/local |
||||
|
/opt |
||||
|
/opt/local |
||||
|
/usr/local/opt |
||||
|
/System/Library/Frameworks) |
||||
|
|
||||
|
# Finds the include directories for lapacke.h |
||||
|
find_path (LAPACKE_INCLUDE_DIRS |
||||
|
NAMES lapacke.h |
||||
|
HINTS ${CBLAS_HINTS} |
||||
|
PATH_SUFFIXES |
||||
|
include inc include/x86_64 include/x64 |
||||
|
openblas/include |
||||
|
# Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Versions/Current/Headers |
||||
|
PATHS ${CBLAS_PATHS} |
||||
|
DOC "LAPACK(E) include header lapacke.h") |
||||
|
mark_as_advanced (LAPACKE_INCLUDE_DIRS) |
||||
|
if (LAPACKE_INCLUDE_DIRS) |
||||
|
include_directories (${LAPACKE_INCLUDE_DIRS}) |
||||
|
else () |
||||
|
add_definitions (-DEIGEN_LAPACKE) |
||||
|
endif (LAPACKE_INCLUDE_DIRS) |
||||
|
|
||||
|
# Finds the include directories for cblas*.h |
||||
|
find_path (CBLAS_INCLUDE_DIRS |
||||
|
NAMES cblas.h cblas_openblas.h cblas-openblas.h |
||||
|
HINTS ${CBLAS_HINTS} |
||||
|
PATH_SUFFIXES |
||||
|
include inc include/x86_64 include/x64 |
||||
|
openblas/include |
||||
|
# Accelerate.framework/Versions/Current/Frameworks/vecLib.framework/Versions/Current/Headers |
||||
|
PATHS ${CBLAS_PATHS} |
||||
|
DOC "BLAS include header cblas.h") |
||||
|
mark_as_advanced (CBLAS_INCLUDE_DIRS) |
||||
|
include_directories (${CBLAS_INCLUDE_DIRS}) |
||||
|
foreach (cblas in cblas.h cblas_openblas.h cblas-openblas.h) |
||||
|
if (EXISTS "${CBLAS_INCLUDE_DIRS}/${cblas}") |
||||
|
add_definitions (-DCBLAS_HEADER="${cblas}") |
||||
|
break() |
||||
|
endif (EXISTS "${CBLAS_INCLUDE_DIRS}/${cblas}") |
||||
|
endforeach (cblas) |
||||
|
|
||||
|
message ("Found BLAS : ${BLAS_LIBRARIES}") |
||||
|
message ("Found cBLAS : ${CBLAS_INCLUDE_DIRS}") |
||||
|
message ("Found lapacke : ${LAPACKE_INCLUDE_DIRS}") |
||||
|
|
||||
|
set (OPT_FLAGS "") |
||||
|
if (NOT MSVC) |
||||
|
#set (OPT_FLAGS "-O3;-mavx") |
||||
|
#set (OPT_FLAGS "-O3;-march=native;-fopenmp") |
||||
|
set (OPT_FLAGS "-O3;-msse3;-fopenmp") |
||||
|
set (OPT_FLAGS "-O3") |
||||
|
set (OPT_FLAGS "-O3;-msse3") |
||||
|
set (OPT_FLAGS "-O3;-march=native;-funroll-loops") |
||||
|
set (OPT_FLAGS "-O3;-msse3;-mavx2;-mfma") |
||||
|
set (OPT_FLAGS "-O3;-march=native") |
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-save-temps;-fverbose-asm") |
||||
|
else () |
||||
|
set (OPT_FLAGS "/arch:IA32") |
||||
|
set (OPT_FLAGS "/arch:SSE") |
||||
|
set (OPT_FLAGS "/arch:SSE2") |
||||
|
set (OPT_FLAGS "/arch:AVX2") |
||||
|
endif () |
||||
|
|
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-DEIGEN_DONT_VECTORIZE") |
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_DONT_VECTORIZE") |
||||
|
#set (OPT_FLAGS "${OPT_FLAGS};-DCPPDUALS_DONT_VECTORIZE_CDUAL") |
||||
|
|
||||
|
foreach (BENCH bench_dual bench_eigen bench_gemm bench_example bench_fmt) |
||||
|
add_executable (${BENCH} ${BENCH}.cpp) |
||||
|
target_compile_options (${BENCH} PUBLIC ${OPT_FLAGS}) |
||||
|
#set_target_properties (${BENCH} PROPERTIES LINK_FLAGS -fopenmp) |
||||
|
#target_link_options (${BENCH} PUBLIC ${OPT_FLAGS}) |
||||
|
string (REPLACE ";" ", " L2 "${OPT_FLAGS} ${CMAKE_CXX_FLAGS}") |
||||
|
target_compile_definitions (${BENCH} PRIVATE "OPT_FLAGS=${L2}") |
||||
|
add_dependencies (${BENCH} benchmarkX eigenX expokitX) |
||||
|
target_link_libraries (${BENCH} ${BENCHMARK_LIBRARY} -lpthread ${BLAS_LIBRARIES}) |
||||
|
endforeach (BENCH) |
||||
|
|
||||
|
target_link_libraries (bench_fmt fmt::fmt) |
||||
|
|
||||
|
endif (CPPDUALS_BENCHMARK) |
||||
|
|
||||
|
add_executable (sandbox sandbox.cpp) |
||||
|
add_dependencies (sandbox eigenX expokitX ) # mpfrX mprealX |
||||
|
#target_compile_options (sandbox PUBLIC ${OPT_FLAGS}) |
||||
|
target_compile_options (sandbox PUBLIC -DCPPDUALS_VECTORIZE_CDUAL) |
||||
|
if (MSVC) |
||||
|
target_compile_options (sandbox PUBLIC /arch:AVX2) |
||||
|
else () |
||||
|
target_compile_options (sandbox PUBLIC -O1 -msse3 -mavx2 -mfma) |
||||
|
endif () |
||||
|
|
||||
|
set_target_properties (sandbox PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) |
||||
|
target_link_libraries (sandbox PUBLIC cppduals_coverage_config) |
||||
|
|
||||
|
# |
||||
|
# Generate coverage reports |
||||
|
# |
||||
|
if (CODE_COVERAGE) |
||||
|
add_custom_target (cov |
||||
|
DEPENDS ${ALL_TEST_BINS} |
||||
|
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test |
||||
|
COMMAND $<TARGET_FILE:sandbox> |
||||
|
COMMAND lcov --capture --directory . --output-file coverage.info |
||||
|
COMMAND lcov --remove coverage.info '/usr/*' --output-file coverage.info |
||||
|
COMMAND lcov --remove coverage.info '*/thirdparty/*' --output-file coverage.info |
||||
|
COMMAND lcov --remove coverage.info '*/googletest/*' --output-file coverage.info |
||||
|
COMMAND lcov --list coverage.info |
||||
|
) |
||||
|
add_custom_target (cov-html |
||||
|
DEPENDS cov |
||||
|
COMMAND rm -rf ../coverage |
||||
|
COMMAND genhtml --ignore-errors source coverage.info --legend --title "make cov" |
||||
|
--output-directory=../coverage |
||||
|
COMMAND echo "output in coverage/index.html" |
||||
|
) |
||||
|
endif () |
||||
@ -0,0 +1,88 @@ |
|||||
|
//===-- bench_dual - test dual class ----------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals Project
|
||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
#include <iostream>
|
||||
|
#include "benchmark/benchmark.h"
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <Eigen/Core> // for SimdInstructionSetsInUse()
|
||||
|
#include <duals/dual>
|
||||
|
|
||||
|
#define N_RANGE ->RangeMultiplier(8)->Range(2, 1<<13) // 2 - 2048
|
||||
|
|
||||
|
|
||||
|
template <class Rt> void B_Add(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
a[i] = b[i] + c[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_Sub(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
a[i] = b[i] - c[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_Mul(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
a[i] = b[i] * c[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_Div(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
a[i] = b[i] / c[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_Add, duals::dualf) N_RANGE; |
||||
|
BENCHMARK_TEMPLATE(B_Add, std::complex<float>) N_RANGE; |
||||
|
//BENCHMARK_TEMPLATE(B_Add, std::complex<duals::dualf>) N_RANGE;
|
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_Sub, duals::dualf) N_RANGE; |
||||
|
BENCHMARK_TEMPLATE(B_Sub, std::complex<float>) N_RANGE; |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_Mul, duals::dualf) N_RANGE; |
||||
|
BENCHMARK_TEMPLATE(B_Mul, std::complex<float>) N_RANGE; |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_Div, duals::dualf) N_RANGE; |
||||
|
BENCHMARK_TEMPLATE(B_Div, std::complex<float>) N_RANGE; |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::benchmark::Initialize(&argc, argv); |
||||
|
::benchmark::RunSpecifiedBenchmarks(); |
||||
|
} |
||||
@ -0,0 +1,398 @@ |
|||||
|
//===-- bench_dual - test dual class ----------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
|
||||
|
#include <iostream>
|
||||
|
#include <fstream>
|
||||
|
#include <complex>
|
||||
|
#include <memory>
|
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Core>
|
||||
|
#include <Eigen/Dense>
|
||||
|
|
||||
|
#include "eexpokit/padm.hpp"
|
||||
|
#include "eexpokit/chbv.hpp"
|
||||
|
#include "eexpokit/expv.hpp"
|
||||
|
//#include "eexpokit/mexpv.hpp"
|
||||
|
#include "benchmark/benchmark.h"
|
||||
|
|
||||
|
using namespace duals; |
||||
|
|
||||
|
template< class T > struct type_identity { typedef T type; }; |
||||
|
|
||||
|
namespace Eigen { |
||||
|
namespace internal { |
||||
|
template<typename T> struct is_exp_known_type; |
||||
|
template<typename T> struct is_exp_known_type<std::complex<T>> : is_exp_known_type<T> {}; |
||||
|
#if 0
|
||||
|
template <typename RealScalar> struct MatrixExponentialScalingOp; |
||||
|
template <typename RealScalar> |
||||
|
struct MatrixExponentialScalingOp<duals::dual<RealScalar>> |
||||
|
{ |
||||
|
MatrixExponentialScalingOp(int squarings) : m_squarings(squarings) { } |
||||
|
inline const duals::dual<RealScalar> operator() (const duals::dual<RealScalar> & x) const |
||||
|
{ |
||||
|
using std::ldexp; |
||||
|
return ldexp(x, -m_squarings); |
||||
|
} |
||||
|
typedef std::complex<duals::dual<RealScalar>> ComplexScalar; |
||||
|
inline const ComplexScalar operator() (const ComplexScalar& x) const |
||||
|
{ |
||||
|
using std::ldexp; |
||||
|
return ComplexScalar(ldexp(x.real(), -m_squarings), ldexp(x.imag(), -m_squarings)); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
int m_squarings; |
||||
|
}; |
||||
|
#endif
|
||||
|
}} |
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
|
||||
|
namespace Eigen { |
||||
|
namespace internal { |
||||
|
template <typename MatrixType, typename T> |
||||
|
struct matrix_exp_computeUV<MatrixType, duals::dual<T> > |
||||
|
{ |
||||
|
typedef typename NumTraits<typename traits<MatrixType>::Scalar>::Real RealScalar; |
||||
|
template <typename ArgType> |
||||
|
static void run(const ArgType& arg, MatrixType& U, MatrixType& V, int& squarings) |
||||
|
{ |
||||
|
using std::frexp; |
||||
|
using std::pow; |
||||
|
const RealScalar l1norm = arg.cwiseAbs().colwise().sum().maxCoeff(); |
||||
|
squarings = 0; |
||||
|
if (l1norm < 1.495585217958292e-002) { |
||||
|
matrix_exp_pade3(arg, U, V); |
||||
|
} else if (l1norm < 2.539398330063230e-001) { |
||||
|
matrix_exp_pade5(arg, U, V); |
||||
|
} else if (l1norm < 9.504178996162932e-001) { |
||||
|
matrix_exp_pade7(arg, U, V); |
||||
|
} else if (l1norm < 2.097847961257068e+000) { |
||||
|
matrix_exp_pade9(arg, U, V); |
||||
|
} else { |
||||
|
const RealScalar maxnorm = 5.371920351148152; |
||||
|
frexp(l1norm / maxnorm, &squarings); |
||||
|
if (squarings < 0) squarings = 0; |
||||
|
MatrixType A = arg.unaryExpr(MatrixExponentialScalingOp<RealScalar>(squarings)); |
||||
|
matrix_exp_pade13(A, U, V); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
}} |
||||
|
|
||||
|
/* encode the type into an integer for benchmark output */ |
||||
|
template<typename Tp> struct type_num { /* should fail */ }; |
||||
|
template<> struct type_num<float> { static constexpr int id = 1; }; |
||||
|
template<> struct type_num<double> { static constexpr int id = 2; }; |
||||
|
template<> struct type_num<long double> { static constexpr int id = 3; }; |
||||
|
template<typename Tp> struct type_num<std::complex<Tp>> { static constexpr int id = 10 + type_num<Tp>::id; }; |
||||
|
template<typename Tp> struct type_num<duals::dual<Tp>> { static constexpr int id = 100 + type_num<Tp>::id; }; |
||||
|
|
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
template <class T> using MatrixX = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; |
||||
|
|
||||
|
#if 0
|
||||
|
#define V_RANGE(V,NF) ->Arg(V*4/NF)->Arg(V*32/NF)->Arg(V*256/NF)->Arg(V*2048/NF)->Arg(V*1)->Complexity()
|
||||
|
#else
|
||||
|
#define V_RANGE(V,NF) ->Arg(V*1024/NF)
|
||||
|
#endif
|
||||
|
|
||||
|
template <class Rt, class U> void B_VecVecAddCXX(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
a[i] = b[i] + b[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's vec-vec multiplication
|
||||
|
template <class Rt, class U> void B_VecVecAdd(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
B = A + A; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's vec-vec multiplication
|
||||
|
template <class Rt, class U> void B_VecVecSub(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
B = A - A; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class Rt, class U> void B_VecVecMulCXX(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> c(N); |
||||
|
for (auto _ : state) { |
||||
|
for (int i = 0; i < N; i++) |
||||
|
b[i] = a[i] * a[i]; |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's vec-vec multiplication
|
||||
|
template <class Rt, class U> void B_VecVecMul(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
B = A.array() * C.array(); |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's vec-vec multiplication
|
||||
|
template <class Rt, class U> void B_VecVecDiv(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
C = A.array() / B.array(); |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's matrix-matrix multiplication
|
||||
|
template <class T, class U> void B_MatMat(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
typedef typename Eigen::ScalarBinaryOpTraits<T, U>::ReturnType R; |
||||
|
MatrixX<T> A = MatrixX<T>::Random(N, N); |
||||
|
MatrixX<U> B = MatrixX<U>::Random(N, N); |
||||
|
MatrixX<R> C = MatrixX<R>::Random(N, N); |
||||
|
for (auto _ : state) { |
||||
|
C.noalias() = A * B; |
||||
|
benchmark::ClobberMemory(); // Force c to be written to memory.
|
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<T>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure compiler's matrix-matrix multiplication
|
||||
|
template <class Rt, class U> void B_MatMatCXX(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N*N); |
||||
|
std::vector<Rt> b(N*N); |
||||
|
std::vector<Rt> c(N*N); |
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
state.PauseTiming(); |
||||
|
a.assign(N*N,1.1); |
||||
|
b.assign(N*N,2.2); |
||||
|
c.assign(N*N,0.); |
||||
|
state.ResumeTiming(); |
||||
|
|
||||
|
for(int i=0; i<N; ++i) |
||||
|
for(int j=0; j<N; ++j) |
||||
|
for(int k=0; k<N; ++k) |
||||
|
c[i*N+j] += a[i*N+k] * b[k*N+j]; |
||||
|
|
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure Eigen's matrix-matrix solve
|
||||
|
template <class Rt, class U> void B_MatDiv(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Zero(N, N); |
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
C = B.partialPivLu().solve(A); // C = A / B
|
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure eigen's matrix-vector multiplication
|
||||
|
template <class Rt, class U> void B_MatVec(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> b = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> c = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
c = A * b; |
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_Expm(benchmark::State& state) |
||||
|
{ |
||||
|
int N = state.range(0); |
||||
|
//Rt S(1);
|
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Zero(N, N); |
||||
|
//A = S * A / A.norm();
|
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
B = A.exp(); |
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_ExpPadm(benchmark::State& state) |
||||
|
{ |
||||
|
int N = state.range(0); |
||||
|
//Rt S(1);
|
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Zero(N, N); |
||||
|
//A = S * A / A.norm();
|
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
B = eexpokit::padm(A); |
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_ExpExpv(benchmark::State& state) |
||||
|
{ |
||||
|
int N = state.range(0); |
||||
|
//Rt S(1);
|
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Zero(N, N); |
||||
|
MatrixX<Rt> b = MatrixX<Rt>::Ones(N, 1); |
||||
|
MatrixX<Rt> c = MatrixX<Rt>::Zero(N, 1); |
||||
|
//A = S * A / A.norm();
|
||||
|
|
||||
|
// sparse random fill
|
||||
|
for (int i = 0; i < 4*N; i++) |
||||
|
A((int)duals::randos::random(0.,N-1.), |
||||
|
(int)duals::randos::random(0.,N-1.)) = duals::randos::random2<Rt>(); |
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
auto ret = eexpokit::expv(1,A,b); |
||||
|
if (ret.err > 1) { |
||||
|
std::ofstream f("fail.m"); |
||||
|
f << "A=" << A.format(eexpokit::OctaveFmt) << "\n"; |
||||
|
break; |
||||
|
} |
||||
|
// c = ret.w
|
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class Rt> void B_ExpChbv(benchmark::State& state) |
||||
|
{ |
||||
|
int N = state.range(0); |
||||
|
//Rt S(1);
|
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> b = MatrixX<Rt>::Zero(N, 1); |
||||
|
MatrixX<Rt> c = MatrixX<Rt>::Zero(N, 1); |
||||
|
//A = S * A / A.norm();
|
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
c = eexpokit::chbv(A,b); |
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
#define MAKE_BM_SIMPLE(TYPE1,TYPE2,NF) \
|
||||
|
BENCHMARK_TEMPLATE(B_VecVecAdd, TYPE1,TYPE2) V_RANGE(4,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_VecVecSub, TYPE1,TYPE2) V_RANGE(4,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_VecVecMul, TYPE1,TYPE2) V_RANGE(4,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_VecVecDiv, TYPE1,TYPE2) V_RANGE(4,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_MatVec, TYPE1,TYPE2) V_RANGE(4,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_MatMat, TYPE1,TYPE2) V_RANGE(1,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_MatDiv, TYPE1,TYPE2) V_RANGE(1,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_Expm, TYPE1) V_RANGE(1,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_ExpPadm, TYPE1) V_RANGE(1,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_ExpChbv, TYPE1) V_RANGE(1,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_ExpExpv, TYPE1) V_RANGE(1,NF) |
||||
|
|
||||
|
#define MAKE_BENCHMARKS(TYPE1,TYPE2,NF) \
|
||||
|
MAKE_BM_SIMPLE(TYPE1,TYPE2,NF) |
||||
|
|
||||
|
// BENCHMARK_TEMPLATE(B_VecVecMulCXX, TYPE1,TYPE2) V_RANGE(4,NF);
|
||||
|
// BENCHMARK_TEMPLATE(B_MatMatCXX, TYPE1,TYPE2) V_RANGE(1,NF);
|
||||
|
|
||||
|
#if 1
|
||||
|
MAKE_BENCHMARKS(float, float, 1); |
||||
|
MAKE_BENCHMARKS(complexf, complexf,2); |
||||
|
MAKE_BM_SIMPLE(dualf, dualf,2); |
||||
|
MAKE_BM_SIMPLE(cdualf, cdualf,4); |
||||
|
#else
|
||||
|
MAKE_BENCHMARKS(double, double,1); |
||||
|
MAKE_BENCHMARKS(complexd, complexd,2); |
||||
|
MAKE_BM_SIMPLE(duald, duald,2); |
||||
|
MAKE_BM_SIMPLE(cduald, cduald,4); |
||||
|
#endif
|
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
#ifndef EIGEN_VECTORIZE
|
||||
|
static_assert(false, "no vectorization?"); |
||||
|
#endif
|
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::benchmark::Initialize(&argc, argv); |
||||
|
::benchmark::RunSpecifiedBenchmarks(); |
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
//===-- bench_example - benchmark the examples ---------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
|
||||
|
#include <complex>
|
||||
|
#include <duals/dual>
|
||||
|
#include "benchmark/benchmark.h"
|
||||
|
|
||||
|
using namespace duals; |
||||
|
|
||||
|
template <class T> T f(T x) { return pow(x,pow(x,x)); } |
||||
|
template <class T> T df(T x) { return pow(x,-1. + x + pow(x,x)) * (1. + x*log(x) + x*pow(log(x),2.)); } |
||||
|
template <class T> T ddf(T x) { return (pow(x,pow(x,x)) * pow(pow(x,x - 1.) + pow(x,x)*log(x)*(log(x) + 1.), 2.) + |
||||
|
pow(x,pow(x,x)) * (pow(x,x - 1.) * log(x) + |
||||
|
pow(x,x - 1.) * (log(x) + 1.) + |
||||
|
pow(x,x - 1.) * ((x - 1.)/x + log(x)) + |
||||
|
pow(x,x) * log(x) * pow(log(x) + 1., 2.) )); } |
||||
|
|
||||
|
template <class T> |
||||
|
void F(benchmark::State& state) { |
||||
|
T x = state.range(0); |
||||
|
for (auto _ : state) { benchmark::DoNotOptimize(f(x)); } |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
void DF(benchmark::State& state) { |
||||
|
T x = state.range(0); |
||||
|
for (auto _ : state) { benchmark::DoNotOptimize(df(x)); } |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
void DDF(benchmark::State& state) { |
||||
|
T x = state.range(0); |
||||
|
for (auto _ : state) { benchmark::DoNotOptimize(ddf(x)); } |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
void dF(benchmark::State& state) { |
||||
|
T x = state.range(0); |
||||
|
for (auto _ : state) { benchmark::DoNotOptimize(f(dual<T>(x,1))); } |
||||
|
} |
||||
|
|
||||
|
template <class T> |
||||
|
void ddF(benchmark::State& state) { |
||||
|
T x = state.range(0); |
||||
|
for (auto _ : state) { |
||||
|
benchmark::DoNotOptimize(f(duals::dual<duals::dual<T>>(x+1_e,1+0_e))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(F, float) ->Arg(2); // V_RANGE(1,NF)
|
||||
|
BENCHMARK_TEMPLATE(DF, float)->Arg(2); // V_RANGE(1,NF)
|
||||
|
BENCHMARK_TEMPLATE(DDF, float)->Arg(2); // V_RANGE(1,NF)
|
||||
|
BENCHMARK_TEMPLATE(dF, float)->Arg(2); // V_RANGE(1,NF)
|
||||
|
BENCHMARK_TEMPLATE(ddF, float)->Arg(2); // V_RANGE(1,NF)
|
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
::benchmark::Initialize(&argc, argv); |
||||
|
::benchmark::RunSpecifiedBenchmarks(); |
||||
|
} |
||||
@ -0,0 +1,109 @@ |
|||||
|
/*
|
||||
|
* Copyright 2019 Michael Tesch. All rights reserved. |
||||
|
* |
||||
|
* author(s): michael tesch (tesch1@gmail.com) |
||||
|
* |
||||
|
*/ |
||||
|
/*! \file bench_fmt.cpp
|
||||
|
* \brief benchmarking for formatting |
||||
|
* |
||||
|
* To disable freq scaling: |
||||
|
* cpupower frequency-set --governor performance |
||||
|
* to re-enable freq scaling: |
||||
|
* cpupower frequency-set --governor ondemand |
||||
|
*/ |
||||
|
|
||||
|
#include <benchmark/benchmark.h>
|
||||
|
#include <complex>
|
||||
|
#define CPPDUALS_LIBFMT
|
||||
|
#define CPPDUALS_LIBFMT_COMPLEX
|
||||
|
#include "duals/dual"
|
||||
|
|
||||
|
template <class T> void B_fmt_1(benchmark::State& state) { |
||||
|
T c(3.4); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
benchmark::DoNotOptimize(s = fmt::format("{}", c)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_ios_1(benchmark::State& state) { |
||||
|
T c(3.4); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
std::stringstream ss; |
||||
|
ss << c; |
||||
|
s = ss.str(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_fmt(benchmark::State& state) { |
||||
|
T c(3.4, 5.6); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
benchmark::DoNotOptimize(s = fmt::format("{}", c)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_fmt_g(benchmark::State& state) { |
||||
|
T c(3.4, 5.6); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
benchmark::DoNotOptimize(s = fmt::format("{:g}", c)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_fmt_star_g(benchmark::State& state) { |
||||
|
T c(3.4, 5.6); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
benchmark::DoNotOptimize(s = fmt::format("{:*g}", c)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_fmt_comma_g(benchmark::State& state) { |
||||
|
T c(3.4, 5.6); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
benchmark::DoNotOptimize(s = fmt::format("{:,g}", c)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <class T> void B_ios(benchmark::State& state) { |
||||
|
T c(3.4, 5.6); |
||||
|
for (auto _ : state) { |
||||
|
std::string s; |
||||
|
std::stringstream ss; |
||||
|
ss << c; |
||||
|
s = ss.str(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_fmt_1, float); |
||||
|
BENCHMARK_TEMPLATE(B_fmt_1, double); |
||||
|
BENCHMARK_TEMPLATE(B_ios_1, float); |
||||
|
BENCHMARK_TEMPLATE(B_ios_1, double); |
||||
|
BENCHMARK_TEMPLATE(B_fmt_g, std::complex<float>); |
||||
|
BENCHMARK_TEMPLATE(B_fmt_star_g, std::complex<float>); |
||||
|
BENCHMARK_TEMPLATE(B_fmt_comma_g, std::complex<float>); |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_fmt, std::complex<float>); |
||||
|
BENCHMARK_TEMPLATE(B_fmt, std::complex<double>); |
||||
|
BENCHMARK_TEMPLATE(B_fmt, duals::dual<float>); |
||||
|
BENCHMARK_TEMPLATE(B_fmt, duals::dual<double>); |
||||
|
|
||||
|
BENCHMARK_TEMPLATE(B_ios, std::complex<float>); |
||||
|
BENCHMARK_TEMPLATE(B_ios, std::complex<double>); |
||||
|
BENCHMARK_TEMPLATE(B_ios, duals::dual<float>); |
||||
|
BENCHMARK_TEMPLATE(B_ios, duals::dual<double>); |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
std::ios::sync_with_stdio(false); |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
::benchmark::Initialize(&argc, argv); |
||||
|
::benchmark::RunSpecifiedBenchmarks(); |
||||
|
} |
||||
@ -0,0 +1,244 @@ |
|||||
|
//===-- bench_gemm - benchmark dual m*m -----------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals Project
|
||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
#if defined(__APPLE__) && defined(__clang__)
|
||||
|
#include <Accelerate/Accelerate.h>
|
||||
|
|
||||
|
#else
|
||||
|
|
||||
|
#ifdef EIGEN_LAPACKE
|
||||
|
#include <Eigen/src/misc/lapacke.h>
|
||||
|
#else
|
||||
|
#include <lapacke.h>
|
||||
|
#endif
|
||||
|
|
||||
|
extern "C" { |
||||
|
//#include <cblas.h>
|
||||
|
//#include <cblas_openblas.h>
|
||||
|
#include CBLAS_HEADER
|
||||
|
} |
||||
|
#endif // defined(__APPLE__) && defined(__clang__)
|
||||
|
|
||||
|
#include <iostream>
|
||||
|
#include <fstream>
|
||||
|
#include <complex>
|
||||
|
#include <memory>
|
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Core>
|
||||
|
#include <Eigen/Dense>
|
||||
|
|
||||
|
#include "benchmark/benchmark.h"
|
||||
|
|
||||
|
using namespace duals; |
||||
|
|
||||
|
template< class T > struct type_identity { typedef T type; }; |
||||
|
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
|
||||
|
|
||||
|
/* encode the type into an integer for benchmark output */ |
||||
|
template<typename Tp> struct type_num { /* should fail */ }; |
||||
|
template<> struct type_num<float> { static constexpr int id = 1; }; |
||||
|
template<> struct type_num<double> { static constexpr int id = 2; }; |
||||
|
template<> struct type_num<long double> { static constexpr int id = 3; }; |
||||
|
template<typename Tp> struct type_num<std::complex<Tp>> { static constexpr int id = 10 + type_num<Tp>::id; }; |
||||
|
template<typename Tp> struct type_num<duals::dual<Tp>> { static constexpr int id = 100 + type_num<Tp>::id; }; |
||||
|
|
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
template <class T> using MatrixX = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>; |
||||
|
|
||||
|
#if 0
|
||||
|
#define V_RANGE(V,NF) ->Arg(V*4/NF)->Arg(V*32/NF)->Arg(V*256/NF)->Arg(V*2048/NF)->Arg(V*1)->Complexity()
|
||||
|
#else
|
||||
|
#define V_RANGE(V,NF) ->Arg(V*64/NF)->Arg(V*128/NF)->Arg(V*256/NF)->Arg(V*512/NF)->Arg(V*1024/NF) ->Arg(V*2048/NF)
|
||||
|
#endif
|
||||
|
|
||||
|
// measure Eigen's matrix-matrix multiplication
|
||||
|
template <class T, class U> void B_MatMat(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
typedef typename Eigen::ScalarBinaryOpTraits<T, U>::ReturnType R; |
||||
|
MatrixX<T> A = MatrixX<T>::Random(N, N); |
||||
|
MatrixX<U> B = MatrixX<U>::Random(N, N); |
||||
|
MatrixX<R> C = MatrixX<R>::Random(N, N); |
||||
|
for (auto _ : state) { |
||||
|
C.noalias() = A * B; |
||||
|
benchmark::ClobberMemory(); // Force c to be written to memory.
|
||||
|
} |
||||
|
|
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
template <class T, typename std::enable_if<!duals::is_dual<T>::value>::type* = nullptr> |
||||
|
void matrix_multiplcation(T *A, int Awidth, int Aheight, |
||||
|
T *B, int Bwidth, int Bheight, |
||||
|
T *AB, bool tA, bool tB, |
||||
|
typename type_identity<T>::type beta) |
||||
|
{ |
||||
|
int A_height = tA ? Awidth : Aheight; |
||||
|
int A_width = tA ? Aheight : Awidth; |
||||
|
#ifndef NDEBUG
|
||||
|
int B_height = tB ? Bwidth : Bheight; |
||||
|
#endif
|
||||
|
int B_width = tB ? Bheight : Bwidth; |
||||
|
int m = A_height; |
||||
|
int n = B_width; |
||||
|
int k = A_width; |
||||
|
// Error, width and height should match!
|
||||
|
assert(A_width == B_height); |
||||
|
int lda = tA ? m : k; |
||||
|
int ldb = tB ? k : n; |
||||
|
#define TRANSPOSE(X) ((X) ? CblasTrans : CblasNoTrans)
|
||||
|
// http://www.netlib.org/lapack/explore-html/d7/d2b/dgemm_8f.html
|
||||
|
if (!is_complex<T>::value) { |
||||
|
if (sizeof(T) == sizeof(float)) |
||||
|
cblas_sgemm(CblasColMajor, TRANSPOSE(tA), TRANSPOSE(tB), |
||||
|
m, n, k, 1.0, (float *)A, lda, (float *)B, ldb, |
||||
|
std::real(beta), (float *)AB, n); |
||||
|
else |
||||
|
cblas_dgemm(CblasColMajor, TRANSPOSE(tA), TRANSPOSE(tB), |
||||
|
m, n, k, 1.0, (double *)A, lda, (double *)B, ldb, |
||||
|
std::real(beta), (double *)AB, n); |
||||
|
} |
||||
|
else { |
||||
|
std::complex<float> alphaf(1,0); |
||||
|
std::complex<double> alpha(1,0); |
||||
|
if (Eigen::NumTraits<T>::digits10() < 10) |
||||
|
cblas_cgemm(CblasColMajor, TRANSPOSE(tA), TRANSPOSE(tB), |
||||
|
m, n, k, &alphaf, A, lda, B, ldb, &beta, AB, n); |
||||
|
else |
||||
|
cblas_zgemm(CblasColMajor, TRANSPOSE(tA), TRANSPOSE(tB), |
||||
|
m, n, k, &alpha, A, lda, B, ldb, &beta, AB, n); |
||||
|
} |
||||
|
#undef TRANSPOSE
|
||||
|
} |
||||
|
|
||||
|
template <class T, typename std::enable_if<duals::is_dual<T>::value>::type* = nullptr> |
||||
|
void matrix_multiplcation(T *A, int Awidth, int Aheight, |
||||
|
T *B, int Bwidth, int Bheight, |
||||
|
T *AB, bool tA, bool tB, |
||||
|
typename type_identity<T>::type beta) |
||||
|
{ /* nothing */ |
||||
|
} |
||||
|
|
||||
|
// measure BLAS matrix-matrix multiplication
|
||||
|
template <class Rt> void B_MatMatBLAS(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> B = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> C = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> D = A*B; |
||||
|
for (auto _ : state) { |
||||
|
matrix_multiplcation(A.data(), A.cols(), A.rows(), |
||||
|
B.data(), B.cols(), B.rows(), |
||||
|
C.data(), false, false, (Rt)0.); |
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
|
||||
|
double err = (double)rpart((D - C).norm() / D.norm()); |
||||
|
if (err > 1e-6) |
||||
|
state.SkipWithError("BLAS matmat error"); |
||||
|
|
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure compiler's matrix-matrix multiplication
|
||||
|
template <class Rt, class U> void B_MatMatCXX(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
std::vector<Rt> a(N*N); |
||||
|
std::vector<Rt> b(N*N); |
||||
|
std::vector<Rt> c(N*N); |
||||
|
|
||||
|
for (auto _ : state) { |
||||
|
state.PauseTiming(); |
||||
|
a.assign(N*N,1.1); |
||||
|
b.assign(N*N,2.2); |
||||
|
c.assign(N*N,0.); |
||||
|
state.ResumeTiming(); |
||||
|
|
||||
|
for(int i=0; i<N; ++i) |
||||
|
for(int j=0; j<N; ++j) |
||||
|
for(int k=0; k<N; ++k) |
||||
|
c[i*N+j] += a[i*N+k] * b[k*N+j]; |
||||
|
|
||||
|
benchmark::ClobberMemory(); // Force a to be written to memory.
|
||||
|
} |
||||
|
|
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
// measure eigen's matrix-vector multiplication
|
||||
|
template <class Rt, class U> void B_MatVec(benchmark::State& state) { |
||||
|
int N = state.range(0); |
||||
|
MatrixX<Rt> A = MatrixX<Rt>::Random(N, N); |
||||
|
MatrixX<Rt> b = MatrixX<Rt>::Random(N, 1); |
||||
|
MatrixX<Rt> c = MatrixX<Rt>::Random(N, 1); |
||||
|
for (auto _ : state) { |
||||
|
c = A * b; |
||||
|
benchmark::ClobberMemory(); |
||||
|
} |
||||
|
|
||||
|
state.counters["type"] = type_num<Rt>::id; |
||||
|
state.SetComplexityN(state.range(0)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#define MAKE_BM_SIMPLE(TYPE1,TYPE2,NF) \
|
||||
|
BENCHMARK_TEMPLATE(B_MatMat, TYPE1,TYPE2) V_RANGE(1,NF) |
||||
|
|
||||
|
#define MAKE_BENCHMARKS(TYPE1,TYPE2,NF) \
|
||||
|
MAKE_BM_SIMPLE(TYPE1,TYPE2,NF); \ |
||||
|
BENCHMARK_TEMPLATE(B_MatMatBLAS, TYPE1) V_RANGE(1,NF) |
||||
|
|
||||
|
// BENCHMARK_TEMPLATE(B_MatMatBLAS, TYPE1) V_RANGE(1,2*NF);
|
||||
|
// BENCHMARK_TEMPLATE(B_VecVecMulCXX, TYPE1,TYPE2) V_RANGE(4,NF);
|
||||
|
// BENCHMARK_TEMPLATE(B_MatMatCXX, TYPE1,TYPE2) V_RANGE(1,NF);
|
||||
|
|
||||
|
MAKE_BENCHMARKS(float, float, 1); |
||||
|
MAKE_BENCHMARKS(complexf, complexf,2); |
||||
|
//MAKE_BM_SIMPLE(dualf, float,2); TODO
|
||||
|
MAKE_BM_SIMPLE(dualf, dualf,2); |
||||
|
//MAKE_BM_SIMPLE(cdualf, cdualf,2);
|
||||
|
MAKE_BM_SIMPLE(cdualf, cdualf,4); |
||||
|
|
||||
|
#if HAVE_BOOST
|
||||
|
#include <audi/audi.hpp>
|
||||
|
MAKE_BM_SIMPLE(audi::gdual<float>,2); |
||||
|
#endif
|
||||
|
|
||||
|
// novelty:
|
||||
|
//MAKE_BM_SIMPLE(float, complexf,2);
|
||||
|
//MAKE_BM_SIMPLE(complexf, float,2);
|
||||
|
|
||||
|
MAKE_BENCHMARKS(double, double, 1); |
||||
|
MAKE_BENCHMARKS(complexd, complexd,2); |
||||
|
MAKE_BM_SIMPLE(duald, duald,2); |
||||
|
MAKE_BM_SIMPLE(cduald, cduald,4); |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char** argv) |
||||
|
{ |
||||
|
#ifndef EIGEN_VECTORIZE
|
||||
|
static_assert(false, "no vectorization?"); |
||||
|
#endif
|
||||
|
#ifndef NDEBUG
|
||||
|
static_assert(false, "NDEBUG to benchmark?"); |
||||
|
#endif
|
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::benchmark::Initialize(&argc, argv); |
||||
|
::benchmark::RunSpecifiedBenchmarks(); |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
//===-- example.cpp - examples of using <duals/dual> -------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file example.cpp Dual number usage examples |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#if defined(PHASE_1)
|
||||
|
#include <duals/dual>
|
||||
|
|
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
template <class T> T f(T x) { return pow(x,pow(x,x)); } |
||||
|
template <class T> T df(T x) { return pow(x,-1. + x + pow(x,x)) * (1. + x*log(x) + x*pow(log(x),2.)); } |
||||
|
template <class T> T ddf(T x) { return (pow(x,pow(x,x)) * pow(pow(x,x - 1.) + pow(x,x)*log(x)*(log(x) + 1.), 2.) + |
||||
|
pow(x,pow(x,x)) * (pow(x,x - 1.) * log(x) + |
||||
|
pow(x,x - 1.) * (log(x) + 1.) + |
||||
|
pow(x,x - 1.) * ((x - 1.)/x + log(x)) + |
||||
|
pow(x,x) * log(x) * pow(log(x) + 1., 2.) )); } |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
std::cout << " f(2.) = " << f(2.) << "\n"; |
||||
|
std::cout << " df(2.) = " << df(2.) << "\n"; |
||||
|
std::cout << "ddf(2.) = " << ddf(2.) << "\n"; |
||||
|
std::cout << " f(2+1_e) = " << f(2+1_e) << "\n"; |
||||
|
std::cout << " f(2+1_e).dpart() = " << f(2+1_e).dpart() << "\n"; |
||||
|
duals::hyperduald x(2+1_e,1+0_e); |
||||
|
std::cout << " f((2+1_e) + (1+0_e)_e).dpart().dpart() = " << f(x).dpart().dpart() << "\n"; |
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -0,0 +1,472 @@ |
|||||
|
{ |
||||
|
"context": { |
||||
|
"date": "2019-04-09 23:10:32", |
||||
|
"host_name": "riick.fritz.box", |
||||
|
"executable": "./tests/bench_dual", |
||||
|
"num_cpus": 8, |
||||
|
"mhz_per_cpu": 4200, |
||||
|
"cpu_scaling_enabled": true, |
||||
|
"caches": [ |
||||
|
{ |
||||
|
"type": "Data", |
||||
|
"level": 1, |
||||
|
"size": 32000000, |
||||
|
"num_sharing": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"type": "Instruction", |
||||
|
"level": 1, |
||||
|
"size": 32000000, |
||||
|
"num_sharing": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"type": "Unified", |
||||
|
"level": 2, |
||||
|
"size": 256000000, |
||||
|
"num_sharing": 2 |
||||
|
}, |
||||
|
{ |
||||
|
"type": "Unified", |
||||
|
"level": 3, |
||||
|
"size": 8192000000, |
||||
|
"num_sharing": 8 |
||||
|
} |
||||
|
], |
||||
|
"load_avg": [0.91,0.55,0.49], |
||||
|
"library_build_type": "debug" |
||||
|
}, |
||||
|
"benchmarks": [ |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/2", |
||||
|
"run_name": "B_Add<duals::dualf>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 824542173, |
||||
|
"real_time": 8.4453082668102275e-01, |
||||
|
"cpu_time": 8.4330497549941574e-01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/8", |
||||
|
"run_name": "B_Add<duals::dualf>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 215407779, |
||||
|
"real_time": 3.3351862932159380e+00, |
||||
|
"cpu_time": 3.3321200252475562e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/64", |
||||
|
"run_name": "B_Add<duals::dualf>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 58354344, |
||||
|
"real_time": 1.2061169807457697e+01, |
||||
|
"cpu_time": 1.2049604618980897e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/512", |
||||
|
"run_name": "B_Add<duals::dualf>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 7147541, |
||||
|
"real_time": 9.8321614102488141e+01, |
||||
|
"cpu_time": 9.8233268476529204e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/4096", |
||||
|
"run_name": "B_Add<duals::dualf>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 583950, |
||||
|
"real_time": 1.1997066478428608e+03, |
||||
|
"cpu_time": 1.1986074835174250e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<duals::dualf>/8192", |
||||
|
"run_name": "B_Add<duals::dualf>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 280278, |
||||
|
"real_time": 2.5014722955172806e+03, |
||||
|
"cpu_time": 2.4990253212881489e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/2", |
||||
|
"run_name": "B_Add<std::complex<float>>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 719322979, |
||||
|
"real_time": 9.6203674730458488e-01, |
||||
|
"cpu_time": 9.6122821067280295e-01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/8", |
||||
|
"run_name": "B_Add<std::complex<float>>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 208022307, |
||||
|
"real_time": 3.3676157142748866e+00, |
||||
|
"cpu_time": 3.3648201247955565e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/64", |
||||
|
"run_name": "B_Add<std::complex<float>>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 41387591, |
||||
|
"real_time": 1.6822550362762875e+01, |
||||
|
"cpu_time": 1.6808160639260215e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/512", |
||||
|
"run_name": "B_Add<std::complex<float>>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 5437243, |
||||
|
"real_time": 1.2896090977804755e+02, |
||||
|
"cpu_time": 1.2885078338415281e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/4096", |
||||
|
"run_name": "B_Add<std::complex<float>>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 583456, |
||||
|
"real_time": 1.2011305840153541e+03, |
||||
|
"cpu_time": 1.2000171855289859e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Add<std::complex<float>>/8192", |
||||
|
"run_name": "B_Add<std::complex<float>>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 281308, |
||||
|
"real_time": 2.5101460142166443e+03, |
||||
|
"cpu_time": 2.5074422056962462e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/2", |
||||
|
"run_name": "B_Sub<duals::dualf>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 728551981, |
||||
|
"real_time": 9.6308006466451668e-01, |
||||
|
"cpu_time": 9.6223501587047333e-01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/8", |
||||
|
"run_name": "B_Sub<duals::dualf>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 242708995, |
||||
|
"real_time": 2.8970816594436135e+00, |
||||
|
"cpu_time": 2.8945758520404290e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/64", |
||||
|
"run_name": "B_Sub<duals::dualf>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 42881747, |
||||
|
"real_time": 1.6390650175399376e+01, |
||||
|
"cpu_time": 1.6376361322219417e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/512", |
||||
|
"run_name": "B_Sub<duals::dualf>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 5463762, |
||||
|
"real_time": 1.2839805814698460e+02, |
||||
|
"cpu_time": 1.2829124383529179e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/4096", |
||||
|
"run_name": "B_Sub<duals::dualf>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 579043, |
||||
|
"real_time": 1.2007505781594916e+03, |
||||
|
"cpu_time": 1.1996460815518028e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<duals::dualf>/8192", |
||||
|
"run_name": "B_Sub<duals::dualf>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 283021, |
||||
|
"real_time": 2.4547645685559423e+03, |
||||
|
"cpu_time": 2.4523946138272386e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/2", |
||||
|
"run_name": "B_Sub<std::complex<float>>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 828173889, |
||||
|
"real_time": 8.4244681131040999e-01, |
||||
|
"cpu_time": 8.4170307016284329e-01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/8", |
||||
|
"run_name": "B_Sub<std::complex<float>>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 224061326, |
||||
|
"real_time": 3.1243714855868139e+00, |
||||
|
"cpu_time": 3.1216511010025840e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/64", |
||||
|
"run_name": "B_Sub<std::complex<float>>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 58141628, |
||||
|
"real_time": 1.2089688595827512e+01, |
||||
|
"cpu_time": 1.2079371891684870e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/512", |
||||
|
"run_name": "B_Sub<std::complex<float>>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 7040996, |
||||
|
"real_time": 9.9699899139357910e+01, |
||||
|
"cpu_time": 9.9613642160853260e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/4096", |
||||
|
"run_name": "B_Sub<std::complex<float>>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 581668, |
||||
|
"real_time": 1.2034631524593226e+03, |
||||
|
"cpu_time": 1.2022905179586996e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Sub<std::complex<float>>/8192", |
||||
|
"run_name": "B_Sub<std::complex<float>>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 282164, |
||||
|
"real_time": 2.4708674956039085e+03, |
||||
|
"cpu_time": 2.4684340667129668e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/2", |
||||
|
"run_name": "B_Mul<duals::dualf>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 265558620, |
||||
|
"real_time": 2.6450566357631402e+00, |
||||
|
"cpu_time": 2.6427702102082029e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/8", |
||||
|
"run_name": "B_Mul<duals::dualf>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 223502135, |
||||
|
"real_time": 3.1301059652276355e+00, |
||||
|
"cpu_time": 3.1273447656327855e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/64", |
||||
|
"run_name": "B_Mul<duals::dualf>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 30377857, |
||||
|
"real_time": 2.3107029109224477e+01, |
||||
|
"cpu_time": 2.3087210891801917e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/512", |
||||
|
"run_name": "B_Mul<duals::dualf>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 3753884, |
||||
|
"real_time": 1.8687841100299300e+02, |
||||
|
"cpu_time": 1.8672708799739081e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/4096", |
||||
|
"run_name": "B_Mul<duals::dualf>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 461567, |
||||
|
"real_time": 1.5087395958443526e+03, |
||||
|
"cpu_time": 1.5074006547261827e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<duals::dualf>/8192", |
||||
|
"run_name": "B_Mul<duals::dualf>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 229621, |
||||
|
"real_time": 3.0899390212718718e+03, |
||||
|
"cpu_time": 3.0867818709961157e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/2", |
||||
|
"run_name": "B_Mul<std::complex<float>>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 46285967, |
||||
|
"real_time": 1.5099909223178337e+01, |
||||
|
"cpu_time": 1.5086400139377007e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/8", |
||||
|
"run_name": "B_Mul<std::complex<float>>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 11661962, |
||||
|
"real_time": 6.0014554242011371e+01, |
||||
|
"cpu_time": 5.9962549440651621e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/64", |
||||
|
"run_name": "B_Mul<std::complex<float>>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 1468536, |
||||
|
"real_time": 4.7647983704918062e+02, |
||||
|
"cpu_time": 4.7608059795605925e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/512", |
||||
|
"run_name": "B_Mul<std::complex<float>>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 183082, |
||||
|
"real_time": 3.8213512741184391e+03, |
||||
|
"cpu_time": 3.8181861133262651e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/4096", |
||||
|
"run_name": "B_Mul<std::complex<float>>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 22675, |
||||
|
"real_time": 3.0901148974846190e+04, |
||||
|
"cpu_time": 3.0871022888643743e+04, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Mul<std::complex<float>>/8192", |
||||
|
"run_name": "B_Mul<std::complex<float>>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 11344, |
||||
|
"real_time": 6.1823873857552790e+04, |
||||
|
"cpu_time": 6.1759684238363785e+04, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/2", |
||||
|
"run_name": "B_Div<duals::dualf>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 223074129, |
||||
|
"real_time": 3.1221121030774452e+00, |
||||
|
"cpu_time": 3.1193331432888822e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/8", |
||||
|
"run_name": "B_Div<duals::dualf>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 206899949, |
||||
|
"real_time": 3.3619264062599843e+00, |
||||
|
"cpu_time": 3.3588176041551177e+00, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/64", |
||||
|
"run_name": "B_Div<duals::dualf>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 29041803, |
||||
|
"real_time": 2.3762771511892577e+01, |
||||
|
"cpu_time": 2.3742337485038277e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/512", |
||||
|
"run_name": "B_Div<duals::dualf>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 3605971, |
||||
|
"real_time": 1.9516093806834385e+02, |
||||
|
"cpu_time": 1.9498607337663077e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/4096", |
||||
|
"run_name": "B_Div<duals::dualf>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 412656, |
||||
|
"real_time": 1.7029046954383241e+03, |
||||
|
"cpu_time": 1.7012804781706957e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<duals::dualf>/8192", |
||||
|
"run_name": "B_Div<duals::dualf>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 199214, |
||||
|
"real_time": 3.5068666004871179e+03, |
||||
|
"cpu_time": 3.5033117702571099e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/2", |
||||
|
"run_name": "B_Div<std::complex<float>>/2", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 38292924, |
||||
|
"real_time": 1.8300814009951591e+01, |
||||
|
"cpu_time": 1.8285078308462527e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/8", |
||||
|
"run_name": "B_Div<std::complex<float>>/8", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 9592683, |
||||
|
"real_time": 7.3376013778254773e+01, |
||||
|
"cpu_time": 7.3309770269694255e+01, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/64", |
||||
|
"run_name": "B_Div<std::complex<float>>/64", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 1196541, |
||||
|
"real_time": 5.8431534145313731e+02, |
||||
|
"cpu_time": 5.8382388986252840e+02, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/512", |
||||
|
"run_name": "B_Div<std::complex<float>>/512", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 150056, |
||||
|
"real_time": 4.6825903796710227e+03, |
||||
|
"cpu_time": 4.6785734792344165e+03, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/4096", |
||||
|
"run_name": "B_Div<std::complex<float>>/4096", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 18718, |
||||
|
"real_time": 3.7536350839790939e+04, |
||||
|
"cpu_time": 3.7500307404637017e+04, |
||||
|
"time_unit": "ns" |
||||
|
}, |
||||
|
{ |
||||
|
"name": "B_Div<std::complex<float>>/8192", |
||||
|
"run_name": "B_Div<std::complex<float>>/8192", |
||||
|
"run_type": "iteration", |
||||
|
"iterations": 9342, |
||||
|
"real_time": 7.4837835688738924e+04, |
||||
|
"cpu_time": 7.4762648469278734e+04, |
||||
|
"time_unit": "ns" |
||||
|
} |
||||
|
] |
||||
|
} |
||||
1160
src/include/cppduals/tests/gold-riick.bench_eigen.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,142 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
|
||||
|
# |
||||
|
# run benchmarks - |
||||
|
# |
||||
|
|
||||
|
CMDLINE="$0 $@" |
||||
|
SCRIPT=$(basename "$0") |
||||
|
SRCDIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
||||
|
OnError() { |
||||
|
echo "$SCRIPT: Error on line ${BASH_LINENO[0]}, exiting." |
||||
|
exit 1 |
||||
|
} |
||||
|
trap OnError ERR |
||||
|
|
||||
|
HOSTTAG=$(hostname | cut -d . -f 1) |
||||
|
VERBOSE=1 |
||||
|
GOLDBASE="$SRCDIR/gold-${HOSTTAG}" |
||||
|
BENCH_LIST= |
||||
|
BENCH_ARGS= |
||||
|
MAKE_ARGS= |
||||
|
TAG= |
||||
|
|
||||
|
usage () { |
||||
|
if [ -t 3 ]; then echo "$SCRIPT failed, see log" >&3 ; fi |
||||
|
cat <<EOF |
||||
|
usage: |
||||
|
${SCRIPT} <benchmarks> [options...] |
||||
|
|
||||
|
where <benchmarks> are [bench_eigen|bench_dual] |
||||
|
|
||||
|
where [options...] are: |
||||
|
-g|--makegold - save ouput to the 'gold' file standard location |
||||
|
-T|--tag <tag> - add tag to results file [$TAG] |
||||
|
-t|--test <test> - filter benchmark tests against <test> [*] |
||||
|
-o|--output <base> - output file name base [$OUTFILE] |
||||
|
-f|--fast - run fast, at the great expense of accurate measurement |
||||
|
-m|--medium - run medium fast, at the medium expense of accurate measurement |
||||
|
-v|--verbose - be more verbose (can add multiple times) |
||||
|
-q|--quiet - be more quiet (can add multiple times) |
||||
|
-h|--help - print this usage message and exit |
||||
|
|
||||
|
current bench1 args: ${BENCH_ARGS} |
||||
|
EOF |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
# process command line args |
||||
|
while [ $# -gt 0 ]; do |
||||
|
key="$1" |
||||
|
case $key in |
||||
|
-g|--makegold) OUTFILE="$GOLDBASE" ;; |
||||
|
-T|--tag) TAG="-$2" ; shift ;; |
||||
|
-o|--output) OUTFILE="$2"; shift ;; |
||||
|
-t|--test) |
||||
|
BENCH_ARGS="${BENCH_ARGS} --benchmark_filter=$2" |
||||
|
shift |
||||
|
;; |
||||
|
-f|--fast) |
||||
|
BENCH_ARGS="${BENCH_ARGS} --benchmark_min_time=0.001" |
||||
|
;; |
||||
|
-m|--medium) |
||||
|
BENCH_ARGS="${BENCH_ARGS} --benchmark_min_time=0.05" |
||||
|
;; |
||||
|
-h|help) usage ;; |
||||
|
-v|--verbose) |
||||
|
VERBOSE=$(( VERBOSE + 1 )) |
||||
|
MAKE_ARGS="${MAKE_ARGS} VERBOSE=1" |
||||
|
;; |
||||
|
-q|--quiet) VERBOSE=$(( VERBOSE - 1 )) ;; |
||||
|
*) |
||||
|
if [ -f "${SRCDIR}/${key}.cpp" ]; then |
||||
|
BENCH_LIST="${BENCH_LIST} ${key}" |
||||
|
shift |
||||
|
continue |
||||
|
fi |
||||
|
# unknown option |
||||
|
echo "unknown option $key" |
||||
|
usage |
||||
|
;; |
||||
|
esac |
||||
|
shift |
||||
|
done |
||||
|
|
||||
|
# default |
||||
|
if [ -z "${BENCH_LIST}" ]; then |
||||
|
BENCH_LIST=bench_dual |
||||
|
fi |
||||
|
|
||||
|
BENCH_ARGS="${BENCH_ARGS} --benchmark_out_format=json" |
||||
|
ret=0 |
||||
|
for NAME in ${BENCH_LIST}; do |
||||
|
GOLDFILE=${GOLDBASE}.${NAME}${TAG}.json |
||||
|
TMPFILE=$(mktemp ./bench.XXXXXXXXX) |
||||
|
|
||||
|
# if there's no gold reference yet, by default create one |
||||
|
if [ -z "$OUTFILE" ]; then |
||||
|
if [ ! -f "$GOLDFILE" ]; then |
||||
|
echo "No gold file found, creating one..." |
||||
|
REALOUT=$GOLDFILE |
||||
|
else |
||||
|
REALOUT=bo-${NAME}${TAG}.json |
||||
|
fi |
||||
|
else |
||||
|
REALOUT=${OUTFILE}.${NAME}${TAG}.json |
||||
|
fi |
||||
|
|
||||
|
|
||||
|
BENCH_ARGS="${BENCH_ARGS} --benchmark_out=${TMPFILE}" |
||||
|
#BENCH_ARGS="${BENCH_ARGS} --benchmark_counters_tabular=true" |
||||
|
#BENCH_ARGS="${BENCH_ARGS} --benchmark_repetitions=1000" |
||||
|
|
||||
|
echo "GOLDFILE=$GOLDFILE" |
||||
|
echo "TMPFILE =$TMPFILE" |
||||
|
echo "OUTFILE =$OUTFILE" |
||||
|
echo "REALOUT =$REALOUT" |
||||
|
echo "Making ${NAME}${TAG} $MAKE_ARGS" |
||||
|
make -j4 "${NAME}" $MAKE_ARGS |
||||
|
|
||||
|
echo "Running benchmarks: ./tests/${NAME} $BENCH_ARGS" |
||||
|
#echo " : output in ${NAME}.out" |
||||
|
if ! ./tests/${NAME} $BENCH_ARGS ; then |
||||
|
echo "failed $NAME" |
||||
|
ret=1 |
||||
|
continue |
||||
|
fi |
||||
|
|
||||
|
if [ "${REALOUT}" != "$TMPFILE" ]; then |
||||
|
mv "$TMPFILE" "${REALOUT}" |
||||
|
fi |
||||
|
|
||||
|
if [ "${REALOUT}" != "$GOLDFILE" ]; then |
||||
|
echo "comparing with $GOLDFILE" |
||||
|
./thirdparty/benchmarkX/src/benchmarkX/tools/compare.py benchmarks "$GOLDFILE" "${REALOUT}" |
||||
|
fi |
||||
|
|
||||
|
#./thirdparty/benchmarkX/src/benchmarkX/tools/compare.py filters ./bench_eigen B_Pade B_Expm |
||||
|
|
||||
|
echo "Benchmark ouput in '${REALOUT}'" |
||||
|
done |
||||
|
|
||||
|
exit $ret |
||||
@ -0,0 +1,122 @@ |
|||||
|
//===-- test_dual.cpp - test duals/dual -------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals Project
|
||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* just a place to play around and get dirty. |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include <math.h>
|
||||
|
#include <iostream>
|
||||
|
#include <iomanip>
|
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
|
||||
|
using std::cout; |
||||
|
using std::cerr; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
typedef std::complex<hyperdualf> chyperdualf; |
||||
|
|
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int P=N> using emtx = Eigen::Matrix<eT, N, P>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int P=N> using ecf = Eigen::Matrix<complexf, N, P> ; |
||||
|
template <int N=2, int P=N> using edf = Eigen::Matrix<dualf, N, P> ; |
||||
|
template <int N=2, int P=N> using ecdf = Eigen::Matrix<cdualf, N, P> ; |
||||
|
#define PO_EXPR_TYPE(...) typename std::decay<decltype( __VA_ARGS__ )>::type::PlainObject
|
||||
|
|
||||
|
|
||||
|
template <class T = int> |
||||
|
class Rando { T x; }; |
||||
|
|
||||
|
struct Randa { int x; }; |
||||
|
|
||||
|
namespace std { |
||||
|
template <class T> |
||||
|
struct common_type<Rando<T>,T> { typedef Rando<T> type; }; |
||||
|
} |
||||
|
|
||||
|
#if 0
|
||||
|
|
||||
|
int main(int argc, char * argv[]) |
||||
|
{ |
||||
|
emtx<cduald,50> A,B,C; |
||||
|
//emtx<complexd,50> A,B,C;
|
||||
|
C = A * B; |
||||
|
} |
||||
|
|
||||
|
#elif 0
|
||||
|
int main(int argc, char * argv[]) |
||||
|
{ |
||||
|
typedef double T; |
||||
|
T h(T(1) / (1ull << (std::numeric_limits<T>::digits / 3))); |
||||
|
#define func erfc
|
||||
|
for (double x = 0; x < 4; x += .21) { |
||||
|
std::cout << " erf(" << x << ") = " << func (x) << " , =" << (func (x+h)- func (x))/h << "\n"; |
||||
|
std::cout << "d(erf" << x << ") = " << func (x + 1_e) << "\n"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#else
|
||||
|
|
||||
|
template <class T> T f(T x) { return pow(x,pow(x,x)); } |
||||
|
template <class T> T df(T x) { return pow(x,-1 + x + pow(x,x)) * (1 + x*log(x) + x*pow(log(x),2)); } |
||||
|
template <class T> T ddf(T x) { return (pow(x,pow(x,x)) * pow(pow(x,x - 1) + pow(x,x)*log(x)*(log(x) + 1), 2) + |
||||
|
pow(x,pow(x,x)) * (pow(x,x - 1) * log(x) + |
||||
|
pow(x,x - 1) * (log(x) + 1) + |
||||
|
pow(x,x - 1) * ((x - 1)/x + log(x)) + |
||||
|
pow(x,x) * log(x) * pow(log(x) + 1, 2) )); } |
||||
|
int main(int argc, char * argv[]) |
||||
|
{ |
||||
|
dualf h; |
||||
|
dualf xx(1); |
||||
|
hyperdualf y; |
||||
|
hyperdualf w(1); |
||||
|
hyperdualf z(xx,h); |
||||
|
hyperdualf a(xx); |
||||
|
emtx<double> ed; |
||||
|
emtx<float> ef; |
||||
|
emtx<complexd> ecd; |
||||
|
emtx<complexf> ecf_; |
||||
|
emtx<duald> edd; |
||||
|
emtx<dualf,2> edf_; |
||||
|
emtx<cduald> ecdd; |
||||
|
emtx<cdualf> ecdf_; |
||||
|
|
||||
|
std::cout << " f(2.) = " << f(2.) << "\n"; |
||||
|
std::cout << " df(2.) = " << df(2.) << "\n"; |
||||
|
std::cout << "ddf(2.) = " << ddf(2.) << "\n"; |
||||
|
std::cout << " f(2+1_e) = " << f(2+1_e) << "\n"; |
||||
|
std::cout << " f(2+1_e).dpart() = " << f(2+1_e).dpart() << "\n"; |
||||
|
|
||||
|
duals::hyperduald x(2+1_e,1+0_e); |
||||
|
std::cout << " f((2+1_e) + (1+0_e)_e).dpart().dpart() = " << f(x).dpart().dpart() << "\n"; |
||||
|
std::cout << " c((2+1_e) + (1+0_e)_e).dpart().dpart() = " << cbrt(x).dpart().dpart() << "\n"; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
#endif
|
||||
@ -0,0 +1,208 @@ |
|||||
|
//===-- test_1.cpp - test duals/dual ------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_eigen Dual number Eigen integration tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <fstream>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
#include <unsupported/Eigen/AutoDiff>
|
||||
|
#include "eexpokit/padm.hpp"
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
/// Simple taylor series, truncated when |S| is "small enough"
|
||||
|
template <class DerivedA, typename ReturnT = typename DerivedA::PlainObject> |
||||
|
ReturnT |
||||
|
expm4(const Eigen::EigenBase<DerivedA> & A_, |
||||
|
typename DerivedA::RealScalar mn |
||||
|
= std::numeric_limits<typename DerivedA::RealScalar>::epsilon() * 10 |
||||
|
//= 1.L/(1ull << (std::numeric_limits<typename DerivedA::RealScalar>::digits / 3))
|
||||
|
) |
||||
|
{ |
||||
|
//std::cerr << "do PO:" << type_name<typename DerivedA::PlainObject>() << "\n";
|
||||
|
typedef typename DerivedA::RealScalar Real; |
||||
|
using std::isfinite; |
||||
|
using std::pow; |
||||
|
const DerivedA & A = A_.derived(); |
||||
|
int maxt = std::numeric_limits<Real>::digits; |
||||
|
int s = (int)log2(rpart(A.derived().norm())) + 1; |
||||
|
s = std::max(0, s); |
||||
|
|
||||
|
auto B = A * pow(Real(2), -s); |
||||
|
ReturnT R(A.rows(), A.cols()); |
||||
|
R.setIdentity(); |
||||
|
R += B; |
||||
|
ReturnT S = B; |
||||
|
int ni = 0; |
||||
|
for (int ii = 2; ii < maxt; ii++) { |
||||
|
ni++; |
||||
|
S = Real(1.0/ii) * S * B; |
||||
|
R += S; |
||||
|
auto Sn = S.norm(); |
||||
|
if (!isfinite(Sn)) { |
||||
|
std::cout << "expm() non-finite norm:" << Sn << " at " << ii << "\n"; |
||||
|
std::cout << " |R| = " << R.norm() << " s=" << s << "\n" |
||||
|
<< " |A| = " << rpart(A.real().norm()) << "\n" |
||||
|
<< " |A/2^s|=" << rpart(A.real().norm()/pow(2,s)) << "\n"; |
||||
|
break; |
||||
|
} |
||||
|
// converged yet?
|
||||
|
if (Sn < mn) |
||||
|
break; |
||||
|
if (ii == maxt - 1) { |
||||
|
std::cout << "expm() didn't converge in " << maxt << " |S| = " << Sn << "\n"; |
||||
|
throw std::invalid_argument("no converge"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//int ss = s;
|
||||
|
for (; s; s--) |
||||
|
R = R * R; |
||||
|
//std::cout << "expm s=" << ss << " ni=" << ni << " tol=" << mn << " |S|= " << S.norm() << "\n";
|
||||
|
return R; |
||||
|
} |
||||
|
|
||||
|
template <class T, int NN = 30, class DT = dual<T> > |
||||
|
void dexpm() { |
||||
|
//typedef std::complex<float> T;
|
||||
|
//typedef std::complex<dual<T>> dualt;
|
||||
|
T tol = NN * NN * 1000 * Eigen::NumTraits<T>::epsilon(); |
||||
|
|
||||
|
#define N2 2*NN
|
||||
|
|
||||
|
// check dual
|
||||
|
emtx<T,NN> A = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> V = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> dA1,dA2,dA3,eA1,eA2,eA3,C; |
||||
|
|
||||
|
// dA/dV method 1
|
||||
|
emtx<T,N2> AVA = emtx<T,N2>::Zero(); |
||||
|
AVA.block( 0, 0,NN,NN) = A; |
||||
|
AVA.block( 0,NN,NN,NN) = V; |
||||
|
AVA.block(NN,NN,NN,NN) = A; |
||||
|
AVA = AVA.exp(); |
||||
|
//AVA = eexpokit::padm(AVA,13);
|
||||
|
eA1 = AVA.block(0,0,NN,NN); |
||||
|
dA1 = AVA.block(0,NN,NN,NN); |
||||
|
|
||||
|
// dA/dV method 2
|
||||
|
emtx<DT, NN> a,b,c; |
||||
|
a = A + DT(0,1) * V; |
||||
|
b = expm4(a); |
||||
|
// TODO: find a second trustworthy expm function, padm() and a.exp()
|
||||
|
// arent reliable here.
|
||||
|
//c = eexpokit::padm(a,13);
|
||||
|
//C = eexpokit::padm(A,13);
|
||||
|
//c = a.exp();
|
||||
|
eA2 = rpart(b); |
||||
|
dA2 = dpart(b); |
||||
|
|
||||
|
eA3 = rpart(c); |
||||
|
dA3 = dpart(c); |
||||
|
#if 0
|
||||
|
std::ofstream A_(type_name<T>().str() + std::to_string(NN) + "A.dat"); |
||||
|
A_ << A; |
||||
|
std::ofstream V_(type_name<T>().str() + std::to_string(NN) + "V.dat"); |
||||
|
V_ << V; |
||||
|
|
||||
|
std::ofstream _(type_name<T>().str() + std::to_string(NN) + "_.dat"); |
||||
|
_ << "A=" << A << "\n"; |
||||
|
_ << "V=" << V << "\n"; |
||||
|
_ << "eA1=" << eA1 << "\n"; |
||||
|
_ << "dA1=" << dA1 << "\n"; |
||||
|
//_ << "a=" << a << "\n";
|
||||
|
_ << "b=" << b << "\n"; |
||||
|
_ << "c=" << c << "\n"; |
||||
|
_ << "C=" << C << "\n"; |
||||
|
|
||||
|
std::cout << "a:" << type_name<decltype(a)>() << "\n"; |
||||
|
#endif
|
||||
|
EXPECT_LT((eA1 - eA2).norm(), tol) << "eA1=" << eA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "eA2=" << eA2.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "b=" << b.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
EXPECT_LT((dA1 - dA2).norm(), tol) << "dA1=" << dA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "dA2=" << dA2.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "b=" << b.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
#if 0 // see above.
|
||||
|
EXPECT_LT((eA1 - eA3).norm(), tol) << "eA1=" << eA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "eA3=" << eA3.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "c=" << c.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
EXPECT_LT((dA1 - dA3).norm(), tol) << "dA1=" << dA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "dA3=" << dA3.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "c=" << c.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
#if defined(PHASE_1)
|
||||
|
|
||||
|
TEST(dexpm, float2) { dexpm<float,2>(); } |
||||
|
TEST(dexpm, float4) { dexpm<float,4>(); } |
||||
|
|
||||
|
#elif defined(PHASE_2)
|
||||
|
|
||||
|
TEST(dexpm, double2) { dexpm<double,2>(); } |
||||
|
TEST(dexpm, double4) { dexpm<double,4>(); } |
||||
|
|
||||
|
#endif
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::ptrdiff_t l1, l2, l3; |
||||
|
Eigen::internal::manage_caching_sizes(Eigen::GetAction, &l1, &l2, &l3); |
||||
|
|
||||
|
std::cout << "l1=" << l1 << " l2=" << l2 << " l3=" << l3 << "\n"; |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
1108
src/include/cppduals/tests/test_dual.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,549 @@ |
|||||
|
//===-- test_funcs.cpp - test duals/dual ------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_eigen Dual number Eigen integration tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
//#include <unsupported/Eigen/AutoDiff>
|
||||
|
#include "eexpokit/padm.hpp"
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
#define EXPECT_DEQ(A,B) EXPECT_EQ(rpart(A), rpart(B)); EXPECT_EQ(dpart(A), dpart(B))
|
||||
|
#define ASSERT_DEQ(A,B) ASSERT_EQ(rpart(A), rpart(B)); ASSERT_EQ(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNE(A,B) EXPECT_NE(rpart(A), rpart(B)); EXPECT_NE(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNEAR(A,B,tol) \
|
||||
|
EXPECT_NEAR(rpart(A), rpart(B),tol); \ |
||||
|
EXPECT_NEAR(dpart(A), dpart(B),tol) |
||||
|
|
||||
|
/// Simple taylor series, truncated when |S| is "small enough"
|
||||
|
template <class DerivedA, typename ReturnT = typename DerivedA::PlainObject> |
||||
|
ReturnT |
||||
|
expm4(const Eigen::EigenBase<DerivedA> & A_, |
||||
|
typename DerivedA::RealScalar mn = std::numeric_limits<typename DerivedA::RealScalar>::epsilon() * 1000) |
||||
|
{ |
||||
|
//std::cerr << "do PO:" << type_name<typename DerivedA::PlainObject>() << "\n";
|
||||
|
typedef typename DerivedA::RealScalar Real; |
||||
|
using std::isfinite; |
||||
|
const DerivedA & A = A_.derived(); |
||||
|
int maxt = std::numeric_limits<Real>::digits; |
||||
|
int s = log2(rpart(A.derived().norm())) + 1; |
||||
|
s = std::max(0, s); |
||||
|
|
||||
|
auto B = A * pow(Real(2), -s); |
||||
|
ReturnT R(A.rows(), A.cols()); |
||||
|
R.setIdentity(); |
||||
|
R += B; |
||||
|
ReturnT S = B; |
||||
|
for (int ii = 2; ii < maxt; ii++) { |
||||
|
S = S * B * Real(1.0/ii); |
||||
|
R += S; |
||||
|
auto Sn = S.norm(); |
||||
|
if (!isfinite(Sn)) { |
||||
|
std::cout << "expm() non-finite norm:" << Sn << " at " << ii << "\n"; |
||||
|
std::cout << " |R| = " << R.norm() << " s=" << s << "\n" |
||||
|
<< " |A| = " << rpart(A.real().norm()) << "\n" |
||||
|
<< " |A/2^s|=" << rpart(A.real().norm()/pow(2,s)) << "\n"; |
||||
|
break; |
||||
|
} |
||||
|
// converged yet?
|
||||
|
if (Sn < mn) |
||||
|
break; |
||||
|
if (ii == maxt - 1) { |
||||
|
std::cout << "expm() didn't converge in " << maxt << " |S| = " << Sn << "\n"; |
||||
|
throw std::invalid_argument("no converge"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (; s; s--) |
||||
|
R = R * R; |
||||
|
return R; |
||||
|
} |
||||
|
|
||||
|
TEST(Eigen, NumTraits) { |
||||
|
//::testing::StaticAssertTypeEq<Eigen::NumTraits<duals::dual<float>>::Real, float>();
|
||||
|
_EXPECT_TRUE(std::is_same<typename Eigen::NumTraits<duals::dual<float>>::Real, dualf>); |
||||
|
_EXPECT_TRUE(std::is_same<typename Eigen::NumTraits<cdualf>::Real, dualf>); |
||||
|
|
||||
|
EXPECT_EQ(Eigen::NumTraits<duals::dual<float>>::dummy_precision(), |
||||
|
Eigen::NumTraits<float>::dummy_precision()); |
||||
|
EXPECT_EQ(Eigen::NumTraits<duals::dual<float>>::digits10(), |
||||
|
Eigen::NumTraits<float>::digits10()); |
||||
|
|
||||
|
EXPECT_EQ(Eigen::NumTraits<cdualf>::dummy_precision(), |
||||
|
Eigen::NumTraits<float>::dummy_precision()); |
||||
|
} |
||||
|
|
||||
|
TEST(Eigen, construction) |
||||
|
{ |
||||
|
emtx<double> ed; |
||||
|
emtx<float> ef; |
||||
|
emtx<complexd> ecd; |
||||
|
emtx<complexf> ecf; |
||||
|
emtx<duald> edd; |
||||
|
emtx<dualf> edf_; |
||||
|
emtx<cduald> ecdd; |
||||
|
emtx<cdualf> ecdf_; |
||||
|
} |
||||
|
|
||||
|
TEST(Eigen, sparse) |
||||
|
{ |
||||
|
smtx<double> ed; |
||||
|
smtx<float> ef; |
||||
|
smtx<complexd> ecd; |
||||
|
smtx<complexf> ecf; |
||||
|
smtx<duald> edd; |
||||
|
smtx<dualf> edf_; |
||||
|
smtx<cduald> ecdd; |
||||
|
smtx<cdualf> ecdf_; |
||||
|
} |
||||
|
|
||||
|
TEST(Eigen, expr_type_dense) { |
||||
|
emtx<double> ed; |
||||
|
emtx<float> ef; |
||||
|
emtx<complexd> ecd; |
||||
|
emtx<complexf> ecf; |
||||
|
emtx<duald> edd; |
||||
|
emtx<dualf> edf_; |
||||
|
emtx<cduald> ecdd; |
||||
|
emtx<cdualf> ecdf_; |
||||
|
|
||||
|
//_EXPECT_TRUE(std::is_base_of<Eigen::EigenBase<U>,U >::value);
|
||||
|
|
||||
|
//_EXPECT_TRUE(std::is_same<std::common_type<emtx<dualf>,dualf>::type, emtx<dualf>>);
|
||||
|
ecf = ecf * 1; |
||||
|
#define PO_EXPR_TYPE(...) typename std::decay<decltype( __VA_ARGS__ )>::type::PlainObject
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf*1), emtx<complexf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf + ecf), emtx<complexf>>); |
||||
|
//_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf * edf_), emtx<cdualf>>); [1]
|
||||
|
//_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf * 1_ef), emtx<cdualf>>); [1]
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf * cdualf(1,2)), emtx<cdualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edf_ * 2), emtx<dualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edf_ * cdualf(2,2)), emtx<cdualf>>); |
||||
|
static_assert(!duals::can_promote<dualf, emtx<dualf>>::value, "nope"); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edf_ * 2_ef), emtx<dualf>>); |
||||
|
//_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edf_ * 2_e), emtx<duald>>);
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecf * complexf(1,2)), emtx<complexf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecdf_ * 1), emtx<cdualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecdf_ * 2_ef), emtx<cdualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecdf_ * complexf(1,2)), emtx<cdualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ecdf_ * cdualf(1_ef,2_ef)), emtx<cdualf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edd * 1_e), emtx<duald>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(edd * 1_ef), emtx<duald>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(ed*1), emtx<double>>); |
||||
|
|
||||
|
auto a1 = ecf * 1; |
||||
|
auto a2 = ecf * ecf; |
||||
|
//auto a3 = ecf * edf_; [1]
|
||||
|
//auto a4 = ecf * 1_ef; [1]
|
||||
|
auto a5 = ecf * cdualf(1,2); |
||||
|
auto a6 = edf_ * 2; |
||||
|
auto a7 = edf_ * 2_ef; |
||||
|
auto a8 = ecf * complexf(1,2); |
||||
|
auto a9 = ecdf_ * 1; |
||||
|
ecdf_ = ecdf_ * complexf(1,2); |
||||
|
ecdf_ = ecdf_ * cdualf(1_ef,2_ef); |
||||
|
auto a12 = edd * 1_e; |
||||
|
auto a13 = ed * 1; |
||||
|
auto A1 = a1.eval(); A1 += A1; |
||||
|
auto A2 = a2.eval(); A2 += A2; |
||||
|
//auto A3 = a3.eval(); A3 += A3; [1]
|
||||
|
//auto A4 = a4.eval(); A4 += A4; [1]
|
||||
|
auto A5 = a5.eval(); A5 += A5; |
||||
|
auto A6 = a6.eval(); A6 += A6; |
||||
|
auto A7 = a7.eval(); A7 += A7; |
||||
|
auto A8 = a8.eval(); A8 += A8; |
||||
|
auto A9 = a9.eval(); A9 += A9; |
||||
|
auto A12 = a12.eval(); A12 += A12; |
||||
|
auto A13 = a13.eval(); A13 += A13; |
||||
|
} |
||||
|
|
||||
|
TEST(init, Constant) { |
||||
|
edf<3> a = edf<3>::Constant(3,3, 5 + 8_ef); |
||||
|
ecdf<3> b = ecdf<3>::Constant(3,3, cdualf(4,2 + 3_ef)); |
||||
|
|
||||
|
EXPECT_EQ(a(1,1), 5 + 8_ef); |
||||
|
EXPECT_EQ(b(0,1), cdualf(4,2 + 3_ef)); |
||||
|
EXPECT_TRUE((a.array() < 6).all()); |
||||
|
EXPECT_FALSE((a.array() != 5 + 8_ef).any()); |
||||
|
EXPECT_EQ((a.array() == 5 + 8_ef).count(), 9); |
||||
|
} |
||||
|
|
||||
|
TEST(init, setIdentity) { |
||||
|
edf<3> a = edf<3>::Constant(3,3, 5 + 8_ef); |
||||
|
ecdf<3> b = ecdf<3>::Constant(3,3, cdualf(4,2 + 3_ef)); |
||||
|
a.setIdentity(); |
||||
|
b.setIdentity(); |
||||
|
|
||||
|
EXPECT_EQ(a(0,0), 1); |
||||
|
EXPECT_EQ(a(0,1), 0); |
||||
|
EXPECT_EQ(a(0,2), 0); |
||||
|
EXPECT_EQ(a(1,0), 0); |
||||
|
EXPECT_EQ(a(1,1), 1); |
||||
|
EXPECT_EQ(a(1,2), 0); |
||||
|
EXPECT_EQ(a(2,0), 0); |
||||
|
EXPECT_EQ(a(2,1), 0); |
||||
|
EXPECT_EQ(a(2,2), 1); |
||||
|
|
||||
|
EXPECT_EQ(b(0,0).real(), 1); |
||||
|
EXPECT_EQ(b(0,1).real(), 0); |
||||
|
EXPECT_EQ(b(0,2).real(), 0); |
||||
|
EXPECT_EQ(b(1,0).real(), 0); |
||||
|
EXPECT_EQ(b(1,1).real(), 1); |
||||
|
EXPECT_EQ(b(1,2).real(), 0); |
||||
|
EXPECT_EQ(b(2,0).real(), 0); |
||||
|
EXPECT_EQ(b(2,1).real(), 0); |
||||
|
EXPECT_EQ(b(2,2).real(), 1); |
||||
|
} |
||||
|
|
||||
|
TEST(init, setZero) { |
||||
|
edf<3> a = edf<3>::Constant(3,3, 5 + 8_ef); |
||||
|
ecdf<3> b = ecdf<3>::Constant(3,3, cdualf(4,2 + 3_ef)); |
||||
|
|
||||
|
EXPECT_EQ(a(1,1), 5 + 8_ef); |
||||
|
|
||||
|
a.setZero(); |
||||
|
b.setZero(); |
||||
|
|
||||
|
EXPECT_EQ(a(0,0), 0); |
||||
|
EXPECT_EQ(a(0,1), 0); |
||||
|
EXPECT_EQ(a(0,2), 0); |
||||
|
EXPECT_EQ(a(1,0), 0); |
||||
|
EXPECT_EQ(a(1,1), 0); |
||||
|
EXPECT_EQ(a(1,2), 0); |
||||
|
EXPECT_EQ(a(2,0), 0); |
||||
|
EXPECT_EQ(a(2,1), 0); |
||||
|
EXPECT_EQ(a(2,2), 0); |
||||
|
|
||||
|
EXPECT_EQ(b(0,0).real(), 0); |
||||
|
EXPECT_EQ(b(0,1).real(), 0); |
||||
|
EXPECT_EQ(b(0,2).real(), 0); |
||||
|
EXPECT_EQ(b(1,0).real(), 0); |
||||
|
EXPECT_EQ(b(1,1).real(), 0); |
||||
|
EXPECT_EQ(b(1,2).real(), 0); |
||||
|
EXPECT_EQ(b(2,0).real(), 0); |
||||
|
EXPECT_EQ(b(2,1).real(), 0); |
||||
|
EXPECT_EQ(b(2,2).real(), 0); |
||||
|
EXPECT_EQ(b(0,0).imag(), 0); |
||||
|
EXPECT_EQ(b(0,1).imag(), 0); |
||||
|
EXPECT_EQ(b(0,2).imag(), 0); |
||||
|
EXPECT_EQ(b(1,0).imag(), 0); |
||||
|
EXPECT_EQ(b(1,1).imag(), 0); |
||||
|
EXPECT_EQ(b(1,2).imag(), 0); |
||||
|
EXPECT_EQ(b(2,0).imag(), 0); |
||||
|
EXPECT_EQ(b(2,1).imag(), 0); |
||||
|
EXPECT_EQ(b(2,2).imag(), 0); |
||||
|
} |
||||
|
|
||||
|
TEST(init, LinSpaced) { |
||||
|
ecf<3,1> a = ecf<3,1>::LinSpaced(3, 4, complexf(6,7)); |
||||
|
EXPECT_EQ(a(0).real(), 4); |
||||
|
EXPECT_EQ(a(1).real(), 5); |
||||
|
EXPECT_EQ(a(2).real(), 6); |
||||
|
|
||||
|
edf<3,1> b = edf<3,1>::LinSpaced(3, 4, 6 + 6_ef); |
||||
|
EXPECT_EQ(b(0), 4); |
||||
|
EXPECT_EQ(b(1), 5 + 3_ef); |
||||
|
EXPECT_EQ(b(2), 6 + 6_ef); |
||||
|
} |
||||
|
|
||||
|
TEST(init, Random) { |
||||
|
complexf c = emtx<complexf,1>::Random()(0,0); |
||||
|
EXPECT_NE(c.real(), 0); |
||||
|
EXPECT_NE(c.imag(), 0); |
||||
|
|
||||
|
typedef dualf Rt; |
||||
|
using duals::random; |
||||
|
|
||||
|
Rt b = emtx<Rt,1>::Random()(0,0); |
||||
|
EXPECT_NE(b.rpart(), 0); |
||||
|
//EXPECT_NE(b.dpart(), 0); //
|
||||
|
|
||||
|
edf<3> j = edf<3>::Random(3,3); |
||||
|
EXPECT_NE(j(1,2).rpart(), 0); |
||||
|
//EXPECT_NE(j(2,0).dpart(), 0); //
|
||||
|
|
||||
|
ecdf<3> k = ecdf<3>::Random(3,3); |
||||
|
EXPECT_NE(k(0,1).real().rpart(), 0); |
||||
|
//EXPECT_NE(k(1,1).imag().dpart(), 0); //
|
||||
|
|
||||
|
using duals::randos::random2; |
||||
|
dualf x = random2<dualf>(); |
||||
|
EXPECT_NE(x.rpart(), 0); |
||||
|
EXPECT_NE(x.dpart(), 0); |
||||
|
|
||||
|
duald y = random2<duald>(); |
||||
|
EXPECT_NE(y.rpart(), 0); |
||||
|
EXPECT_NE(y.dpart(), 0); |
||||
|
|
||||
|
//EXPECT_NE(k(1,1).imag().dpart(), 0); //
|
||||
|
} |
||||
|
|
||||
|
TEST(assign, ops) { |
||||
|
emtx<double> ed; |
||||
|
emtx<float> ef; |
||||
|
emtx<complexd> ecd; |
||||
|
emtx<complexf> ecf; |
||||
|
emtx<duald> edd; |
||||
|
emtx<dualf> edf_; |
||||
|
emtx<cduald> ecdd; |
||||
|
emtx<cdualf> ecdf_; |
||||
|
|
||||
|
ed *= 2; |
||||
|
ef *= 2; |
||||
|
|
||||
|
//ecd *= 2;
|
||||
|
//ecf *= 2;
|
||||
|
//ecd *= 2_e;
|
||||
|
//ecf *= 2_ef;
|
||||
|
|
||||
|
edd *= 2; |
||||
|
edf_ *= 2; |
||||
|
edd *= 2_e; |
||||
|
edf_ *= 2_ef; |
||||
|
//ecdd *= 2;
|
||||
|
// ecdf_ *= 2;
|
||||
|
} |
||||
|
|
||||
|
TEST(Array, math) { |
||||
|
int N = 5; |
||||
|
|
||||
|
emtx<float> x(N,1); |
||||
|
emtx<float> y(N,1); |
||||
|
emtx<float> z(N,1); |
||||
|
|
||||
|
x.array() += 1; |
||||
|
x += y + z; |
||||
|
x *= 2; |
||||
|
|
||||
|
emtx<duald> a(N,1); |
||||
|
emtx<duald> A(N,1); |
||||
|
emtx<duald> c(N,1); |
||||
|
a.array() = 1 + 1_e; |
||||
|
a.array() += 3_e; |
||||
|
a.array() = 0; |
||||
|
a.array() += 1; |
||||
|
A.array() += 2; |
||||
|
c = a + A; |
||||
|
c = a * 2; |
||||
|
c = a * 2_e; |
||||
|
c = 2 * a; |
||||
|
c = (3 + 2_e) * a; |
||||
|
c *= 3; |
||||
|
c *= 3_e; |
||||
|
EXPECT_EQ(c(N-1), 27_e); |
||||
|
} |
||||
|
|
||||
|
TEST(access, CwiseRpartOp) { |
||||
|
// on float matrices (pass-through)
|
||||
|
emtx<float,3> a, b = emtx<float,3>::Random(); |
||||
|
a = b.unaryExpr(duals::CwiseRpartOp<float>()); |
||||
|
EXPECT_NE(a.norm(), 0); |
||||
|
|
||||
|
// on dual<float> matrices
|
||||
|
emtx<dualf,3> d; |
||||
|
a = d.unaryExpr(duals::CwiseRpartOp<dualf>()); |
||||
|
a = d.unaryExpr(duals::CwiseDpartOp<dualf>()); |
||||
|
a = rpart(d); |
||||
|
a = dpart(d); |
||||
|
|
||||
|
// on complex<dual<float>> matrices
|
||||
|
emtx<complexf,3> g, f = emtx<complexf,3>::Random(); |
||||
|
emtx<cdualf,3> e; |
||||
|
e.array() = f.array().cast<cdualf>() - 1_ef * f.array().cast<cdualf>(); |
||||
|
g = e.unaryExpr(duals::CwiseRpartOp<cdualf>()); |
||||
|
EXPECT_EQ((f-g).norm(), 0); |
||||
|
g = f.unaryExpr(duals::CwiseRpartOp<complexf>()); |
||||
|
EXPECT_EQ((f-g).norm(), 0); |
||||
|
g = rpart(f); |
||||
|
EXPECT_EQ((f-g).norm(), 0); |
||||
|
|
||||
|
g = e.unaryExpr(duals::CwiseDpartOp<cdualf>()); |
||||
|
EXPECT_EQ((f+g).norm(), 0); |
||||
|
g = f.unaryExpr(duals::CwiseDpartOp<complexf>()); |
||||
|
EXPECT_EQ((g).norm(), 0); |
||||
|
g = dpart(f); |
||||
|
EXPECT_EQ((g).norm(), 0); |
||||
|
} |
||||
|
|
||||
|
TEST(access, CwiseDpartOp) { |
||||
|
// on float matrices (pass-through)
|
||||
|
emtx<float,3> a, b = emtx<float,3>::Random(); |
||||
|
a = b.unaryExpr(duals::CwiseDpartOp<float>()); |
||||
|
EXPECT_EQ(a.norm(), 0); |
||||
|
|
||||
|
// on dual<float> matrices
|
||||
|
emtx<dualf,3> d = b - 1_ef * b; |
||||
|
a = d.unaryExpr(duals::CwiseDpartOp<dualf>()); |
||||
|
EXPECT_NE(a.norm(), 0); |
||||
|
EXPECT_EQ((a+b).norm(), 0); |
||||
|
|
||||
|
// on complex<dual<float>> matrices
|
||||
|
emtx<complexf,3> g, f = emtx<complexf,3>::Random(); |
||||
|
emtx<cdualf,3> e; |
||||
|
e.array() = f.array().cast<cdualf>() - 1_ef * f.array().cast<cdualf>(); |
||||
|
|
||||
|
g = e.unaryExpr(duals::CwiseDpartOp<cdualf>()); |
||||
|
EXPECT_EQ((g+f).norm(), 0); |
||||
|
d = e.real(); |
||||
|
EXPECT_NE(d.norm(), 0); |
||||
|
} |
||||
|
|
||||
|
TEST(measure, norm) { |
||||
|
typedef emtx<complexf, 3> MatrixC; |
||||
|
MatrixC c = (MatrixC() << 1,2,3, 4,5,6, 7,8,9).finished(); |
||||
|
|
||||
|
EXPECT_EQ(c.cwiseAbs().colwise().sum().maxCoeff(), complexf(18)); |
||||
|
//EXPECT_EQ(c.maxCoeff(), complexf(9));
|
||||
|
|
||||
|
//typedef duald Rt;
|
||||
|
typedef dualf Rt; |
||||
|
//typedef cdualf Rt;
|
||||
|
typedef emtx<Rt, 3> MatrixD; |
||||
|
Rt b = 1+0_ef; |
||||
|
b = 3; |
||||
|
Rt d(1); |
||||
|
MatrixD x; |
||||
|
x << d; |
||||
|
MatrixD a = (MatrixD() << 1,2,3, 4,5+5_ef,6, 7,8,9).finished(); |
||||
|
//typename MatrixD::Index index;
|
||||
|
|
||||
|
EXPECT_EQ(a.sum(), 45 + 5_ef); |
||||
|
EXPECT_NEAR(rpart(a.norm()), 16.8819430161341337282, 1e-5); |
||||
|
EXPECT_NEAR(rpart(a.mean()), 5, 1e-5); |
||||
|
EXPECT_NEAR(dpart(a.mean()), 0.555555555555555, 1e-5); |
||||
|
EXPECT_EQ(a.minCoeff(), 1); |
||||
|
EXPECT_EQ(a.maxCoeff(), 9); |
||||
|
EXPECT_EQ(a.trace(), 15 + 5_ef); |
||||
|
EXPECT_EQ(a.squaredNorm(), 285+0_e); |
||||
|
EXPECT_EQ(a.lpNorm<1>(), 45 + 5_ef); |
||||
|
//EXPECT_EQ(a.lpNorm<Eigen::Infinity>(), 9);
|
||||
|
// 1-norm
|
||||
|
//EXPECT_EQ(a.colwise().lpNorm<1>().maxCoeff(), 45 + 5_ef);
|
||||
|
EXPECT_EQ(a.cwiseAbs().colwise().sum().maxCoeff(), 18); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
TEST(dual_decay, stat) { |
||||
|
emtx<float> ef; |
||||
|
emtx<complexd> ecd; |
||||
|
emtx<complexf> ecf; |
||||
|
emtx<duald> edd; |
||||
|
emtx<dualf> edf_; |
||||
|
emtx<cduald> ecdd; |
||||
|
emtx<cdualf> ecdf_; |
||||
|
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(rpart(ef)), emtx<float>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(dpart(ef)), emtx<float>>); |
||||
|
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(rpart(edf_)), emtx<float>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(dpart(edf_)), emtx<float>>); |
||||
|
|
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(rpart(ecdf_)), emtx<complexf>>); |
||||
|
_EXPECT_TRUE(std::is_same<PO_EXPR_TYPE(dpart(ecdf_)), emtx<complexf>>); |
||||
|
} |
||||
|
|
||||
|
TEST(dpart, matrix) { |
||||
|
emtx<float,3> a = emtx<float,3>::Random(3,3); |
||||
|
emtx<float,3> b = emtx<float,3>::Random(3,3); |
||||
|
emtx<float,3> c = emtx<float,3>::Random(3,3); |
||||
|
emtx<float,3> d = emtx<float,3>::Random(3,3); |
||||
|
emtx<dualf,3> A = a + 1_ef * b; |
||||
|
emtx<dualf,3> B = c + 1_ef * d; |
||||
|
emtx<cdualf,3> AA; |
||||
|
emtx<complexf,3> BB,CC; |
||||
|
AA.real() = A; |
||||
|
AA.imag() = B; |
||||
|
BB.real() = a; |
||||
|
BB.imag() = c; |
||||
|
CC.real() = b; |
||||
|
CC.imag() = d; |
||||
|
|
||||
|
EXPECT_EQ((rpart(A) - a).norm(),0); |
||||
|
EXPECT_EQ((dpart(A) - b).norm(),0); |
||||
|
|
||||
|
EXPECT_EQ((rpart(AA) - BB).norm(),0); |
||||
|
EXPECT_EQ((dpart(AA) - CC).norm(),0); |
||||
|
} |
||||
|
|
||||
|
TEST(func, expm) { |
||||
|
typedef float T; |
||||
|
typedef dual<T> dualt; |
||||
|
typedef std::complex<dual<T>> cdualt; |
||||
|
#define NN 3
|
||||
|
#define N2 6
|
||||
|
emtx<dualt, NN> a,b; |
||||
|
a = emtx<dualt, NN>::Random(); |
||||
|
a.array() += 1.1 + 2.2_ef; |
||||
|
a.setZero(); |
||||
|
a = eexpokit::padm(a); |
||||
|
EXPECT_LT((a - emtx<dualt, NN>::Identity()).norm(), 1e-6) << "a=" << a << "\n"; |
||||
|
a *= 1+2_e; |
||||
|
EXPECT_LT((a - emtx<dualt, NN>::Identity()).norm(), 1e-6) << "a=" << a << "\n"; |
||||
|
|
||||
|
emtx<cdualt, NN> c; |
||||
|
//b = a + 1_e * emtx<cdualf, 3>::Random();
|
||||
|
c.setZero(); |
||||
|
c = c.exp(); |
||||
|
//c = expm4(c);
|
||||
|
EXPECT_LT((c - emtx<cdualf, NN>::Identity()).norm(), 1e-6) << "b=" << b << "\n"; |
||||
|
#undef NN
|
||||
|
#undef N2
|
||||
|
} |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,215 @@ |
|||||
|
//===-- test_funcs.cpp - test duals/dual ------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_eigen Dual number Eigen integration tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
#include <unsupported/Eigen/AutoDiff>
|
||||
|
#include "eexpokit/padm.hpp"
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
#define EXPECT_DEQ(A,B) EXPECT_EQ(rpart(A), rpart(B)); EXPECT_EQ(dpart(A), dpart(B))
|
||||
|
#define ASSERT_DEQ(A,B) ASSERT_EQ(rpart(A), rpart(B)); ASSERT_EQ(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNE(A,B) EXPECT_NE(rpart(A), rpart(B)); EXPECT_NE(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNEAR(A,B,tol) \
|
||||
|
EXPECT_NEAR(rpart(A), rpart(B),tol); \ |
||||
|
EXPECT_NEAR(dpart(A), dpart(B),tol) |
||||
|
|
||||
|
/// Simple taylor series, truncated when |S| is "small enough"
|
||||
|
template <class DerivedA, typename ReturnT = typename DerivedA::PlainObject> |
||||
|
ReturnT |
||||
|
expm4(const Eigen::EigenBase<DerivedA> & A_, |
||||
|
typename DerivedA::RealScalar mn = std::numeric_limits<typename DerivedA::RealScalar>::epsilon() * 1000) |
||||
|
{ |
||||
|
//std::cerr << "do PO:" << type_name<typename DerivedA::PlainObject>() << "\n";
|
||||
|
typedef typename DerivedA::RealScalar Real; |
||||
|
using std::isfinite; |
||||
|
const DerivedA & A = A_.derived(); |
||||
|
int maxt = std::numeric_limits<Real>::digits; |
||||
|
int s = log2(rpart(A.derived().norm())) + 1; |
||||
|
s = std::max(0, s); |
||||
|
|
||||
|
auto B = A * pow(Real(2), -s); |
||||
|
ReturnT R(A.rows(), A.cols()); |
||||
|
R.setIdentity(); |
||||
|
R += B; |
||||
|
ReturnT S = B; |
||||
|
for (int ii = 2; ii < maxt; ii++) { |
||||
|
S = S * B * Real(1.0/ii); |
||||
|
R += S; |
||||
|
auto Sn = S.norm(); |
||||
|
if (!isfinite(Sn)) { |
||||
|
std::cout << "expm() non-finite norm:" << Sn << " at " << ii << "\n"; |
||||
|
std::cout << " |R| = " << R.norm() << " s=" << s << "\n" |
||||
|
<< " |A| = " << rpart(A.real().norm()) << "\n" |
||||
|
<< " |A/2^s|=" << rpart(A.real().norm()/pow(2,s)) << "\n"; |
||||
|
break; |
||||
|
} |
||||
|
// converged yet?
|
||||
|
if (Sn < mn) |
||||
|
break; |
||||
|
if (ii == maxt - 1) { |
||||
|
std::cout << "expm() didn't converge in " << maxt << " |S| = " << Sn << "\n"; |
||||
|
throw std::invalid_argument("no converge"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (; s; s--) |
||||
|
R = R * R; |
||||
|
return R; |
||||
|
} |
||||
|
|
||||
|
template <class T, int NN = 30, class DT = dual<T> > |
||||
|
void dexpm() { |
||||
|
//typedef std::complex<float> T;
|
||||
|
//typedef std::complex<dual<T>> dualt;
|
||||
|
auto tol = NN * NN * 10000 * Eigen::NumTraits<T>::epsilon(); |
||||
|
|
||||
|
#define N2 2*NN
|
||||
|
|
||||
|
// check dual
|
||||
|
emtx<T,NN> A = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> V = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> dA1,dA2,dA3,eA1,eA2,eA3; |
||||
|
|
||||
|
// dA/dV method 1
|
||||
|
emtx<T,N2> AVA = emtx<T,N2>::Zero(); |
||||
|
AVA.block( 0, 0,NN,NN) = A; |
||||
|
AVA.block( 0,NN,NN,NN) = V; |
||||
|
AVA.block(NN,NN,NN,NN) = A; |
||||
|
AVA = AVA.exp(); |
||||
|
eA1 = AVA.block(0,0,NN,NN); |
||||
|
dA1 = AVA.block(0,NN,NN,NN); |
||||
|
|
||||
|
// dA/dV method 2
|
||||
|
emtx<DT, NN> a,b; |
||||
|
a = A + DT(1_e) * V; |
||||
|
b = eexpokit::padm(a,13); |
||||
|
//b = expm4(a);
|
||||
|
//b = a.exp();
|
||||
|
eA2 = rpart(b); |
||||
|
dA2 = dpart(b); |
||||
|
|
||||
|
#if 0
|
||||
|
// dA/dV method 3
|
||||
|
//typedef Eigen::AutoDiffScalar<emtx<T,NN>> AD;
|
||||
|
typedef Eigen::Matrix<T,1,1> Vector1t; |
||||
|
typedef Eigen::AutoDiffScalar<Vector1t> AD; |
||||
|
typedef Eigen::Matrix<AD,NN,NN> MatrixAD; |
||||
|
//MatrixAD c = A.template cast<AD>();
|
||||
|
MatrixAD c(A); |
||||
|
for (Eigen::Index j = 0; j < NN; j++) |
||||
|
for (Eigen::Index i = 0; i < NN; i++) |
||||
|
c(i,j).derivatives()(0) = V(i,j); |
||||
|
//auto d = eexpokit::padm(c,8);
|
||||
|
MatrixAD d = c.exp(); |
||||
|
eA3 = d; |
||||
|
for (Eigen::Index j = 0; j < NN; j++) |
||||
|
for (Eigen::Index i = 0; i < NN; i++) |
||||
|
dA3(i,j) = d(i,j).derivatives()(0); |
||||
|
|
||||
|
EXPECT_LT((dA1 - dA3).norm(), tol) << "dA1=" << dA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "dA3=" << dA3.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
#endif
|
||||
|
|
||||
|
#if 0
|
||||
|
std::cout << "A=" << A << "\n"; |
||||
|
std::cout << "V=" << V << "\n"; |
||||
|
std::cout << "a=" << a << "\n"; |
||||
|
std::cout << "b=" << b << "\n"; |
||||
|
#endif
|
||||
|
EXPECT_LT((eA1 - eA2).norm(), tol) << "eA1=" << eA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "eA2=" << eA2.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
EXPECT_LT((dA1 - dA2).norm(), tol) << "dA1=" << dA1.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n" |
||||
|
<< "dA2=" << dA2.block(0,0,std::min(4,NN),std::min(4,NN)) << "\n"; |
||||
|
#undef NN
|
||||
|
#undef N2
|
||||
|
} |
||||
|
|
||||
|
#if defined(PHASE_1)
|
||||
|
|
||||
|
TEST(dexpm, float2) { dexpm<float,2>(); } |
||||
|
//TEST(dexpm, float3) { dexpm<float,3>(); }
|
||||
|
TEST(dexpm, float7) { dexpm<float,7>(); } |
||||
|
|
||||
|
#elif defined(PHASE_2)
|
||||
|
|
||||
|
TEST(dexpm, float8) { dexpm<float,8>(); } |
||||
|
//TEST(dexpm, float16) { dexpm<float,16>(); }
|
||||
|
TEST(dexpm, float31) { dexpm<float,31>(); } |
||||
|
|
||||
|
#elif defined(PHASE_3)
|
||||
|
|
||||
|
TEST(dexpm, double2) { dexpm<double,2>(); } |
||||
|
TEST(dexpm, double3) { dexpm<double,3>(); } |
||||
|
|
||||
|
#elif defined(PHASE_4)
|
||||
|
|
||||
|
TEST(dexpm, double4) { dexpm<double,4>(); } |
||||
|
TEST(dexpm, double31) { dexpm<double,31>(); } |
||||
|
//TEST(dexpm, adouble) { dexpm<double, adouble>(); }
|
||||
|
|
||||
|
#elif defined(PHASE_5)
|
||||
|
|
||||
|
TEST(dexpm, cfloat8) { dexpm<complexf,8,cdualf>(); } |
||||
|
TEST(dexpm, cfloat31) { dexpm<complexf,31,cdualf>(); } |
||||
|
|
||||
|
#endif
|
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,213 @@ |
|||||
|
//===-- test_dual.cpp - test duals/dual -------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_dual Dual number libfmt formatting tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
#include <fmt/format.h>
|
||||
|
#define CPPDUALS_LIBFMT
|
||||
|
#define CPPDUALS_LIBFMT_COMPLEX
|
||||
|
#include <duals/dual>
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
using namespace duals::literals; |
||||
|
using namespace std::complex_literals; |
||||
|
|
||||
|
TEST(libfmt, complex_) { |
||||
|
std::string s = fmt::format("{}", 2.f + 3if); |
||||
|
EXPECT_EQ(s, "(2.0+3.0if)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_el) { |
||||
|
std::string s = fmt::format("{}", 2.l + 3il); |
||||
|
EXPECT_EQ(s, "(2.0+3.0il)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_flags) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("{}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(2.0+3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:$}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(2.0+3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:*}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(2.0+3.0*i)"); |
||||
|
|
||||
|
s = fmt::format("{:,}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(2.0,3.0)"); |
||||
|
|
||||
|
// + +
|
||||
|
s = fmt::format("{:$+}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(+2.0+3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:*+}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(+2.0+3.0*i)"); |
||||
|
|
||||
|
s = fmt::format("{:,+}", 2. + 3i); |
||||
|
EXPECT_EQ(s, "(+2.0,+3.0)"); |
||||
|
|
||||
|
// + -
|
||||
|
s = fmt::format("{:$+}", 2. - 3i); |
||||
|
EXPECT_EQ(s, "(+2.0-3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:*+}", 2. - 3i); |
||||
|
EXPECT_EQ(s, "(+2.0-3.0*i)"); |
||||
|
|
||||
|
s = fmt::format("{:,+}", 2. - 3i); |
||||
|
EXPECT_EQ(s, "(+2.0,-3.0)"); |
||||
|
|
||||
|
} |
||||
|
TEST(libfmt, complex_all_real) { |
||||
|
std::string s; |
||||
|
s = fmt::format("{}", 2. + 0i); |
||||
|
EXPECT_EQ(s, "(2.0)"); |
||||
|
|
||||
|
s = fmt::format("{:*}", 2. + 0i); |
||||
|
EXPECT_EQ(s, "(2.0)"); |
||||
|
|
||||
|
s = fmt::format("{:,}", 2. + 0i); |
||||
|
EXPECT_EQ(s, "(2.0,0.0)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_all_imag) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("{}", 0. + 3i); |
||||
|
EXPECT_EQ(s, "(3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:*}", 0. + 3i); |
||||
|
EXPECT_EQ(s, "(3.0*i)"); |
||||
|
|
||||
|
s = fmt::format("{:,}", 0. + 3i); |
||||
|
EXPECT_EQ(s, "(0.0,3.0)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_plus) { |
||||
|
std::string s = fmt::format("{:+}", 1. + 3i); |
||||
|
EXPECT_EQ(s, "(+1.0+3.0i)"); |
||||
|
|
||||
|
s = fmt::format("{:+}", 1. - 3i); |
||||
|
EXPECT_EQ(s, "(+1.0-3.0i)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_g) { |
||||
|
std::string s = fmt::format("{:g}", 2.f + 3if); |
||||
|
EXPECT_EQ(s, "(2+3if)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_gs) { |
||||
|
std::string s = fmt::format("{:*g}", 3i); |
||||
|
EXPECT_EQ(s, "(3*i)"); |
||||
|
} |
||||
|
TEST(libfmt, complex_gel) { |
||||
|
std::string s = fmt::format("{:g}", 2.l + 3il); |
||||
|
EXPECT_EQ(s, "(2+3il)"); |
||||
|
} |
||||
|
|
||||
|
TEST(libfmt, dual_) { |
||||
|
std::string s = fmt::format("{}", 2 + 3_ef); |
||||
|
EXPECT_EQ(s, "(2.0+3.0_ef)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_el) { |
||||
|
std::string s = fmt::format("{}", 2 + 3_el); |
||||
|
EXPECT_EQ(s, "(2.0+3.0_el)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_flags) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("{}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(2.0+3.0_e)"); |
||||
|
|
||||
|
s = fmt::format("{:$}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(2.0+3.0_e)"); |
||||
|
|
||||
|
s = fmt::format("{:*}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(2.0+3.0*e)"); |
||||
|
|
||||
|
s = fmt::format("{:,}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(2.0,3.0)"); |
||||
|
|
||||
|
// + +
|
||||
|
s = fmt::format("{:$+}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0+3.0_e)"); |
||||
|
|
||||
|
s = fmt::format("{:*+}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0+3.0*e)"); |
||||
|
|
||||
|
s = fmt::format("{:,+}", 2. + 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0,+3.0)"); |
||||
|
|
||||
|
// + -
|
||||
|
s = fmt::format("{:$+}", 2. - 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0-3.0_e)"); |
||||
|
|
||||
|
s = fmt::format("{:*+}", 2. - 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0-3.0*e)"); |
||||
|
|
||||
|
s = fmt::format("{:,+}", 2. - 3_e); |
||||
|
EXPECT_EQ(s, "(+2.0,-3.0)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_all_real) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("{}", 2 + 0_e); |
||||
|
EXPECT_EQ(s, "(2.0)"); |
||||
|
s = fmt::format("{:*}", 2 + 0_e); |
||||
|
EXPECT_EQ(s, "(2.0)"); |
||||
|
s = fmt::format("{:,}", 2 + 0_e); |
||||
|
EXPECT_EQ(s, "(2.0,0.0)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_all_dual) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("a{}b", 0 + 3_e); |
||||
|
EXPECT_EQ(s, "a(3.0_e)b"); |
||||
|
s = fmt::format("a{:*}b", 0 + 3_e); |
||||
|
EXPECT_EQ(s, "a(3.0*e)b"); |
||||
|
s = fmt::format("a{:,}b", 0 + 3_e); |
||||
|
EXPECT_EQ(s, "a(0.0,3.0)b"); |
||||
|
} |
||||
|
TEST(libfmt, dual_g) { |
||||
|
std::string s = fmt::format("{:g}", 2 + 3_ef); |
||||
|
EXPECT_EQ(s, "(2+3_ef)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_gs) { |
||||
|
std::string s = fmt::format("a{:*g}b", 3_e); |
||||
|
EXPECT_EQ(s, "a(3*e)b"); |
||||
|
|
||||
|
s = fmt::format("{:*+g}", 3_e); |
||||
|
EXPECT_EQ(s, "(+3*e)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_gel) { |
||||
|
std::string s = fmt::format("{:g}", 2 + 3_el); |
||||
|
EXPECT_EQ(s, "(2+3_el)"); |
||||
|
} |
||||
|
TEST(libfmt, dual_cgt) { |
||||
|
std::string s = fmt::format("{:g}", cdualf(2 + 3_ef, 4 + 5_ef)); |
||||
|
EXPECT_EQ(s, "((2+3_ef)+(4+5_ef)i)"); |
||||
|
} |
||||
|
|
||||
|
TEST(libfmt, dual_cgts) { |
||||
|
std::string s; |
||||
|
|
||||
|
s = fmt::format("{:**g}", cdualf(2 + 3_ef, 4 + 5_ef)); |
||||
|
EXPECT_EQ(s, "((2+3*ef)+(4+5*ef)*i)"); // todo - should be *if
|
||||
|
|
||||
|
s = fmt::format("{:,*g}", cdualf(2 + 3_ef, 4 + 5_ef)); |
||||
|
EXPECT_EQ(s, "((2+3*ef),(4+5*ef))"); |
||||
|
|
||||
|
s = fmt::format("{:,,g}", cdualf(2 + 3_ef, 4 + 5_ef)); |
||||
|
EXPECT_EQ(s, "((2,3),(4,5))"); |
||||
|
} |
||||
@ -0,0 +1,215 @@ |
|||||
|
//===-- test_funcs.cpp - test duals/dual ------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals Project
|
||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
|
||||
|
#include "gtest/gtest.h"
|
||||
|
#include <duals/dual>
|
||||
|
#include <complex>
|
||||
|
|
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<double> complexd; |
||||
|
|
||||
|
//using std::complex;
|
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ asdf; EXPECT_TRUE(asdf::value); }
|
||||
|
#define EXPECT_CNEAR(a,b,prec) EXPECT_NEAR(std::abs((a) - (b)), 0, std::abs(prec))
|
||||
|
|
||||
|
// rough comparison of a finite-differences approx of the derivative
|
||||
|
// with the duals's implementation. just meant to catch wild wrongness,
|
||||
|
// not verify precision.
|
||||
|
#define FD_CHECK(T, F, ...) \
|
||||
|
TEST(func##_##T, F) { \ |
||||
|
for (T x : __VA_ARGS__) { \ |
||||
|
T prec = 100 * std::sqrt(std::numeric_limits<T>::epsilon()); \ |
||||
|
T dd = dpart(F(x + dual<T>(0,1))); \ |
||||
|
/*T dx = std::numeric_limits<T>::epsilon() * (T)1000000; */ \ |
||||
|
T dx = T(1)/ (1ull << (std::numeric_limits<T>::digits / 3)); \ |
||||
|
T fd = (F(x + dx) - F(x - dx)) / (2*dx); \ |
||||
|
EXPECT_CNEAR(dd, fd, prec * std::abs(std::max(std::max(dd,fd),T(1)))) \ |
||||
|
<< "dd=" << dd << " fd=" << fd << " x=" << x << " dx=" << dx; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
FD_CHECK(double, exp, {-1,0,1}) |
||||
|
FD_CHECK(double, log, {1}) |
||||
|
//FD_CHECK(complexd, log, {-1,1}) TODO
|
||||
|
FD_CHECK(double, log10, {1}) |
||||
|
//FD_CHECK(complexd, log10, {-1,0,1}) TODO
|
||||
|
FD_CHECK(double, sqrt, {0.5,1.0}) |
||||
|
FD_CHECK(double, cbrt, {-10.,-0.01,0.01,1.0,10.}) |
||||
|
//FD_CHECK(complexd, sqrt, {0,1}) TODO
|
||||
|
FD_CHECK(double, sin, {-1,0,1}) |
||||
|
FD_CHECK(double, cos, {-1,0,1}) |
||||
|
FD_CHECK(double, tan, {-1,0,1}) |
||||
|
FD_CHECK(double, asin, {-.9,0.,.9}) |
||||
|
FD_CHECK(double, acos, {-.9,0.,.9}) |
||||
|
FD_CHECK(double, atan, {-10,-1,0,1,10}) |
||||
|
|
||||
|
// TODO:
|
||||
|
//FD_CHECK(double, sinh, {0})
|
||||
|
//FD_CHECK(double, cosh, {0})
|
||||
|
//FD_CHECK(double, tanh, {0})
|
||||
|
//FD_CHECK(double, asinh, {0})
|
||||
|
//FD_CHECK(double, acosh, {0})
|
||||
|
//FD_CHECK(double, atanh, {0})
|
||||
|
|
||||
|
FD_CHECK(double, erf, {-1,0,1}) |
||||
|
FD_CHECK(double, erfc, {-1,0,1}) |
||||
|
FD_CHECK(double, tgamma, {1.,0.5,10.}) |
||||
|
FD_CHECK(double, lgamma, {-1.1, 0.5, 1.1, 2.}) |
||||
|
|
||||
|
// check that functions with poles in their derivatives dont generate
|
||||
|
// NaNs at the poles if dpart==0.
|
||||
|
#define DZERO_CHECK(F, DZ) \
|
||||
|
TEST(zero_##F, DZ) { \ |
||||
|
dual<double> d(DZ,0); \ |
||||
|
EXPECT_TRUE(std::isfinite(F(d).dpart())); \ |
||||
|
} |
||||
|
|
||||
|
DZERO_CHECK(log, 0) |
||||
|
DZERO_CHECK(sqrt, 0) |
||||
|
DZERO_CHECK(cbrt, 0) |
||||
|
DZERO_CHECK(asin, 1) |
||||
|
DZERO_CHECK(acos, 1) |
||||
|
//DZERO_CHECK(atan, i)
|
||||
|
//DZERO_CHECK(atan2, i)
|
||||
|
|
||||
|
// These dont really cause d/dt = 0, but do a partial check and
|
||||
|
// increase code coverage.
|
||||
|
DZERO_CHECK(tgamma, 0) |
||||
|
DZERO_CHECK(lgamma, 0) |
||||
|
|
||||
|
TEST(func, tgamma) { |
||||
|
duald x = 10 + 4_e; |
||||
|
//EXPECT_EQ(tgamma(x).rpart(), 362880); "interestingly", compiling without optimization (-O0) causes this to fail
|
||||
|
EXPECT_NEAR(tgamma(x).rpart(), 362880, 362880 * 100 * std::numeric_limits<double>::epsilon()); |
||||
|
} |
||||
|
TEST(func, rpart) { |
||||
|
dualf x = 10 + 4_e; |
||||
|
EXPECT_EQ(rpart(x), 10); |
||||
|
} |
||||
|
TEST(func, dpart) { |
||||
|
dualf x = 2 + 4_e; |
||||
|
EXPECT_EQ(dpart(x), 4); |
||||
|
} |
||||
|
TEST(func, abs) { |
||||
|
} |
||||
|
TEST(func, arg) { |
||||
|
} |
||||
|
TEST(func, norm) { |
||||
|
} |
||||
|
TEST(func, conj) { |
||||
|
} |
||||
|
TEST(func, polar) { |
||||
|
} |
||||
|
|
||||
|
struct pike_f1 { |
||||
|
// function
|
||||
|
template <typename TYPE> |
||||
|
TYPE |
||||
|
f(const TYPE & x) { |
||||
|
return exp(x) / sqrt(pow(sin(x), 3) + pow(cos(x), 3)); |
||||
|
} |
||||
|
|
||||
|
// analytic derivative
|
||||
|
template <typename TYPE> |
||||
|
TYPE |
||||
|
df(const TYPE & x) { |
||||
|
return (exp(x) * (3 * cos(x) + 5*cos(3*x) + 9 * sin(x) + sin(3*x))) / |
||||
|
(8 * pow(pow(sin(x), (3)) + pow(cos(x), 3), 3./2.)); |
||||
|
} |
||||
|
|
||||
|
// analytic second derivative
|
||||
|
template <typename TYPE> |
||||
|
TYPE |
||||
|
ddf(const TYPE & x) { |
||||
|
return (exp(x) * (130 - 12 * cos(2*x) + 30*cos(4*x) |
||||
|
+ 12*cos(6*x) |
||||
|
- 111.*sin(2*x) + 48.*sin(4*x) + 5*sin(6*x))) / |
||||
|
(64. * pow(pow(sin(x), 3) + pow(cos(x), 3), 5./2.)); |
||||
|
} |
||||
|
|
||||
|
// analytic third derivative
|
||||
|
template <typename TYPE> |
||||
|
TYPE |
||||
|
dddf(const TYPE & x) { |
||||
|
return exp(x)*(1.0) |
||||
|
/ pow(sin(x) |
||||
|
+ pow(cos(x),(3.0)) |
||||
|
- pow(cos(x),(2.0)) * sin(x), 7.0/2.0) |
||||
|
* (cos(x) * |
||||
|
- (186.0) |
||||
|
+ sin(x)*(68.0) |
||||
|
+ pow(cos(x),3)*171 |
||||
|
- pow(cos(x),5)*42 |
||||
|
- pow(cos(x),7)*33 |
||||
|
+ pow(cos(x),9)*110 |
||||
|
+ pow(cos(x),2)*sin(x)*(256.0) |
||||
|
- pow(cos(x),4)*sin(x)*(495.0) |
||||
|
+ pow(cos(x),6)*sin(x)*(139.0) |
||||
|
+ pow(cos(x),8)*sin(x)*74.0) * (1.0/8); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
TEST(diff, pike) { |
||||
|
#if 1
|
||||
|
typedef double real_t; |
||||
|
typedef duald dual_t; |
||||
|
typedef hyperduald hdual_t; |
||||
|
#else
|
||||
|
typedef float real_t; |
||||
|
typedef dualf dual_t; |
||||
|
typedef hyperduald hdual_t; |
||||
|
#endif
|
||||
|
pike_f1 f1; |
||||
|
// calculate f, f' and f'' and f''' analytically at x
|
||||
|
real_t x = 7; |
||||
|
real_t f = f1.f(x); |
||||
|
real_t fp = f1.df(x); |
||||
|
real_t fpp = f1.ddf(x); |
||||
|
real_t fppp = f1.dddf(x); |
||||
|
|
||||
|
// calculate f, f' and f'' and f'' and f''' using duals
|
||||
|
dual_t dfp = f1.f(x + 1_e); |
||||
|
dual_t ddfp = f1.df(x + 1_e); |
||||
|
real_t x4 = 0; |
||||
|
hdual_t dfpp = f1.f(hdual_t(x+1_e, 1 + x4*1_e) ); // x + 1*e1 + 1*e2 + x4*e1e2
|
||||
|
hdual_t dfppp = f1.df(hdual_t(x+1_e, 1 + x4*1_e)); |
||||
|
|
||||
|
real_t prec = std::numeric_limits<real_t>::epsilon() * 1e6; |
||||
|
//prec = 1e-11;
|
||||
|
EXPECT_NEAR(f, dfpp.rpart().rpart(), prec); |
||||
|
EXPECT_NEAR(fp, dfp.dpart(), prec); |
||||
|
EXPECT_NEAR(fp, ddfp.rpart(), prec); |
||||
|
EXPECT_NEAR(fp, dfpp.rpart().dpart(), prec); |
||||
|
EXPECT_NEAR(fpp, ddfp.dpart(), prec); |
||||
|
EXPECT_NEAR(fpp, dfpp.dpart().dpart(), prec); |
||||
|
EXPECT_NEAR(fppp, dfppp.dpart().dpart(), prec); |
||||
|
//std::cout << "dfpp=" << dfpp << "\n";
|
||||
|
//std::cout << "dfppp=" << dfppp << "\n";
|
||||
|
} |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,402 @@ |
|||||
|
//===-- test_packets.cpp - test duals/dual_eigen -----------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_packets Dual number Eigen integration tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
#define EXPECT_DEQ(A,B) EXPECT_EQ(rpart(A), rpart(B)); EXPECT_EQ(dpart(A), dpart(B))
|
||||
|
#define ASSERT_DEQ(A,B) ASSERT_EQ(rpart(A), rpart(B)); ASSERT_EQ(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNE(A,B) EXPECT_NE(rpart(A), rpart(B)); EXPECT_NE(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNEAR(A,B,tol) \
|
||||
|
EXPECT_NEAR(abs(rpart((A) - (B))),0,tol); \ |
||||
|
EXPECT_NEAR(abs(dpart((A) - (B))),0,tol) |
||||
|
|
||||
|
|
||||
|
#if !defined(CPPDUALS_DONT_VECTORIZE) && !defined(EIGEN_DONT_VECTORIZE)
|
||||
|
|
||||
|
TEST(Packet1cdf, pload_pstore) { |
||||
|
using namespace Eigen::internal; |
||||
|
cdualf cd1 = cdualf(1+2_ef,3+4_ef); |
||||
|
cdualf cd2 = cdualf(5+6_ef,7+8_ef); |
||||
|
Packet1cdf p1 = pload<Packet1cdf>(&cd1); |
||||
|
pstore(&cd2, p1); |
||||
|
EXPECT_DEQ(cd1, cd2); |
||||
|
} |
||||
|
|
||||
|
using duals::randos::random2; |
||||
|
|
||||
|
#define GEN_PACKET_TEST_BI(PTYPE,pop,op) TEST(PTYPE,pop) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
double tol = rpart(20*Eigen::NumTraits<DTYPE>::epsilon()); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd3(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
cd2[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
PTYPE p2 = pload<PTYPE>(cd2.data()); \ |
||||
|
auto p3 = pop (p1, p2); \ |
||||
|
pstore(cd3.data(), p3); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DNEAR(cd3[i], cd1[i] op cd2[i], tol) \ |
||||
|
<< cd1[i] << ',' << cd2[i] << " fail at " << i; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_UN(PTYPE,pop,op) TEST(PTYPE,pop) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
double tol = rpart(20*Eigen::NumTraits<DTYPE>::epsilon()); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
auto p2 = pop (p1); \ |
||||
|
pstore(cd2.data(), p2); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DNEAR(cd2[i], op(cd1[i]), tol) \ |
||||
|
<< cd1[i] << " fail at " << i; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_RD(PTYPE,pop,op) TEST(PTYPE,pop) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
double tol = rpart(20*Eigen::NumTraits<DTYPE>::epsilon()); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
DTYPE p2 = pop (p1); \ |
||||
|
DTYPE acc(1); \ |
||||
|
for (int i = 0; i < N; i++) \ |
||||
|
acc op##= cd1[i]; \ |
||||
|
EXPECT_DNEAR(acc, (DTYPE(1) op p2), tol) \ |
||||
|
<< acc << " " << p2 << " fail."; \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_REVERSE(PTYPE) TEST(PTYPE,preverse) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
PTYPE p2 = preverse (p1); \ |
||||
|
pstore(cd2.data(), p2); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[i], cd2[N-1-i]) \ |
||||
|
<< cd1[i] << "," << cd2[N-1-i] << " @ " << i << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_FIRST(PTYPE) TEST(PTYPE,pfirst) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
DTYPE c2 = pfirst (p1); \ |
||||
|
EXPECT_DEQ(cd1[0], c2) \ |
||||
|
<< cd1[0] << "," << c2 << " fail."; \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_SET1(PTYPE) TEST(PTYPE,pset1) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
cd2[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
DTYPE c2 = random2<DTYPE>(); \ |
||||
|
PTYPE p1 = pset1<PTYPE>(c2); \ |
||||
|
PTYPE p2 = pload1<PTYPE>(&c2); \ |
||||
|
pstore(cd1.data(), p1); \ |
||||
|
pstore(cd2.data(), p2); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[i], c2) \ |
||||
|
<< i << ":" << cd1[i] << "," << c2 << " fail."; \ |
||||
|
EXPECT_DEQ(cd2[i], c2) \ |
||||
|
<< i << ":" << cd1[i] << "," << c2 << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_LOADDUP(PTYPE) TEST(PTYPE,ploaddup) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(1+N/2); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < 1+N/2; i++) { cd1[i] = random2<DTYPE>(); } \ |
||||
|
for (size_t i = 0; i < N ; i++) { cd2[i] = random2<DTYPE>(); } \ |
||||
|
PTYPE p1 = ploaddup<PTYPE>(cd1.data()); \ |
||||
|
pstore(cd2.data(), p1); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[i/2], cd2[i]) \ |
||||
|
<< i << ":" << cd1[i/2] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_ULOAD(PTYPE) TEST(PTYPE,ploadu) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
char b1[sizeof(DTYPE) * (N+2)]; \ |
||||
|
char b2[sizeof(DTYPE) * (N+2)]; \ |
||||
|
DTYPE * cd1 = (DTYPE *)&b1[1]; \ |
||||
|
DTYPE * cd2 = (DTYPE *)&b2[2]; \ |
||||
|
for (size_t i = 0; i < N+1; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
cd2[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = ploadu<PTYPE>(&cd1[1]); \ |
||||
|
pstoreu(&cd2[1], p1); \ |
||||
|
for (int i = 1; i < N+1; i++) { \ |
||||
|
EXPECT_DEQ(cd1[i], cd2[i]) \ |
||||
|
<< cd1[i] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_BROADCAST(PTYPE,B) TEST(PTYPE,pbroadcast##B) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
PTYPE p1; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(B); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { cd1[i] = random2<DTYPE>(); } \ |
||||
|
PTYPE p0,p3,p2; \ |
||||
|
if (B == 2) pbroadcast2(cd1.data(), p0,p1); \ |
||||
|
if (B == 4) pbroadcast4(cd1.data(), p0,p1,p2,p3); \ |
||||
|
pstore(cd2.data(), p0); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[0], cd2[i]) << i << ":" << cd1[0] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
pstore(cd2.data(), p1); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[1], cd2[i]) << i << ":" << cd1[1] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
if (B == 4) { \ |
||||
|
pstore(cd2.data(), p2); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[2], cd2[i]) << i << ":" << cd1[2] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
pstore(cd2.data(), p3); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(cd1[3], cd2[i]) << i << ":" << cd1[3] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_CPLXFLIP(PTYPE) TEST(PTYPE,pcplxflip) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
cd2[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
PTYPE p2 = pcplxflip (p1); \ |
||||
|
pstore(cd2.data(), p2); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DEQ(real(cd1[i]), imag(cd2[i])) \ |
||||
|
<< cd1[i] << "," << cd2[i] << " fail."; \ |
||||
|
EXPECT_DEQ(imag(cd1[i]), real(cd2[i])) \ |
||||
|
<< cd1[i] << "," << cd2[i] << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
#define GEN_PACKET_TEST_CONJ_HELPER(PTYPE) TEST(PTYPE,conj_helper) { \
|
||||
|
using namespace Eigen::internal; \ |
||||
|
typedef unpacket_traits<PTYPE>::type DTYPE; \ |
||||
|
const static int N = unpacket_traits<PTYPE>::size; \ |
||||
|
double tol = rpart(10*Eigen::NumTraits<DTYPE>::epsilon()); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd1(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd2(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> cd3(N); \ |
||||
|
std::vector<DTYPE,Eigen::aligned_allocator<DTYPE>> r(N); \ |
||||
|
for (size_t i = 0; i < N; i++) { \ |
||||
|
cd1[i] = random2<DTYPE>(); \ |
||||
|
cd2[i] = random2<DTYPE>(); \ |
||||
|
cd3[i] = random2<DTYPE>(); \ |
||||
|
} \ |
||||
|
PTYPE p1 = pload<PTYPE>(cd1.data()); \ |
||||
|
PTYPE p2 = pload<PTYPE>(cd2.data()); \ |
||||
|
PTYPE p3 = pload<PTYPE>(cd3.data()); \ |
||||
|
conj_helper<PTYPE,PTYPE,false,false> cj; p3 = cj.pmadd(p1,p2,p3); \ |
||||
|
pstore(r.data(), p3); \ |
||||
|
for (int i = 0; i < N; i++) { \ |
||||
|
EXPECT_DNEAR(r[i], cd1[i] * cd2[i] + cd3[i], tol) \ |
||||
|
<< r[i] << "!=" << cd1[i] << "*" << cd3[i] << "+" << cd3[i] << " fail."; \ |
||||
|
} \ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#define GEN_PACKET_TESTS(PTYPE) \
|
||||
|
GEN_PACKET_TEST_BI(PTYPE,padd,+) \ |
||||
|
GEN_PACKET_TEST_BI(PTYPE,psub,-) \ |
||||
|
GEN_PACKET_TEST_BI(PTYPE,pmul,*) \ |
||||
|
GEN_PACKET_TEST_BI(PTYPE,pdiv,/) \ |
||||
|
GEN_PACKET_TEST_UN(PTYPE,pnegate,-) \ |
||||
|
GEN_PACKET_TEST_RD(PTYPE,predux,+) \ |
||||
|
GEN_PACKET_TEST_RD(PTYPE,predux_mul,*) \ |
||||
|
GEN_PACKET_TEST_ULOAD(PTYPE) \ |
||||
|
GEN_PACKET_TEST_SET1(PTYPE) \ |
||||
|
GEN_PACKET_TEST_LOADDUP(PTYPE) \ |
||||
|
/*GEN_PACKET_TEST_BROADCAST(PTYPE,2)*/ \ |
||||
|
GEN_PACKET_TEST_BROADCAST(PTYPE,4) \ |
||||
|
GEN_PACKET_TEST_FIRST(PTYPE) \ |
||||
|
GEN_PACKET_TEST_REVERSE(PTYPE) |
||||
|
|
||||
|
#define GEN_CPACKET_TESTS(PTYPE) \
|
||||
|
GEN_PACKET_TESTS(PTYPE) \ |
||||
|
GEN_PACKET_TEST_CPLXFLIP(PTYPE) \ |
||||
|
GEN_PACKET_TEST_CONJ_HELPER(PTYPE) \ |
||||
|
GEN_PACKET_TEST_UN(PTYPE,pconj,conj) |
||||
|
|
||||
|
// TODO:
|
||||
|
//pcplxflip
|
||||
|
//preduxp
|
||||
|
//pand
|
||||
|
//por
|
||||
|
//pxor
|
||||
|
//andnot
|
||||
|
//pbroadcast4
|
||||
|
//ploadquad (for packets w/ size==8)
|
||||
|
//pgather
|
||||
|
//pscatter
|
||||
|
//align_impl
|
||||
|
//insertfirst
|
||||
|
//insertlast
|
||||
|
|
||||
|
|
||||
|
// test the tests
|
||||
|
GEN_PACKET_TESTS(Packet4f) |
||||
|
GEN_CPACKET_TESTS(Packet2cf) |
||||
|
#if defined(EIGEN_VECTORIZE_AVX)
|
||||
|
GEN_CPACKET_TESTS(Packet4cf) |
||||
|
#endif
|
||||
|
|
||||
|
#ifdef EIGEN_VECTORIZE_SSE
|
||||
|
GEN_PACKET_TESTS(Packet2df) |
||||
|
GEN_PACKET_TESTS(Packet1dd) |
||||
|
GEN_CPACKET_TESTS(Packet1cdf) |
||||
|
#endif
|
||||
|
|
||||
|
#if defined(EIGEN_VECTORIZE_AVX)
|
||||
|
GEN_PACKET_TESTS(Packet4df) |
||||
|
GEN_PACKET_TESTS(Packet2dd) |
||||
|
GEN_CPACKET_TESTS(Packet2cdf) |
||||
|
#if defined(__AVX2__)
|
||||
|
GEN_CPACKET_TESTS(Packet1cdd) |
||||
|
#endif
|
||||
|
#endif
|
||||
|
|
||||
|
#endif // CPPDUALS_DONT_VECTORIZE
|
||||
|
|
||||
|
TEST(compile, VECTORIZE) { |
||||
|
#if defined(CPPDUALS_DONT_VECTORIZE) || defined(EIGEN_DONT_VECTORIZE)
|
||||
|
EXPECT_TRUE(false) << "CPPDUALS_DONT_VECTORIZE supresses vectorization tests!"; |
||||
|
#endif
|
||||
|
} |
||||
|
TEST(compile, SSE) { |
||||
|
EXPECT_TRUE(std::string(Eigen::SimdInstructionSetsInUse()).find("SSE") != std::string::npos) |
||||
|
<< "Not using SSE instructions:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#ifndef EIGEN_VECTORIZE_SSE
|
||||
|
EXPECT_TRUE(false) |
||||
|
<< "Not using EIGEN_VECTORIZE_SSE:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#endif
|
||||
|
} |
||||
|
TEST(compile, AVX) { |
||||
|
EXPECT_TRUE(std::string(Eigen::SimdInstructionSetsInUse()).find("AVX") != std::string::npos) |
||||
|
<< "Not using AVX instructions:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#ifndef EIGEN_VECTORIZE_AVX
|
||||
|
EXPECT_TRUE(false) |
||||
|
<< "Not using EIGEN_VECTORIZE_AVX:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::ptrdiff_t l1, l2, l3; |
||||
|
Eigen::internal::manage_caching_sizes(Eigen::GetAction, &l1, &l2, &l3); |
||||
|
|
||||
|
std::cout << "l1=" << l1 << " l2=" << l2 << " l3=" << l3 << "\n"; |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,119 @@ |
|||||
|
//===-- test_funcs.cpp - test duals/dual ------------------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_eigen Dual number Eigen integration tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include <unsupported/Eigen/MatrixFunctions>
|
||||
|
#include <unsupported/Eigen/AutoDiff>
|
||||
|
#include "eexpokit/padm.hpp"
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
#define EXPECT_DEQ(A,B) EXPECT_EQ(rpart(A), rpart(B)); EXPECT_EQ(dpart(A), dpart(B))
|
||||
|
#define ASSERT_DEQ(A,B) ASSERT_EQ(rpart(A), rpart(B)); ASSERT_EQ(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNE(A,B) EXPECT_NE(rpart(A), rpart(B)); EXPECT_NE(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNEAR(A,B,tol) \
|
||||
|
EXPECT_NEAR(rpart(A), rpart(B),tol); \ |
||||
|
EXPECT_NEAR(dpart(A), dpart(B),tol) |
||||
|
|
||||
|
template <class T, int NN = 30, class DT = dual<T> > |
||||
|
void solveLu() { |
||||
|
auto tol = NN * NN * 10000 * Eigen::NumTraits<T>::epsilon(); |
||||
|
|
||||
|
// check scalar
|
||||
|
emtx<T,NN> a = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> b = emtx<T,NN>::Random(); |
||||
|
emtx<T,NN> c,d,e; |
||||
|
|
||||
|
c = a * b; |
||||
|
d = a.lu().solve(c); |
||||
|
EXPECT_LT((b - d).norm(), tol); |
||||
|
|
||||
|
// check dual
|
||||
|
emtx<DT,NN> A = a + DT(0,1) * emtx<T,NN>::Random(); |
||||
|
emtx<DT,NN> B = b + DT(0,1) * emtx<T,NN>::Random(); |
||||
|
emtx<DT,NN> C,D,E; |
||||
|
C = A * B; |
||||
|
D = A.lu().solve(C); |
||||
|
EXPECT_LT(rpart(B - D).norm(), tol); |
||||
|
EXPECT_LT(dpart(B - D).norm(), tol); |
||||
|
} |
||||
|
|
||||
|
#if defined(PHASE_1)
|
||||
|
|
||||
|
TEST(solveLu, float2) { solveLu<float,2>(); } |
||||
|
TEST(solveLu, float7) { solveLu<float,7>(); } |
||||
|
TEST(solveLu, float8) { solveLu<float,8>(); } |
||||
|
TEST(solveLu, float31) { solveLu<float,31>(); } |
||||
|
|
||||
|
TEST(solveLu, double2) { solveLu<double,2>(); } |
||||
|
TEST(solveLu, double3) { solveLu<double,3>(); } |
||||
|
TEST(solveLu, double4) { solveLu<double,4>(); } |
||||
|
TEST(solveLu, double31) { solveLu<double,31>(); } |
||||
|
|
||||
|
#elif defined(PHASE_2)
|
||||
|
|
||||
|
TEST(solveLu, complexf2) { solveLu<complexf,2,cdualf>(); } |
||||
|
TEST(solveLu, complexf8) { solveLu<complexf,8,cdualf>(); } |
||||
|
TEST(solveLu, complexf31) { solveLu<complexf,31,cdualf>(); } |
||||
|
|
||||
|
TEST(solveLu, complexd31) { solveLu<complexd,31,cduald>(); } |
||||
|
|
||||
|
#endif
|
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,342 @@ |
|||||
|
//===-- test_vectorize.cpp - test duals/dual_eigen -------------*- C++ -*-===//
|
||||
|
//
|
||||
|
// Part of the cppduals project.
|
||||
|
// https://gitlab.com/tesch1/cppduals
|
||||
|
//
|
||||
|
// See https://gitlab.com/tesch1/cppduals/blob/master/LICENSE.txt for
|
||||
|
// license information.
|
||||
|
//
|
||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
//
|
||||
|
// (c)2019 Michael Tesch. tesch1@gmail.com
|
||||
|
//
|
||||
|
/**
|
||||
|
* \file test_vectorize Dual number Eigen vectorization op tests |
||||
|
* |
||||
|
* (c)2019 Michael Tesch. tesch1@gmail.com |
||||
|
*/ |
||||
|
|
||||
|
#include "type_name.hpp"
|
||||
|
#include <duals/dual_eigen>
|
||||
|
#include <Eigen/Dense>
|
||||
|
#include <Eigen/Sparse>
|
||||
|
#include <Eigen/StdVector>
|
||||
|
#include "gtest/gtest.h"
|
||||
|
|
||||
|
using duals::rpart; |
||||
|
using duals::dpart; |
||||
|
using duals::dualf; |
||||
|
using duals::duald; |
||||
|
using duals::dualld; |
||||
|
using duals::hyperdualf; |
||||
|
using duals::hyperduald; |
||||
|
using duals::hyperdualld; |
||||
|
using duals::is_dual; |
||||
|
using duals::is_complex; |
||||
|
using duals::dual_traits; |
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
typedef std::complex<double> complexd; |
||||
|
typedef std::complex<float> complexf; |
||||
|
typedef std::complex<duald> cduald; |
||||
|
typedef std::complex<dualf> cdualf; |
||||
|
|
||||
|
template <class eT, int N=Eigen::Dynamic, int K = N> using emtx = Eigen::Matrix<eT, N, K>; |
||||
|
template <class eT> using smtx = Eigen::SparseMatrix<eT>; |
||||
|
|
||||
|
template <int N=2, int K = N> using ecf = Eigen::Matrix<complexf, N, K> ; |
||||
|
template <int N=2, int K = N> using edf = Eigen::Matrix<dualf, N, K> ; |
||||
|
template <int N=2, int K = N> using ecdf = Eigen::Matrix<cdualf, N, K> ; |
||||
|
|
||||
|
#define _EXPECT_TRUE(...) {typedef __VA_ARGS__ tru; EXPECT_TRUE(tru::value); static_assert(tru::value, "sa"); }
|
||||
|
#define _EXPECT_FALSE(...) {typedef __VA_ARGS__ fal; EXPECT_FALSE(fal::value); static_assert(!fal::value, "sa"); }
|
||||
|
#define ASSERT_DEQ(A,B) ASSERT_EQ(rpart(A), rpart(B)); ASSERT_EQ(dpart(A), dpart(B))
|
||||
|
#define ASSERT_DNEAR(A,B,tol) \
|
||||
|
ASSERT_NEAR(abs(rpart((A) - (B))),0,abs(rpart(A))*(tol)); \ |
||||
|
ASSERT_NEAR(abs(dpart((A) - (B))),0,abs(dpart(A))*(tol)) |
||||
|
#define EXPECT_DEQ(A,B) EXPECT_EQ(rpart(A), rpart(B)); EXPECT_EQ(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNE(A,B) EXPECT_NE(rpart(A), rpart(B)); EXPECT_NE(dpart(A), dpart(B))
|
||||
|
#define EXPECT_DNEAR(A,B,tol) \
|
||||
|
EXPECT_NEAR(abs(rpart((A) - (B))),0,abs(rpart(A))*(tol)); \ |
||||
|
EXPECT_NEAR(abs(dpart((A) - (B))),0,abs(dpart(A))*(tol)) |
||||
|
|
||||
|
|
||||
|
template <typename Rt> |
||||
|
void elemwise(int N) { |
||||
|
std::vector<Rt> a(N); |
||||
|
std::vector<Rt> b(N); |
||||
|
std::vector<Rt> cp(N); |
||||
|
std::vector<Rt> cm(N); |
||||
|
std::vector<Rt> ct(N); |
||||
|
std::vector<Rt> cd(N); |
||||
|
std::vector<Rt> cc(N); |
||||
|
std::vector<Rt> cca(N); |
||||
|
std::vector<Rt> ccb(N); |
||||
|
emtx<Rt> A(N,1); |
||||
|
emtx<Rt> B(N,1); |
||||
|
emtx<Rt> Cp(N,1); |
||||
|
emtx<Rt> Cm(N,1); |
||||
|
emtx<Rt> Ct(N,1); |
||||
|
emtx<Rt> Cd(N,1); |
||||
|
emtx<Rt> Cc(N,1); |
||||
|
emtx<Rt> Cca(N,1); |
||||
|
emtx<Rt> Ccb(N,1); |
||||
|
double tol = rpart(2000*Eigen::NumTraits<Rt>::epsilon()); |
||||
|
using duals::randos::random2; |
||||
|
|
||||
|
Rt sum(0); |
||||
|
for (int i = 0; i < N; i++) { |
||||
|
A(i) = a[i] = random2<Rt>(); |
||||
|
B(i) = b[i] = random2<Rt>(); |
||||
|
cp[i] = a[i] + b[i]; |
||||
|
cm[i] = a[i] - b[i]; |
||||
|
ct[i] = a[i] * b[i]; |
||||
|
cd[i] = a[i] / b[i]; |
||||
|
cc[i] = conj(a[i]) + conj(b[i]); |
||||
|
cca[i] = conj(a[i]) + b[i]; |
||||
|
ccb[i] = a[i] + conj(b[i]); |
||||
|
sum += a[i]; |
||||
|
} |
||||
|
|
||||
|
Cp = A.array() + B.array(); |
||||
|
Cm = A.array() - B.array(); |
||||
|
Ct = A.array() * B.array(); |
||||
|
Cd = A.array() / B.array(); |
||||
|
Cc = conj(A.array()) + conj(B.array()); |
||||
|
Cca = conj(A.array()) + B.array(); |
||||
|
Ccb = A.array() + conj(B.array()); |
||||
|
|
||||
|
for (int i = 0; i < N; i++) { |
||||
|
ASSERT_DEQ(cp[i], Cp(i)) << "p mismatch at " << i << "\n"; |
||||
|
ASSERT_DEQ(cm[i], Cm(i)) << "m mismatch at " << i << "\n"; |
||||
|
ASSERT_DNEAR(ct[i], Ct(i),tol) << "t mismatch at " << i << "\n"; |
||||
|
ASSERT_DNEAR(cd[i], Cd(i),3*tol) /* why is this so much worse? */ |
||||
|
<< "d mismatch at " << i << " " << cd[i] << "|\n" |
||||
|
<< Cd(i) << " != " << a[i] << "/" << b[i] << "\n"; |
||||
|
ASSERT_DEQ(cc[i], Cc(i)) << "c mismatch at " << i << "\n"; |
||||
|
ASSERT_DEQ(cca[i], Cca(i)) << "ca mismatch at " << i << "\n"; |
||||
|
ASSERT_DEQ(ccb[i], Ccb(i)) << "cb mismatch at " << i << "\n"; |
||||
|
} |
||||
|
ASSERT_DNEAR(sum, A.sum(), N*tol); |
||||
|
ASSERT_DNEAR(sum, A.sum(), N*tol); |
||||
|
} |
||||
|
|
||||
|
TEST(Vector, full_even_dualf) { elemwise<dualf>(512); } |
||||
|
TEST(Vector, full_even_duald) { elemwise<duald>(512); } |
||||
|
TEST(Vector, full_even_cdualf) { elemwise<cdualf>(512); } |
||||
|
|
||||
|
TEST(Vector, full_odd_dualf) { elemwise<dualf>(2049); } |
||||
|
TEST(Vector, full_odd_duald) { elemwise<duald>(2049); } |
||||
|
TEST(Vector, full_odd_cdualf) { elemwise<cdualf>(2049); } |
||||
|
|
||||
|
TEST(Vector, single_elem_dualf) { elemwise<dualf>(1); } |
||||
|
TEST(Vector, single_elem_duald) { elemwise<duald>(1); } |
||||
|
TEST(Vector, single_elem_cdualf) { elemwise<cdualf>(1); } |
||||
|
|
||||
|
TEST(Vector, two_elem_dualf) { elemwise<dualf>(2); } |
||||
|
TEST(Vector, two_elem_duald) { elemwise<duald>(2); } |
||||
|
TEST(Vector, two_elem_cdualf) { elemwise<cdualf>(2); } |
||||
|
|
||||
|
#define DBOUT(X)
|
||||
|
#define MAKE_MULT_TEST(TYPE1, TYPE2, FIX, SIZE) \
|
||||
|
TEST(MatMult, TYPE1##_##TYPE2##_##SIZE) { \ |
||||
|
typedef TYPE1 T1; \ |
||||
|
typedef TYPE2 T2; \ |
||||
|
typedef decltype(TYPE1() * TYPE2()) T3; \ |
||||
|
using duals::rpart; \ |
||||
|
using duals::conj; \ |
||||
|
/*using std::conj;*/ \ |
||||
|
using duals::randos::random2; \ |
||||
|
\ |
||||
|
double tol = rpart(20*Eigen::NumTraits<T1>::epsilon()); \ |
||||
|
static const Eigen::Index N = FIX; \ |
||||
|
static const int n = SIZE; \ |
||||
|
emtx<T1,N> A(n,n); \ |
||||
|
emtx<T2,N> B(n,n); \ |
||||
|
emtx<T3,N> C(n,n); \ |
||||
|
emtx<T3,N> D(n,n); \ |
||||
|
\ |
||||
|
for (Eigen::Index i = 0; i < A.size(); i++) { \ |
||||
|
A.data()[i] = random2<T1>(); \ |
||||
|
B.data()[i] = random2<T2>(); \ |
||||
|
} \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += A.data()[k*n+i] * B.data()[j*n+k]; \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << "--------------------------\n"); \ |
||||
|
D = A*B; \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a*b" << C << "\n" << D; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a*b" << C << "\n" << D; \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += A.data()[k*n+i] * conj(B.data()[k*n+j]); \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << CRED " a*b'" CRESET "\n"); \ |
||||
|
D = A*B.adjoint(); \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a*b'"; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a*b'"; \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += conj(A.data()[i*n+k]) * B.data()[j*n+k]; \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << CRED " a'*b" CRESET "\n"); \ |
||||
|
D = A.adjoint()*B; \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a'*b"; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a'*b"; \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += A.data()[k*n+i] * (B.data()[k*n+j]); \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << CRED " a*b.'" CRESET "\n"); \ |
||||
|
D = A*B.transpose(); \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a*b.'"; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a*b.'"; \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += (A.data()[i*n+k]) * B.data()[j*n+k]; \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << CRED " a.'*b'" CRESET "\n"); \ |
||||
|
D = A.transpose()*B; \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a.'*b"; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a.'*b"; \ |
||||
|
\ |
||||
|
C.setZero(); \ |
||||
|
for(int i=0; i<n; ++i) \ |
||||
|
for(int j=0; j<n; ++j) \ |
||||
|
for(int k=0; k<n; ++k) \ |
||||
|
C.data()[j*n+i] += conj(A.data()[i*n+k]) * conj(B.data()[k*n+j]); \ |
||||
|
\ |
||||
|
DBOUT(std::cerr << CRED " a'*b'" CRESET "\n"); \ |
||||
|
D = A.adjoint()*B.adjoint(); \ |
||||
|
ASSERT_NEAR((double)rpart(D - C).norm(), 0, rpart(C).norm() * tol) << "r|a'*b'"; \ |
||||
|
ASSERT_NEAR((double)dpart(D - C).norm(), 0, dpart(C).norm() * tol) << "d|a'*b'"; \ |
||||
|
} |
||||
|
|
||||
|
#if defined(PHASE_1)
|
||||
|
|
||||
|
MAKE_MULT_TEST(double, double, 65, 65) |
||||
|
MAKE_MULT_TEST(complexf, complexf, 2, 2) |
||||
|
MAKE_MULT_TEST(complexf, complexf, 4, 4) |
||||
|
//MAKE_MULT_TEST(complexf, complexf, 8, 8)
|
||||
|
MAKE_MULT_TEST(complexf, complexf, Eigen::Dynamic, 8) |
||||
|
MAKE_MULT_TEST(complexf, complexf, Eigen::Dynamic, 64) |
||||
|
//MAKE_MULT_TEST(complexf, complexf, Eigen::Dynamic, 129)
|
||||
|
MAKE_MULT_TEST(complexd, complexd, Eigen::Dynamic, 129) |
||||
|
|
||||
|
#elif defined(PHASE_2)
|
||||
|
|
||||
|
MAKE_MULT_TEST(double, double, 2, 2) |
||||
|
MAKE_MULT_TEST(complexf, float, 2, 2) |
||||
|
MAKE_MULT_TEST(float, complexf, 2, 2) |
||||
|
//MAKE_MULT_TEST(complexf, float, 4, 4)
|
||||
|
//MAKE_MULT_TEST(float, complexf, 4, 4)
|
||||
|
//MAKE_MULT_TEST(complexf, float, 24, 24)
|
||||
|
//MAKE_MULT_TEST(float, complexf, 24, 24)
|
||||
|
MAKE_MULT_TEST(complexf, float, Eigen::Dynamic, 31) |
||||
|
MAKE_MULT_TEST(float, complexf, Eigen::Dynamic, 31) |
||||
|
//MAKE_MULT_TEST(complexd, double, Eigen::Dynamic, 31)
|
||||
|
//MAKE_MULT_TEST(double, complexd, Eigen::Dynamic, 31)
|
||||
|
|
||||
|
#elif defined(PHASE_3)
|
||||
|
|
||||
|
MAKE_MULT_TEST(dualf, dualf, 2, 2) |
||||
|
MAKE_MULT_TEST(dualf, dualf, 3, 3) |
||||
|
MAKE_MULT_TEST(dualf, dualf, 4, 4) |
||||
|
MAKE_MULT_TEST(dualf, dualf, 7, 7) |
||||
|
MAKE_MULT_TEST(dualf, dualf, 8, 8) |
||||
|
MAKE_MULT_TEST(dualf, dualf, 31, 31) |
||||
|
MAKE_MULT_TEST(dualf, dualf, Eigen::Dynamic, 127) |
||||
|
//MAKE_MULT_TEST(dualf, float, 31, 31)
|
||||
|
//MAKE_MULT_TEST(float, dualf, 31, 31)
|
||||
|
|
||||
|
MAKE_MULT_TEST(cdualf, cdualf, 2,2) |
||||
|
MAKE_MULT_TEST(cdualf, cdualf, 3,3) |
||||
|
MAKE_MULT_TEST(cdualf, cdualf, 4,4) |
||||
|
MAKE_MULT_TEST(cdualf, cdualf, 31,31) |
||||
|
MAKE_MULT_TEST(cdualf, cdualf, Eigen::Dynamic, 127) |
||||
|
//MAKE_MULT_TEST(cdualf, cdualf, Eigen::Dynamic, 255)
|
||||
|
|
||||
|
#elif defined(PHASE_4)
|
||||
|
|
||||
|
MAKE_MULT_TEST(cdualf, dualf, 4,4) |
||||
|
MAKE_MULT_TEST(dualf, cdualf, 4,4) |
||||
|
|
||||
|
MAKE_MULT_TEST(dualf, cdualf, 23,23) |
||||
|
MAKE_MULT_TEST(dualf, cdualf, Eigen::Dynamic,127) |
||||
|
|
||||
|
MAKE_MULT_TEST(cdualf, dualf, 8,8) |
||||
|
MAKE_MULT_TEST(cdualf, dualf, Eigen::Dynamic,127) |
||||
|
|
||||
|
#elif defined(PHASE_5)
|
||||
|
|
||||
|
MAKE_MULT_TEST(duald, duald, 2, 2) |
||||
|
MAKE_MULT_TEST(duald, duald, 3, 3) |
||||
|
MAKE_MULT_TEST(duald, duald, 4, 4) |
||||
|
MAKE_MULT_TEST(duald, duald, 31, 31) |
||||
|
MAKE_MULT_TEST(duald, duald, Eigen::Dynamic, 127) |
||||
|
//MAKE_MULT_TEST(duald, duald, Eigen::Dynamic, 255)
|
||||
|
|
||||
|
MAKE_MULT_TEST(cduald, duald, 4,4) |
||||
|
MAKE_MULT_TEST(duald, cduald, 4,4) |
||||
|
|
||||
|
MAKE_MULT_TEST(cduald, cduald, Eigen::Dynamic, 127) |
||||
|
|
||||
|
MAKE_MULT_TEST(duald, cduald, Eigen::Dynamic,127) |
||||
|
MAKE_MULT_TEST(cduald, duald, Eigen::Dynamic,127) |
||||
|
|
||||
|
#endif
|
||||
|
|
||||
|
TEST(flags, VECTORIZE) { |
||||
|
#if defined(CPPDUALS_DONT_VECTORIZE) || defined(EIGEN_DONT_VECTORIZE)
|
||||
|
EXPECT_TRUE(false) << "CPPDUALS_DONT_VECTORIZE supresses vectorization tests!"; |
||||
|
#endif
|
||||
|
} |
||||
|
TEST(flags, SSE) { |
||||
|
EXPECT_TRUE(std::string(Eigen::SimdInstructionSetsInUse()).find("SSE") != std::string::npos) |
||||
|
<< "Not using SSE instructions:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#ifndef EIGEN_VECTORIZE_SSE
|
||||
|
EXPECT_TRUE(false) |
||||
|
<< "Not using EIGEN_VECTORIZE_SSE:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#endif
|
||||
|
} |
||||
|
TEST(flags, AVX) { |
||||
|
EXPECT_TRUE(std::string(Eigen::SimdInstructionSetsInUse()).find("AVX") != std::string::npos) |
||||
|
<< "Not using AVX instructions:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#ifndef EIGEN_VECTORIZE_AVX
|
||||
|
EXPECT_TRUE(false) |
||||
|
<< "Not using EIGEN_VECTORIZE_AVX:" << Eigen::SimdInstructionSetsInUse(); |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
#define QUOTE(...) STRFY(__VA_ARGS__)
|
||||
|
#define STRFY(...) #__VA_ARGS__
|
||||
|
|
||||
|
int main(int argc, char **argv) |
||||
|
{ |
||||
|
std::ptrdiff_t l1, l2, l3; |
||||
|
Eigen::internal::manage_caching_sizes(Eigen::GetAction, &l1, &l2, &l3); |
||||
|
|
||||
|
std::cout << "l1=" << l1 << " l2=" << l2 << " l3=" << l3 << "\n"; |
||||
|
std::cout << "OPT_FLAGS=" << QUOTE(OPT_FLAGS) << "\n"; |
||||
|
std::cout << "INSTRUCTIONSET=" << Eigen::SimdInstructionSetsInUse() << "\n"; |
||||
|
::testing::InitGoogleTest(&argc, argv); |
||||
|
std::cout.precision(20); |
||||
|
std::cerr.precision(20); |
||||
|
return RUN_ALL_TESTS(); |
||||
|
} |
||||
@ -0,0 +1,106 @@ |
|||||
|
// https://stackoverflow.com/questions/81870/is-it-possible-to-print-a-variables-type-in-standard-c
|
||||
|
#pragma once
|
||||
|
#include <cstddef>
|
||||
|
#include <stdexcept>
|
||||
|
#include <cstring>
|
||||
|
#include <ostream>
|
||||
|
|
||||
|
#ifndef _MSC_VER
|
||||
|
# if __cplusplus < 201103
|
||||
|
# define CONSTEXPR11_TN
|
||||
|
# define CONSTEXPR14_TN
|
||||
|
# define NOEXCEPT_TN
|
||||
|
# elif __cplusplus < 201402
|
||||
|
# define CONSTEXPR11_TN constexpr
|
||||
|
# define CONSTEXPR14_TN
|
||||
|
# define NOEXCEPT_TN noexcept
|
||||
|
# else
|
||||
|
# define CONSTEXPR11_TN constexpr
|
||||
|
# define CONSTEXPR14_TN constexpr
|
||||
|
# define NOEXCEPT_TN noexcept
|
||||
|
# endif
|
||||
|
#else // _MSC_VER
|
||||
|
# if _MSC_VER < 1900
|
||||
|
# define CONSTEXPR11_TN
|
||||
|
# define CONSTEXPR14_TN
|
||||
|
# define NOEXCEPT_TN
|
||||
|
# elif _MSC_VER < 2000
|
||||
|
# define CONSTEXPR11_TN constexpr
|
||||
|
# define CONSTEXPR14_TN
|
||||
|
# define NOEXCEPT_TN noexcept
|
||||
|
# else
|
||||
|
# define CONSTEXPR11_TN constexpr
|
||||
|
# define CONSTEXPR14_TN constexpr
|
||||
|
# define NOEXCEPT_TN noexcept
|
||||
|
# endif
|
||||
|
#endif // _MSC_VER
|
||||
|
|
||||
|
class static_string |
||||
|
{ |
||||
|
const char* const p_; |
||||
|
const std::size_t sz_; |
||||
|
|
||||
|
public: |
||||
|
typedef const char* const_iterator; |
||||
|
|
||||
|
template <std::size_t N> |
||||
|
CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN |
||||
|
: p_(a) |
||||
|
, sz_(N-1) |
||||
|
{} |
||||
|
|
||||
|
CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN |
||||
|
: p_(p) |
||||
|
, sz_(N) |
||||
|
{} |
||||
|
|
||||
|
//CONSTEXPR11_TN operator const char *() const { return p_; }
|
||||
|
CONSTEXPR11_TN const char* data() const NOEXCEPT_TN {return p_;} |
||||
|
CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN {return sz_;} |
||||
|
|
||||
|
CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN {return p_;} |
||||
|
CONSTEXPR11_TN const_iterator end() const NOEXCEPT_TN {return p_ + sz_;} |
||||
|
|
||||
|
CONSTEXPR11_TN char operator[](std::size_t n) const |
||||
|
{ |
||||
|
return n < sz_ ? p_[n] : throw std::out_of_range("static_string"); |
||||
|
} |
||||
|
|
||||
|
std::string str() const { return std::string(begin(), end()); } |
||||
|
}; |
||||
|
|
||||
|
inline |
||||
|
std::ostream& |
||||
|
operator<<(std::ostream& os, static_string const& s) |
||||
|
{ |
||||
|
return os.write(s.data(), s.size()); |
||||
|
} |
||||
|
|
||||
|
#define CRED "\x1b[31m"
|
||||
|
#define CGREEN "\x1b[32m"
|
||||
|
#define CYELLOW "\x1b[33m"
|
||||
|
#define CBLUE "\x1b[34m"
|
||||
|
#define CMAGENTA "\x1b[35m"
|
||||
|
#define CCYAN "\x1b[36m"
|
||||
|
#define CRESET "\x1b[0m"
|
||||
|
|
||||
|
template <class T> |
||||
|
CONSTEXPR14_TN |
||||
|
static_string |
||||
|
type_name() |
||||
|
{ |
||||
|
#ifdef __clang__
|
||||
|
static_string p = __PRETTY_FUNCTION__; |
||||
|
return static_string(p.data() + 31, p.size() - 31 - 1); |
||||
|
#elif defined(__GNUC__)
|
||||
|
static_string p = __PRETTY_FUNCTION__; |
||||
|
# if __cplusplus < 201402
|
||||
|
return static_string(p.data() + 36, p.size() - 36 - 1); |
||||
|
# else
|
||||
|
return static_string(p.data() + 46, p.size() - 46 - 1); |
||||
|
# endif
|
||||
|
#elif defined(_MSC_VER)
|
||||
|
static_string p = __FUNCSIG__; |
||||
|
return static_string(p.data() + 38, p.size() - 38 - 7); |
||||
|
#endif
|
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
cmake_minimum_required (VERSION 2.8.2) |
||||
|
|
||||
|
project (googletest-download NONE) |
||||
|
|
||||
|
include (ExternalProject) |
||||
|
ExternalProject_Add (googletest |
||||
|
GIT_REPOSITORY https://github.com/google/googletest.git |
||||
|
# GIT_TAG master |
||||
|
GIT_TAG release-1.8.1 |
||||
|
GIT_SHALLOW 1 |
||||
|
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" |
||||
|
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" |
||||
|
CONFIGURE_COMMAND "" |
||||
|
BUILD_COMMAND "" |
||||
|
INSTALL_COMMAND "" |
||||
|
TEST_COMMAND "" |
||||
|
) |
||||
@ -0,0 +1,220 @@ |
|||||
|
|
||||
|
# https://gist.github.com/johnb003/65982fdc7a1274fdb023b0c68664ebe4 |
||||
|
|
||||
|
# 3.10 adds support for "gtest_discover_tests" which enumerates the tests inside |
||||
|
# of the code and adds them to ctest. |
||||
|
# |
||||
|
cmake_minimum_required (VERSION 3.10) |
||||
|
project (cppduals_thirdparty) |
||||
|
include (ExternalProject) |
||||
|
|
||||
|
get_directory_property (hasParent PARENT_DIRECTORY) |
||||
|
|
||||
|
set (DEPS_ROOT "${CMAKE_BINARY_DIR}/root") |
||||
|
if (hasParent) |
||||
|
set (DEPS_ROOT "${CMAKE_BINARY_DIR}/thirdparty/root" PARENT_SCOPE) |
||||
|
endif (hasParent) |
||||
|
|
||||
|
if (NOT WIN32) |
||||
|
set (DOWNLOAD_DIR "$ENV{HOME}/Downloads") |
||||
|
else (NOT WIN32) |
||||
|
set (DOWNLOAD_DIR "C:/Downloads") |
||||
|
endif (NOT WIN32) |
||||
|
|
||||
|
# |
||||
|
# Google test (https://github.com/google/googletest/blob/master/googletest/README.md) |
||||
|
# |
||||
|
|
||||
|
# Download and unpack googletest at configure time |
||||
|
configure_file (CMakeLists-gt.txt.in googletest-download/CMakeLists.txt) |
||||
|
execute_process (COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . |
||||
|
RESULT_VARIABLE result |
||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) |
||||
|
if (result) |
||||
|
message (FATAL_ERROR "CMake step for googletest failed: ${result}") |
||||
|
endif () |
||||
|
execute_process (COMMAND ${CMAKE_COMMAND} --build . |
||||
|
RESULT_VARIABLE result |
||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download) |
||||
|
if (result) |
||||
|
message (FATAL_ERROR "Build step for googletest failed: ${result}") |
||||
|
endif () |
||||
|
|
||||
|
# Prevent overriding the parent project's compiler/linker |
||||
|
# settings on Windows |
||||
|
set (gtest_force_shared_crt ON CACHE BOOL "" FORCE) |
||||
|
|
||||
|
# Add googletest directly to our build. This defines |
||||
|
# the gtest and gtest_main targets. |
||||
|
add_subdirectory ( |
||||
|
${CMAKE_CURRENT_BINARY_DIR}/googletest-src |
||||
|
${CMAKE_CURRENT_BINARY_DIR}/googletest-build |
||||
|
EXCLUDE_FROM_ALL) |
||||
|
|
||||
|
# The gtest/gtest_main targets carry header search path |
||||
|
# dependencies automatically when using CMake 2.8.11 or |
||||
|
# later. Otherwise we have to add them here ourselves. |
||||
|
if (CMAKE_VERSION VERSION_LESS 2.8.11) |
||||
|
include_directories ("${gtest_SOURCE_DIR}/include") |
||||
|
endif () |
||||
|
|
||||
|
# Can simply link against gtest or gtest_main as needed. Eg |
||||
|
#add_executable (example example.cpp) |
||||
|
#target_link_libraries (example gtest_main) |
||||
|
#add_test (NAME example_test COMMAND example) |
||||
|
|
||||
|
# |
||||
|
# Eigen |
||||
|
# |
||||
|
if (CPPDUALS_EIGEN_LATEST) |
||||
|
set (EIGEN_URL http://bitbucket.org/eigen/eigen/get/default.tar.bz2) |
||||
|
#set (EIGEN_MD5 ffc83130dcd37b694c6cf7e905099af9) |
||||
|
else () |
||||
|
set (EIGEN_URL http://bitbucket.org/eigen/eigen/get/3.3.7.tar.bz2) |
||||
|
set (EIGEN_MD5 05b1f7511c93980c385ebe11bd3c93fa) |
||||
|
endif () |
||||
|
|
||||
|
ExternalProject_Add (eigenX |
||||
|
PREFIX eigenX |
||||
|
URL ${EIGEN_URL} |
||||
|
#URL_HASH MD5=${EIGEN_MD5} |
||||
|
DOWNLOAD_DIR "$ENV{HOME}/Downloads" |
||||
|
CONFIGURE_COMMAND "" |
||||
|
BUILD_COMMAND "" |
||||
|
INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (eigenX source_dir) |
||||
|
if (hasParent AND NOT EIGEN3_INCLUDE_DIRS) |
||||
|
set (EIGEN3_INCLUDE_DIRS "${source_dir}" PARENT_SCOPE) |
||||
|
endif () |
||||
|
|
||||
|
# |
||||
|
# Eigen-Expokit |
||||
|
# |
||||
|
set (EEX_SHA 72bf6e445d5ae84218dcbd74580720491e0074db ) |
||||
|
ExternalProject_Add (expokitX |
||||
|
PREFIX expokitX |
||||
|
URL https://gitlab.com/api/v4/projects/tesch1%2Feigen-expokit/repository/archive.tbz2?sha=${EEX_SHA} |
||||
|
#URL_HASH MD5=96b79de1d01547f6d658865b7caa02ee |
||||
|
DOWNLOAD_DIR "$ENV{HOME}/Downloads" |
||||
|
CONFIGURE_COMMAND "" |
||||
|
BUILD_COMMAND "" |
||||
|
INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (expokitX source_dir) |
||||
|
if (hasParent) |
||||
|
set (EXPOKIT_INCLUDE_DIR "${source_dir}" PARENT_SCOPE) |
||||
|
endif() |
||||
|
|
||||
|
# |
||||
|
# fmt |
||||
|
# |
||||
|
ExternalProject_Add (fmtX |
||||
|
PREFIX fmtX |
||||
|
URL https://github.com/fmtlib/fmt/archive/6.1.1.tar.gz |
||||
|
URL_HASH MD5=acfb83d44afdca171ee26c597c931e7c |
||||
|
DOWNLOAD_DIR ${DOWNLOAD_DIR} |
||||
|
CONFIGURE_COMMAND "" |
||||
|
BUILD_COMMAND "" |
||||
|
INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (fmtX source_dir) |
||||
|
ExternalProject_Get_Property (fmtX binary_dir) |
||||
|
if (hasParent) |
||||
|
message (" FMT3_INCLUDE_DIRS: ${source_dir}") |
||||
|
add_subdirectory (${source_dir} ${binary_dir} EXCLUDE_FROM_ALL) |
||||
|
endif () |
||||
|
|
||||
|
if (CPPDUALS_BENCHMARK) |
||||
|
# |
||||
|
# google benchmark |
||||
|
# |
||||
|
ExternalProject_Add (benchmarkX |
||||
|
PREFIX benchmarkX |
||||
|
URL "http://github.com/google/benchmark/archive/v1.5.0.tar.gz" |
||||
|
URL_HASH MD5=eb1466370f3ae31e74557baa29729e9e |
||||
|
DOWNLOAD_DIR ${DOWNLOAD_DIR} |
||||
|
CMAKE_ARGS --target install -DBENCHMARK_ENABLE_GTEST_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_USE_LIBCXX=${CPPDUALS_USE_LIBCXX} |
||||
|
"-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>" |
||||
|
INSTALL_DIR "${DEPS_ROOT}" |
||||
|
) |
||||
|
ExternalProject_Get_Property (benchmarkX source_dir) |
||||
|
ExternalProject_Get_Property (benchmarkX install_dir) |
||||
|
if (hasParent) |
||||
|
set (BENCHMARK_SRC_DIR "${source_dir}" PARENT_SCOPE) |
||||
|
set (BENCHMARK_INC_DIR "${install_dir}/include" PARENT_SCOPE) |
||||
|
message (" BENCHMARK_SRC_DIR: ${BENCHMARK_SRC_DIR}") |
||||
|
endif() |
||||
|
|
||||
|
if (Boost_FOUND AND NO) |
||||
|
|
||||
|
# |
||||
|
# Audi + Piranha - needs boost |
||||
|
# |
||||
|
#boost 1.70 |
||||
|
find_package (Boost 1.69) |
||||
|
if (hasParent) |
||||
|
set (Boost_FOUND ${Boost_FOUND} PARENT_SCOPE) |
||||
|
set (Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS} PARENT_SCOPE) |
||||
|
endif () |
||||
|
|
||||
|
# piranha |
||||
|
ExternalProject_Add (piranhaX PREFIX piranhaX |
||||
|
URL https://github.com/bluescarni/piranha/archive/v0.11.tar.gz |
||||
|
URL_HASH MD5=33482f719f6b8a6a5316f9bd148f5b10 |
||||
|
DOWNLOAD_DIR "$ENV{HOME}/Downloads" |
||||
|
CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (piranhaX source_dir) |
||||
|
if (hasParent) |
||||
|
set (PIRANHA_INCLUDE_DIR "${source_dir}/include" PARENT_SCOPE) |
||||
|
endif () |
||||
|
|
||||
|
# AuDi |
||||
|
ExternalProject_Add (audiX PREFIX audiX |
||||
|
URL https://github.com/darioizzo/audi/archive/v1.6.5.tar.gz |
||||
|
URL_HASH MD5=a51897469dfce4ceaa25e65519a346b9 |
||||
|
DOWNLOAD_DIR "$ENV{HOME}/Downloads" |
||||
|
#CONFIGURE_COMMAND "" |
||||
|
CMAKE_ARGS -DAUDI_BUILD_TESTS=OFF |
||||
|
BUILD_COMMAND "" INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (audiX source_dir) |
||||
|
if (hasParent) |
||||
|
set (AUDI_INCLUDE_DIR "${source_dir}/include" PARENT_SCOPE) |
||||
|
endif () |
||||
|
endif (Boost_FOUND AND NO) |
||||
|
endif (CPPDUALS_BENCHMARK) |
||||
|
|
||||
|
# |
||||
|
# multi-precision math |
||||
|
# |
||||
|
if (0) |
||||
|
ExternalProject_Add (mpfrX |
||||
|
PREFIX mpfrX |
||||
|
URL https://www.mpfr.org/mpfr-current/mpfr-4.0.2.tar.bz2 |
||||
|
URL_HASH MD5=6d8a8bb46fe09ff44e21cdbf84f5cdac |
||||
|
DOWNLOAD_DIR ${DOWNLOAD_DIR} |
||||
|
CONFIGURE_COMMAND "../mpfrX/configure" --prefix=<INSTALL_DIR> |
||||
|
#BUILD_COMMAND "make install" |
||||
|
#INSTALL_COMMAND "make install" |
||||
|
) |
||||
|
# clumsy download link - retrieves "archive.tar" |
||||
|
ExternalProject_Add (mprealX |
||||
|
PREFIX mprealX |
||||
|
URL "http://www.holoborodko.com/pavel/wp-content/plugins/download-monitor/download.php?id=4" |
||||
|
URL_HASH MD5=68ad2258eb4a1c699c407f0e7bee5125 |
||||
|
DOWNLOAD_DIR ${DOWNLOAD_DIR} |
||||
|
CONFIGURE_COMMAND "" |
||||
|
BUILD_COMMAND "" |
||||
|
INSTALL_COMMAND "" |
||||
|
) |
||||
|
ExternalProject_Get_Property (mprealX source_dir) |
||||
|
ExternalProject_Get_Property (mpfrX INSTALL_DIR) |
||||
|
if (hasParent) |
||||
|
set (MPFR_INCLUDES "${INSTALL_DIR}/include" "${source_dir}" PARENT_SCOPE) |
||||
|
set (MPFR_LIBRARIES "${INSTALL_DIR}/lib/libmpfr.a" -lgmp PARENT_SCOPE) |
||||
|
message (" MPFR_INCLUDES: ${MPFR_INCLUDES}") |
||||
|
add_definitions (-DHAVE_MPFR) |
||||
|
endif (hasParent) |
||||
|
endif (0) |
||||
@ -0,0 +1,33 @@ |
|||||
|
## Process this file with automake to produce Makefile.in
|
||||
|
|
||||
|
noinst_LTLIBRARIES = libhicum2.la |
||||
|
|
||||
|
libhicum2_la_SOURCES = \
|
||||
|
hicum2.c \
|
||||
|
hicum2acld.c \
|
||||
|
hicum2ask.c \
|
||||
|
hicum2conv.c \
|
||||
|
hicum2defs.h \
|
||||
|
hicum2ext.h \
|
||||
|
hicum2getic.c \
|
||||
|
hicum2init.c \
|
||||
|
hicum2init.h \
|
||||
|
hicum2itf.h \
|
||||
|
hicumL2.hpp \
|
||||
|
hicumL2.cpp \
|
||||
|
hicumL2temp.hpp \
|
||||
|
hicumL2temp.cpp \
|
||||
|
hicum2mask.c \
|
||||
|
hicum2mpar.c \
|
||||
|
hicum2noise.c \
|
||||
|
hicum2param.c \
|
||||
|
hicum2pzld.c \
|
||||
|
hicum2setup.c \
|
||||
|
hicum2soachk.c \
|
||||
|
hicum2trunc.c |
||||
|
|
||||
|
AM_CFLAGS = -O -g -Wall -Wextra -I$(top_srcdir)/src/include |
||||
|
AM_CPPFLAGS = @AM_CPPFLAGS@ -O -g -Wall -Wextra |
||||
|
AM_CXXFLAGS = -I$(top_srcdir)/src/include/cppduals -I$(top_srcdir)/src/include -std=c++11 -O -g -Wall -Wextra |
||||
|
|
||||
|
MAINTAINERCLEANFILES = Makefile.in |
||||
@ -0,0 +1,304 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This file defines the HICUM data structures that are |
||||
|
* available to the next level(s) up the calling hierarchy |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/devdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
IFparm HICUMpTable[] = { /* parameters */ |
||||
|
IOPU("area", HICUM_AREA, IF_REAL, "Area factor"), |
||||
|
IOPU("off", HICUM_OFF, IF_FLAG, "Device initially off"), |
||||
|
IP("ic", HICUM_IC, IF_REALVEC, "Initial condition vector"), |
||||
|
|
||||
|
// these are left here for future. Sometimes it is advantageous for debugging if one can set the initial node voltages of all nodes. |
||||
|
// OP("icvb", HICUM_IC_VB, IF_REAL, "Initial B potential"), |
||||
|
// OP("icvc", HICUM_IC_VC, IF_REAL, "Initial C potential"), |
||||
|
// OP("icve", HICUM_IC_VE, IF_REAL, "Initial E potential"), |
||||
|
// OP("icvbi", HICUM_IC_VBi, IF_REAL, "Initial Bi potential"), |
||||
|
// OP("icvbp", HICUM_IC_VBp, IF_REAL, "Initial Bp potential"), |
||||
|
// OP("icvci", HICUM_IC_VCi, IF_REAL, "Initial Ci potential"), |
||||
|
// OP("icvt", HICUM_IC_Vt, IF_REAL, "Initial T potential"), |
||||
|
// OP("icvei", HICUM_IC_VEi, IF_REAL, "Initial Ei potential"), |
||||
|
|
||||
|
IOPU("m", HICUM_M, IF_REAL, "Multiplier"), |
||||
|
IOPU("temp", HICUM_TEMP, IF_REAL, "Instance temperature"), |
||||
|
IP("dt", HICUM_DTEMP, IF_REAL, "Instance delta temperature"), |
||||
|
IOPU("tk", HICUM_QUEST_TK, IF_REAL, "Actual device temperature"), |
||||
|
IOPU("dtsh", HICUM_QUEST_DTSH, IF_REAL, "Temperature increase due to self-heating"), |
||||
|
IOPU("it", HICUM_QUEST_IT, IF_REAL, "transfer current"), |
||||
|
|
||||
|
OPU("collnode", HICUM_QUEST_COLLNODE, IF_INTEGER, "Number of collector node"), |
||||
|
OPU("basenode", HICUM_QUEST_BASENODE, IF_INTEGER, "Number of base node"), |
||||
|
OPU("emitnode", HICUM_QUEST_EMITNODE, IF_INTEGER, "Number of emitter node"), |
||||
|
OPU("subsnode", HICUM_QUEST_SUBSNODE, IF_INTEGER, "Number of substrate node"), |
||||
|
OPU("tempnode", HICUM_QUEST_TEMPNODE, IF_INTEGER, "Number of temperature node"), |
||||
|
OPU("collCInode", HICUM_QUEST_COLLCINODE, IF_INTEGER, "Internal collector node"), |
||||
|
OPU("baseBPnode", HICUM_QUEST_BASEBPNODE, IF_INTEGER, "External base node"), |
||||
|
OPU("baseBInode", HICUM_QUEST_BASEBINODE, IF_INTEGER, "Internal base node"), |
||||
|
OPU("emitEInode", HICUM_QUEST_EMITEINODE, IF_INTEGER, "Internal emitter node"), |
||||
|
OPU("subsSInode", HICUM_QUEST_SUBSSINODE, IF_INTEGER, "Internal substrate node"), |
||||
|
OPU("xfnode", HICUM_QUEST_XFNODE, IF_INTEGER, "Internal phase node xf"), |
||||
|
OPU("xf1node", HICUM_QUEST_XF1NODE, IF_INTEGER, "Internal phase node xf1"), |
||||
|
OPU("xf2node", HICUM_QUEST_XF2NODE, IF_INTEGER, "Internal phase node xf2"), |
||||
|
/* voltages */ |
||||
|
OP("vbe", HICUM_QUEST_VBE, IF_REAL, "External BE voltage"), |
||||
|
OP("vbbp", HICUM_QUEST_VBBP, IF_REAL, "BBP voltage"), |
||||
|
OP("vbc", HICUM_QUEST_VBC, IF_REAL, "External BC voltage"), |
||||
|
OP("vce", HICUM_QUEST_VCE, IF_REAL, "External CE voltage"), |
||||
|
OP("vsc", HICUM_QUEST_VSC, IF_REAL, "External SC voltage"), |
||||
|
OP("vbiei", HICUM_QUEST_VBIEI, IF_REAL, "Internal BE voltage"), |
||||
|
OP("vbpbi", HICUM_QUEST_VBPBI, IF_REAL, "Peripheral Base to internal Base voltage"), |
||||
|
OP("vbici", HICUM_QUEST_VBICI, IF_REAL, "Internal BC voltage"), |
||||
|
OP("vciei", HICUM_QUEST_VCIEI, IF_REAL, "Interal CE voltage"), |
||||
|
/* currents */ |
||||
|
OP("ic", HICUM_QUEST_CC, IF_REAL, "Collector current"), |
||||
|
OP("iavl", HICUM_QUEST_CAVL, IF_REAL, "Avalanche current"), |
||||
|
OP("ib", HICUM_QUEST_CB, IF_REAL, "Base current"), |
||||
|
OP("ibei", HICUM_QUEST_CBEI, IF_REAL, "Intenral Base Emitter current"), |
||||
|
OP("ibci", HICUM_QUEST_CBCI, IF_REAL, "Internal Base Collector current"), |
||||
|
OP("ie", HICUM_QUEST_CE, IF_REAL, "Emitter current"), |
||||
|
OP("is", HICUM_QUEST_CS, IF_REAL, "Substrate current"), |
||||
|
/* resistances */ |
||||
|
OP("rcx_t", HICUM_QUEST_RCX_T, IF_REAL, "External (saturated) collector series resistance"), |
||||
|
OP("re_t", HICUM_QUEST_RE_T, IF_REAL, "Emitter series resistance"), |
||||
|
OP("rbi", HICUM_QUEST_RBI, IF_REAL, "Internal base resistance as calculated in the model"), |
||||
|
OP("rb", HICUM_QUEST_RB, IF_REAL, "Total base resistance as calculated in the model"), |
||||
|
|
||||
|
/* transconductances and capacitances */ |
||||
|
OP("betadc", HICUM_QUEST_BETADC, IF_REAL, "Common emitter forward current gain"), |
||||
|
OP("gmi", HICUM_QUEST_GMI, IF_REAL, "Internal transconductance"), |
||||
|
OP("gms", HICUM_QUEST_GMS, IF_REAL, "Transconductance of the parasitic substrate PNP"), |
||||
|
OP("rpii", HICUM_QUEST_RPII, IF_REAL, "Internal base-emitter (input) resistance"), |
||||
|
OP("rpix", HICUM_QUEST_RPIX, IF_REAL, "External base-emitter (input) resistance"), |
||||
|
OP("rmui", HICUM_QUEST_RMUI, IF_REAL, "Internal feedback resistance"), |
||||
|
OP("rmux", HICUM_QUEST_RMUX, IF_REAL, "External feedback resistance"), |
||||
|
OP("roi", HICUM_QUEST_ROI, IF_REAL, "Output resistance"), |
||||
|
OP("cpii", HICUM_QUEST_CPII, IF_REAL, "Total internal BE capacitance"), |
||||
|
OP("cpix", HICUM_QUEST_CPIX, IF_REAL, "Total external BE capacitance"), |
||||
|
OP("cmui", HICUM_QUEST_CMUI, IF_REAL, "Total internal BC capacitance"), |
||||
|
OP("cmux", HICUM_QUEST_CMUX, IF_REAL, "Total external BC capacitance"), |
||||
|
OP("ccs", HICUM_QUEST_CCS, IF_REAL, "CS junction capacitance"), |
||||
|
OP("betaac", HICUM_QUEST_BETAAC, IF_REAL, "Small signal current gain"), |
||||
|
OP("crbi", HICUM_QUEST_CRBI, IF_REAL, "Shunt capacitance across RBI as calculated in the model"), |
||||
|
/* transit time */ |
||||
|
OP("tf", HICUM_QUEST_TF, IF_REAL, "Forward transit time"), |
||||
|
OP("ft", HICUM_QUEST_FT, IF_REAL, "Transit frequency"), |
||||
|
OP("ick", HICUM_QUEST_ICK, IF_REAL, "Transit frequency"), |
||||
|
/* power */ |
||||
|
OP("p", HICUM_QUEST_POWER, IF_REAL, "Power dissipation") |
||||
|
}; |
||||
|
|
||||
|
IFparm HICUMmPTable[] = { /* model parameters */ |
||||
|
//Circuit simulator specific parameters |
||||
|
IOP("type", HICUM_MOD_TYPE, IF_STRING, "For transistor type NPN(+1) or PNP (-1)"), |
||||
|
IOPU("npn", HICUM_MOD_NPN, IF_FLAG, "NPN type device"), |
||||
|
IOPU("pnp", HICUM_MOD_PNP, IF_FLAG, "PNP type device"), |
||||
|
IOP("tnom", HICUM_MOD_TNOM, IF_REAL, "Temperature at which parameters are specified"), |
||||
|
IOPR("tref", HICUM_MOD_TNOM, IF_REAL, "Temperature at which parameters are specified"), |
||||
|
IOP("version", HICUM_MOD_VERSION, IF_STRING, " parameter for model version"), |
||||
|
|
||||
|
//Transfer current |
||||
|
IOP("c10", HICUM_MOD_C10 , IF_REAL, "GICCR constant"), |
||||
|
IOP("qp0", HICUM_MOD_QP0 , IF_REAL, "Zero-bias hole charge"), |
||||
|
IOP("ich", HICUM_MOD_ICH , IF_REAL, "High-current correction for 2D and 3D effects"), //`0' signifies infinity |
||||
|
IOP("hf0", HICUM_MOD_HF0 , IF_REAL, "Weight factor for the low current minority charge"), |
||||
|
IOP("hfe", HICUM_MOD_HFE , IF_REAL, "Emitter minority charge weighting factor in HBTs"), |
||||
|
IOP("hfc", HICUM_MOD_HFC , IF_REAL, "Collector minority charge weighting factor in HBTs"), |
||||
|
IOP("hjei", HICUM_MOD_HJEI , IF_REAL, "B-E depletion charge weighting factor in HBTs"), |
||||
|
IOP("ahjei", HICUM_MOD_AHJEI, IF_REAL, "Parameter describing the slope of hjEi(VBE)"), |
||||
|
IOP("rhjei", HICUM_MOD_RHJEI, IF_REAL, "Smoothing parameter for hjEi(VBE) at high voltage"), |
||||
|
IOP("hjci", HICUM_MOD_HJCI , IF_REAL, "B-C depletion charge weighting factor in HBTs"), |
||||
|
|
||||
|
//Base-Emitter diode currents |
||||
|
IOP("ibeis", HICUM_MOD_IBEIS, IF_REAL, "Internal B-E saturation current"), |
||||
|
IOP("mbei", HICUM_MOD_MBEI , IF_REAL, "Internal B-E current ideality factor"), |
||||
|
IOP("ireis", HICUM_MOD_IREIS, IF_REAL, "Internal B-E recombination saturation current"), |
||||
|
IOP("mrei", HICUM_MOD_MREI , IF_REAL, "Internal B-E recombination current ideality factor"), |
||||
|
IOP("ibeps", HICUM_MOD_IBEPS, IF_REAL, "Peripheral B-E saturation current"), |
||||
|
IOP("mbep", HICUM_MOD_MBEP , IF_REAL, "Peripheral B-E current ideality factor"), |
||||
|
IOP("ireps", HICUM_MOD_IREPS, IF_REAL, "Peripheral B-E recombination saturation current"), |
||||
|
IOP("mrep", HICUM_MOD_MREP , IF_REAL, "Peripheral B-E recombination current ideality factor"), |
||||
|
IOP("mcf", HICUM_MOD_MCF , IF_REAL, "Non-ideality factor for III-V HBTs"), |
||||
|
|
||||
|
//Transit time for excess recombination current at b-c barrier |
||||
|
IOP("tbhrec", HICUM_MOD_TBHREC, IF_REAL, "Base current recombination time constant at B-C barrier for high forward injection"), |
||||
|
|
||||
|
//Base-Collector diode currents |
||||
|
IOP("ibcis", HICUM_MOD_IBCIS, IF_REAL, "Internal B-C saturation current"), |
||||
|
IOP("mbci", HICUM_MOD_MBCI , IF_REAL, "Internal B-C current ideality factor"), |
||||
|
IOP("ibcxs", HICUM_MOD_IBCXS, IF_REAL, "External B-C saturation current"), |
||||
|
IOP("mbcx", HICUM_MOD_MBCX , IF_REAL, "External B-C current ideality factor"), |
||||
|
|
||||
|
//Base-Emitter tunneling current |
||||
|
IOP("ibets", HICUM_MOD_IBETS, IF_REAL, "B-E tunneling saturation current"), |
||||
|
IOP("abet", HICUM_MOD_ABET, IF_REAL, "Exponent factor for tunneling current"), |
||||
|
IOP("tunode",HICUM_MOD_TUNODE, IF_INTEGER, "Specifies the base node connection for the tunneling current"), // =1 signifies perimeter node |
||||
|
|
||||
|
//Base-Collector avalanche current |
||||
|
IOP("favl", HICUM_MOD_FAVL , IF_REAL, "Avalanche current factor"), |
||||
|
IOP("qavl", HICUM_MOD_QAVL , IF_REAL, "Exponent factor for avalanche current"), |
||||
|
IOP("kavl", HICUM_MOD_KAVL , IF_REAL, "Flag/factor for turning strong avalanche on"), |
||||
|
IOP("alfav", HICUM_MOD_ALFAV, IF_REAL, "Relative TC for FAVL"), |
||||
|
IOP("alqav", HICUM_MOD_ALQAV, IF_REAL, "Relative TC for QAVL"), |
||||
|
IOP("alkav", HICUM_MOD_ALKAV, IF_REAL, "Relative TC for KAVL"), |
||||
|
|
||||
|
//Series resistances |
||||
|
IOP("rbi0", HICUM_MOD_RBI0 , IF_REAL, "Zero bias internal base resistance"), |
||||
|
IOP("rbx", HICUM_MOD_RBX , IF_REAL, "External base series resistance"), |
||||
|
IOP("fgeo", HICUM_MOD_FGEO , IF_REAL, "Factor for geometry dependence of emitter current crowding"), |
||||
|
IOP("fdqr0", HICUM_MOD_FDQR0, IF_REAL, "Correction factor for modulation by B-E and B-C space charge layer"), |
||||
|
IOP("fcrbi", HICUM_MOD_FCRBI, IF_REAL, "Ratio of HF shunt to total internal capacitance (lateral NQS effect)"), |
||||
|
IOP("fqi", HICUM_MOD_FQI , IF_REAL, "Ration of internal to total minority charge"), |
||||
|
IOP("re", HICUM_MOD_RE , IF_REAL, "Emitter series resistance"), |
||||
|
IOP("rcx", HICUM_MOD_RCX , IF_REAL, "External collector series resistance"), |
||||
|
|
||||
|
//Substrate transistor |
||||
|
IOP("itss", HICUM_MOD_ITSS, IF_REAL, "Substrate transistor transfer saturation current"), |
||||
|
IOP("msf", HICUM_MOD_MSF , IF_REAL, "Forward ideality factor of substrate transfer current"), |
||||
|
IOP("iscs", HICUM_MOD_ISCS, IF_REAL, "C-S diode saturation current"), |
||||
|
IOP("msc", HICUM_MOD_MSC , IF_REAL, "Ideality factor of C-S diode current"), |
||||
|
IOP("tsf", HICUM_MOD_TSF , IF_REAL, "Transit time for forward operation of substrate transistor"), |
||||
|
|
||||
|
//Intra-device substrate coupling |
||||
|
IOP("rsu", HICUM_MOD_RSU, IF_REAL, "Substrate series resistance"), |
||||
|
IOP("csu", HICUM_MOD_CSU, IF_REAL, "Substrate shunt capacitance"), |
||||
|
|
||||
|
//Depletion Capacitances |
||||
|
IOP("cjei0", HICUM_MOD_CJEI0 , IF_REAL, "Internal B-E zero-bias depletion capacitance"), |
||||
|
IOP("vdei", HICUM_MOD_VDEI , IF_REAL, "Internal B-E built-in potential"), |
||||
|
IOP("zei", HICUM_MOD_ZEI , IF_REAL, "Internal B-E grading coefficient"), |
||||
|
IOP("ajei", HICUM_MOD_AJEI , IF_REAL, "Ratio of maximum to zero-bias value of internal B-E capacitance"), |
||||
|
IOPR("aljei", HICUM_MOD_AJEI , IF_REAL, "Ratio of maximum to zero-bias value of internal B-E capacitance"), |
||||
|
IOP("cjep0", HICUM_MOD_CJEP0 , IF_REAL, "Peripheral B-E zero-bias depletion capacitance"), |
||||
|
IOP("vdep", HICUM_MOD_VDEP , IF_REAL, "Peripheral B-E built-in potential"), |
||||
|
IOP("zep", HICUM_MOD_ZEP , IF_REAL, "Peripheral B-E grading coefficient"), |
||||
|
IOP("ajep", HICUM_MOD_AJEP , IF_REAL, "Ratio of maximum to zero-bias value of peripheral B-E capacitance"), |
||||
|
IOPR("aljep", HICUM_MOD_AJEP , IF_REAL, "Ratio of maximum to zero-bias value of peripheral B-E capacitance"), |
||||
|
IOP("cjci0", HICUM_MOD_CJCI0 , IF_REAL, "Internal B-C zero-bias depletion capacitance"), |
||||
|
IOP("vdci", HICUM_MOD_VDCI , IF_REAL, "Internal B-C built-in potential"), |
||||
|
IOP("zci", HICUM_MOD_ZCI , IF_REAL, "Internal B-C grading coefficient"), |
||||
|
IOP("vptci", HICUM_MOD_VPTCI , IF_REAL, "Internal B-C punch-through voltage"), |
||||
|
IOP("cjcx0", HICUM_MOD_CJCX0 , IF_REAL, "External B-C zero-bias depletion capacitance"), |
||||
|
IOP("vdcx", HICUM_MOD_VDCX , IF_REAL, "External B-C built-in potential"), |
||||
|
IOP("zcx", HICUM_MOD_ZCX , IF_REAL, "External B-C grading coefficient"), |
||||
|
IOP("vptcx", HICUM_MOD_VPTCX , IF_REAL, "External B-C punch-through voltage"), |
||||
|
IOP("fbcpar", HICUM_MOD_FBCPAR, IF_REAL, "Partitioning factor of parasitic B-C cap"), |
||||
|
IOPR("fbc", HICUM_MOD_FBCPAR, IF_REAL, "Partitioning factor of parasitic B-C cap"), |
||||
|
IOP("fbepar", HICUM_MOD_FBEPAR, IF_REAL, "Partitioning factor of parasitic B-E cap"), |
||||
|
IOPR("fbe", HICUM_MOD_FBEPAR, IF_REAL, "Partitioning factor of parasitic B-E cap"), |
||||
|
IOP("cjs0", HICUM_MOD_CJS0 , IF_REAL, "C-S zero-bias depletion capacitance"), |
||||
|
IOP("vds", HICUM_MOD_VDS , IF_REAL, "C-S built-in potential"), |
||||
|
IOP("zs", HICUM_MOD_ZS , IF_REAL, "C-S grading coefficient"), |
||||
|
IOP("vpts", HICUM_MOD_VPTS , IF_REAL, "C-S punch-through voltage"), |
||||
|
IOP("cscp0", HICUM_MOD_CSCP0 , IF_REAL, "Perimeter S-C zero-bias depletion capacitance"), |
||||
|
IOP("vdsp", HICUM_MOD_VDSP , IF_REAL, "Perimeter S-C built-in potential"), |
||||
|
IOP("zsp", HICUM_MOD_ZSP , IF_REAL, "Perimeter S-C grading coefficient"), |
||||
|
IOP("vptsp", HICUM_MOD_VPTSP , IF_REAL, "Perimeter S-C punch-through voltage"), |
||||
|
|
||||
|
//Diffusion Capacitances |
||||
|
IOP("t0", HICUM_MOD_T0 , IF_REAL, "Low current forward transit time at VBC=0V"), |
||||
|
IOP("dt0h", HICUM_MOD_DT0H , IF_REAL, "Time constant for base and B-C space charge layer width modulation"), |
||||
|
IOP("tbvl", HICUM_MOD_TBVL , IF_REAL, "Time constant for modeling carrier jam at low VCE"), |
||||
|
IOP("tef0", HICUM_MOD_TEF0 , IF_REAL, "Neutral emitter storage time"), |
||||
|
IOP("gtfe", HICUM_MOD_GTFE , IF_REAL, "Exponent factor for current dependence of neutral emitter storage time"), |
||||
|
IOP("thcs", HICUM_MOD_THCS , IF_REAL, "Saturation time constant at high current densities"), |
||||
|
IOP("ahc", HICUM_MOD_AHC , IF_REAL, "Smoothing factor for current dependence of base and collector transit time"), |
||||
|
IOPR("alhc", HICUM_MOD_AHC , IF_REAL, "Smoothing factor for current dependence of base and collector transit time"), |
||||
|
IOP("fthc", HICUM_MOD_FTHC , IF_REAL, "Partitioning factor for base and collector portion"), |
||||
|
IOP("rci0", HICUM_MOD_RCI0 , IF_REAL, "Internal collector resistance at low electric field"), |
||||
|
IOP("vlim", HICUM_MOD_VLIM , IF_REAL, "Voltage separating ohmic and saturation velocity regime"), |
||||
|
IOP("vces", HICUM_MOD_VCES , IF_REAL, "Internal C-E saturation voltage"), |
||||
|
IOP("vpt", HICUM_MOD_VPT , IF_REAL, "Collector punch-through voltage"), // `0' signifies infinity |
||||
|
IOP("aick", HICUM_MOD_AICK , IF_REAL, "Smoothing term for ICK"), |
||||
|
IOP("delck", HICUM_MOD_DELCK, IF_REAL, "Fitting factor for critical current"), |
||||
|
IOP("tr", HICUM_MOD_TR , IF_REAL, "Storage time for inverse operation"), |
||||
|
IOP("vcbar", HICUM_MOD_VCBAR, IF_REAL, "Barrier voltage"), |
||||
|
IOP("icbar", HICUM_MOD_ICBAR, IF_REAL, "Normalization parameter"), |
||||
|
IOP("acbar", HICUM_MOD_ACBAR, IF_REAL, "Smoothing parameter for barrier voltage"), |
||||
|
|
||||
|
//Isolation Capacitances |
||||
|
IOP("cbepar", HICUM_MOD_CBEPAR, IF_REAL, "Total parasitic B-E capacitance"), |
||||
|
IOPR("ceox", HICUM_MOD_CBEPAR, IF_REAL, "Total parasitic B-E capacitance"), |
||||
|
IOP("cbcpar", HICUM_MOD_CBCPAR, IF_REAL, "Total parasitic B-C capacitance"), |
||||
|
IOPR("ccox", HICUM_MOD_CBCPAR, IF_REAL, "Total parasitic B-C capacitance"), |
||||
|
|
||||
|
//Non-quasi-static Effect |
||||
|
IOP("alqf", HICUM_MOD_ALQF, IF_REAL, "Factor for additional delay time of minority charge"), |
||||
|
IOP("alit", HICUM_MOD_ALIT, IF_REAL, "Factor for additional delay time of transfer current"), |
||||
|
IOP("flnqs", HICUM_MOD_FLNQS, IF_INTEGER, "Flag for turning on and off of vertical NQS effect"), |
||||
|
|
||||
|
//Noise |
||||
|
IOP("kf", HICUM_MOD_KF , IF_REAL, "Flicker noise coefficient"), |
||||
|
IOP("af", HICUM_MOD_AF , IF_REAL, "Flicker noise exponent factor"), |
||||
|
IOP("cfbe", HICUM_MOD_CFBE , IF_INTEGER, "Flag for determining where to tag the flicker noise source"), |
||||
|
IOP("flcono", HICUM_MOD_FLCONO, IF_INTEGER, "Flag for turning on and off of correlated noise implementation"), |
||||
|
IOP("kfre", HICUM_MOD_KFRE , IF_REAL, "Emitter resistance flicker noise coefficient"), |
||||
|
IOP("afre", HICUM_MOD_AFRE , IF_REAL, "Emitter resistance flicker noise exponent factor"), |
||||
|
|
||||
|
//Lateral Geometry Scaling (at high current densities) |
||||
|
IOP("latb", HICUM_MOD_LATB, IF_REAL, "Scaling factor for collector minority charge in direction of emitter width"), |
||||
|
IOP("latl", HICUM_MOD_LATL, IF_REAL, "Scaling factor for collector minority charge in direction of emitter length"), |
||||
|
|
||||
|
//Temperature dependence |
||||
|
IOP("vgb", HICUM_MOD_VGB , IF_REAL, "Bandgap voltage extrapolated to 0 K"), |
||||
|
IOP("alt0", HICUM_MOD_ALT0 , IF_REAL, "First order relative TC of parameter T0"), |
||||
|
IOP("kt0", HICUM_MOD_KT0 , IF_REAL, "Second order relative TC of parameter T0"), |
||||
|
IOP("zetaci", HICUM_MOD_ZETACI , IF_REAL, "Temperature exponent for RCI0"), |
||||
|
IOP("alvs", HICUM_MOD_ALVS , IF_REAL, "Relative TC of saturation drift velocity"), |
||||
|
IOP("alces", HICUM_MOD_ALCES , IF_REAL, "Relative TC of VCES"), |
||||
|
IOP("zetarbi", HICUM_MOD_ZETARBI , IF_REAL, "Temperature exponent of internal base resistance"), |
||||
|
IOP("zetarbx", HICUM_MOD_ZETARBX , IF_REAL, "Temperature exponent of external base resistance"), |
||||
|
IOP("zetarcx", HICUM_MOD_ZETARCX , IF_REAL, "Temperature exponent of external collector resistance"), |
||||
|
IOP("zetare", HICUM_MOD_ZETARE , IF_REAL, "Temperature exponent of emitter resistance"), |
||||
|
IOP("zetacx", HICUM_MOD_ZETACX , IF_REAL, "Temperature exponent of mobility in substrate transistor transit time"), |
||||
|
IOP("vge", HICUM_MOD_VGE , IF_REAL, "Effective emitter bandgap voltage"), |
||||
|
IOP("vgc", HICUM_MOD_VGC , IF_REAL, "Effective collector bandgap voltage"), |
||||
|
IOP("vgs", HICUM_MOD_VGS , IF_REAL, "Effective substrate bandgap voltage"), |
||||
|
IOP("f1vg", HICUM_MOD_F1VG , IF_REAL, "Coefficient K1 in T-dependent band-gap equation"), |
||||
|
IOP("f2vg", HICUM_MOD_F2VG , IF_REAL, "Coefficient K2 in T-dependent band-gap equation"), |
||||
|
IOP("zetact", HICUM_MOD_ZETACT , IF_REAL, "Exponent coefficient in transfer current temperature dependence"), |
||||
|
IOP("zetabet", HICUM_MOD_ZETABET , IF_REAL, "Exponent coefficient in B-E junction current temperature dependence"), |
||||
|
IOP("alb", HICUM_MOD_ALB , IF_REAL, "Relative TC of forward current gain for V2.1 model"), |
||||
|
IOP("dvgbe", HICUM_MOD_DVGBE , IF_REAL, "Bandgap difference between B and B-E junction used for hjEi0 and hf0"), |
||||
|
IOP("zetahjei", HICUM_MOD_ZETAHJEI, IF_REAL, "Temperature coefficient for ahjEi"), |
||||
|
IOP("zetavgbe", HICUM_MOD_ZETAVGBE, IF_REAL, "Temperature coefficient for hjEi0"), |
||||
|
|
||||
|
//Self-Heating |
||||
|
IOP("flsh", HICUM_MOD_FLSH , IF_INTEGER, "Flag for turning on and off self-heating effect"), |
||||
|
IOP("rth", HICUM_MOD_RTH , IF_REAL, "Thermal resistance"), |
||||
|
IOP("zetarth", HICUM_MOD_ZETARTH, IF_REAL, "Temperature coefficient for Rth"), |
||||
|
IOP("alrth", HICUM_MOD_ALRTH , IF_REAL, "First order relative TC of parameter Rth"), |
||||
|
IOP("cth", HICUM_MOD_CTH , IF_REAL, "Thermal capacitance"), |
||||
|
|
||||
|
//Compatibility with V2.1 |
||||
|
IOP("flcomp", HICUM_MOD_FLCOMP, IF_REAL, "Flag for compatibility with v2.1 model (0=v2.1)"), |
||||
|
|
||||
|
IOP("vbe_max", HICUM_MOD_VBE_MAX, IF_REAL, "maximum voltage B-E junction"), |
||||
|
IOP("vbc_max", HICUM_MOD_VBC_MAX, IF_REAL, "maximum voltage B-C junction"), |
||||
|
IOP("vce_max", HICUM_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch") |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
char *HICUMnames[] = { |
||||
|
"collector", |
||||
|
"base", |
||||
|
"emitter", |
||||
|
"substrate", |
||||
|
"temp" |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
int HICUMnSize = NUMELEMS(HICUMnames); |
||||
|
int HICUMpTSize = NUMELEMS(HICUMpTable); |
||||
|
int HICUMmPTSize = NUMELEMS(HICUMmPTable); |
||||
|
int HICUMiSize = sizeof(HICUMinstance); |
||||
|
int HICUMmSize = sizeof(HICUMmodel); |
||||
@ -0,0 +1,645 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* Function to load the COMPLEX circuit matrix using the |
||||
|
* small signal parameters saved during a previous DC operating |
||||
|
* point analysis. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
int |
||||
|
HICUMacLoad(GENmodel *inModel, CKTcircuit *ckt) |
||||
|
{ |
||||
|
HICUMinstance *here; |
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
double Ibpei_Vbpei; |
||||
|
double Ibpei_Vrth; |
||||
|
|
||||
|
double Ibiei_Vbiei; |
||||
|
double Ibiei_Vxf; |
||||
|
double Ibiei_Vbici; |
||||
|
double Ibiei_Vrth; |
||||
|
|
||||
|
double Ibici_Vbici; |
||||
|
double Ibici_Vbiei; |
||||
|
double Ibici_Vrth; |
||||
|
|
||||
|
double Ibpci_Vbpci; |
||||
|
double Ibpci_Vrth; |
||||
|
|
||||
|
double Isici_Vsici; |
||||
|
double Isici_Vrth; |
||||
|
|
||||
|
double Iciei_Vbiei; |
||||
|
double Iciei_Vbici; |
||||
|
double Iciei_Vrth; |
||||
|
double Iciei_Vxf2; |
||||
|
|
||||
|
|
||||
|
double Ibpbi_Vbpbi; |
||||
|
double Ibpbi_Vbici; |
||||
|
double Ibpbi_Vbiei; |
||||
|
double Ibpbi_Vrth; |
||||
|
|
||||
|
double Isis_Vsis; |
||||
|
double Irth_Vrth; |
||||
|
double Icic_Vcic, Icic_Vrth; |
||||
|
double Ieie_Veie, Ieie_Vrth; |
||||
|
double Ibbp_Vbbp, Ibbp_Vrth; |
||||
|
|
||||
|
double Ibpsi_Vbpci; |
||||
|
double Ibpsi_Vsici; |
||||
|
double Ibpsi_Vrth; |
||||
|
|
||||
|
double XQrbi_Vbpbi; |
||||
|
double XQrbi_Vbiei; |
||||
|
double XQrbi_Vbici; |
||||
|
double XQrbi_Vrth; |
||||
|
double XQjei_Vbiei; |
||||
|
double XQjei_Vrth; |
||||
|
double XQjci_Vbici; |
||||
|
double XQjci_Vrth; |
||||
|
double XQjep_Vbpei; |
||||
|
double XQjep_Vrth; |
||||
|
double volatile Xqjcx0_t_i_Vbci; |
||||
|
double Xqjcx0_t_i_Vrth; |
||||
|
double volatile Xqjcx0_t_ii_Vbpci; |
||||
|
double Xqjcx0_t_ii_Vrth; |
||||
|
double XQdsu_Vbpci; |
||||
|
double XQdsu_Vsici; |
||||
|
double XQdsu_Vrth; |
||||
|
double XQjs_Vsici; |
||||
|
double XQjs_Vrth; |
||||
|
double XQscp_Vsc; |
||||
|
double XQscp_Vrth; |
||||
|
double XQbepar1_Vbe; |
||||
|
double XQbepar2_Vbpe; |
||||
|
double XQbcpar1_Vbci; |
||||
|
double XQbcpar2_Vbpci; |
||||
|
double XQsu_Vsis; |
||||
|
double XQcth_Vrth; |
||||
|
double XQf_Vbiei; |
||||
|
double XQf_Vbici; |
||||
|
double XQf_Vrth; |
||||
|
double XQf_Vxf; |
||||
|
double XQr_Vrth; |
||||
|
double XQr_Vbiei; |
||||
|
double XQr_Vbici; |
||||
|
|
||||
|
double XQxf_Vxf; |
||||
|
double XQxf1_Vxf1; |
||||
|
double XQxf2_Vxf2; |
||||
|
|
||||
|
double Ixf1_Vbiei; |
||||
|
double Ixf1_Vbici; |
||||
|
double Ixf1_Vxf2 ; |
||||
|
double Ixf1_Vxf1 ; |
||||
|
double Ixf1_Vrth ; |
||||
|
|
||||
|
double Ixf2_Vbiei; |
||||
|
double Ixf2_Vbici; |
||||
|
double Ixf2_Vxf2 ; |
||||
|
double Ixf2_Vxf1 ; |
||||
|
double Ixf2_Vrth ; |
||||
|
|
||||
|
double Ixf_Vbiei ; |
||||
|
double Ixf_Vbici ; |
||||
|
double Ixf_Vxf ; |
||||
|
double Ixf_Vrth ; |
||||
|
|
||||
|
double Ith_Vrth, Ith_Vbiei, Ith_Vbici, Ith_Vbpbi, Ith_Vbpci, Ith_Vbpei, Ith_Vciei, Ith_Vsici, Ith_Vcic, Ith_Vbbp, Ith_Veie; |
||||
|
|
||||
|
/* loop through all the models */ |
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
|
||||
|
int selfheat = ( (model->HICUMflsh > 0) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0)); |
||||
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0)); |
||||
|
|
||||
|
/* loop through all the instances of the model */ |
||||
|
for( here = HICUMinstances(model); here!= NULL; |
||||
|
here = HICUMnextInstance(here)) { |
||||
|
|
||||
|
|
||||
|
// get all derivatives of branch DC currents |
||||
|
if(model->HICUMrcxGiven && model->HICUMrcx != 0) { |
||||
|
Icic_Vcic = 1/here->HICUMrcx_t.rpart; |
||||
|
Icic_Vrth = -*(ckt->CKTstate0 + here->HICUMvcic)/here->HICUMrcx_t.rpart/here->HICUMrcx_t.rpart*here->HICUMrcx_t.dpart; |
||||
|
} else { |
||||
|
Icic_Vcic = 0.0; |
||||
|
Icic_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrbxGiven && model->HICUMrbx != 0) { |
||||
|
Ibbp_Vbbp = 1/here->HICUMrbx_t.rpart; |
||||
|
Ibbp_Vrth = -*(ckt->CKTstate0 + here->HICUMvbbp)/here->HICUMrbx_t.rpart/here->HICUMrbx_t.rpart*here->HICUMrbx_t.dpart; |
||||
|
} else { |
||||
|
Ibbp_Vbbp = 0.0; |
||||
|
Ibbp_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMreGiven && model->HICUMre != 0) { |
||||
|
Ieie_Veie = 1/here->HICUMre_t.rpart; |
||||
|
Ieie_Vrth = -*(ckt->CKTstate0 + here->HICUMveie)/here->HICUMre_t.rpart/here->HICUMre_t.rpart*here->HICUMre_t.dpart; |
||||
|
} else { |
||||
|
Ieie_Veie = 0.0; |
||||
|
Ieie_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrsuGiven && model->HICUMrsu != 0) { |
||||
|
Isis_Vsis = 1/model->HICUMrsu*here->HICUMm; |
||||
|
} else { |
||||
|
Isis_Vsis = 0.0; |
||||
|
} |
||||
|
if(selfheat) { |
||||
|
Irth_Vrth = (1/here->HICUMrth_t.rpart - *(ckt->CKTstate0 + here->HICUMvrth)/(here->HICUMrth_t.rpart*here->HICUMrth_t.rpart) * here->HICUMrth_t.dpart); |
||||
|
} else { |
||||
|
Irth_Vrth = 0.0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
Ibiei_Vbiei = *(ckt->CKTstate0 + here->HICUMibiei_Vbiei); |
||||
|
Ibiei_Vxf = *(ckt->CKTstate0 + here->HICUMibiei_Vxf); |
||||
|
Ibiei_Vbici = *(ckt->CKTstate0 + here->HICUMibiei_Vbici); |
||||
|
Ibiei_Vrth = *(ckt->CKTstate0 + here->HICUMibiei_Vrth); |
||||
|
|
||||
|
Ibpei_Vbpei = *(ckt->CKTstate0 + here->HICUMibpei_Vbpei); |
||||
|
Ibpei_Vrth = *(ckt->CKTstate0 + here->HICUMibpei_Vrth); |
||||
|
|
||||
|
Iciei_Vbiei = *(ckt->CKTstate0 + here->HICUMiciei_Vbiei); |
||||
|
Iciei_Vbici = *(ckt->CKTstate0 + here->HICUMiciei_Vbici); |
||||
|
Iciei_Vrth = *(ckt->CKTstate0 + here->HICUMiciei_Vrth); |
||||
|
Iciei_Vxf2 = *(ckt->CKTstate0 + here->HICUMiciei_Vxf2); |
||||
|
|
||||
|
Ibici_Vbici = *(ckt->CKTstate0 + here->HICUMibici_Vbici); |
||||
|
Ibici_Vbiei = *(ckt->CKTstate0 + here->HICUMibici_Vbiei); |
||||
|
Ibici_Vrth = *(ckt->CKTstate0 + here->HICUMibici_Vrth); |
||||
|
|
||||
|
Ibpbi_Vbpbi = *(ckt->CKTstate0 + here->HICUMibpbi_Vbpbi); |
||||
|
Ibpbi_Vbiei = *(ckt->CKTstate0 + here->HICUMibpbi_Vbiei); |
||||
|
Ibpbi_Vbici = *(ckt->CKTstate0 + here->HICUMibpbi_Vbici); |
||||
|
Ibpbi_Vrth = *(ckt->CKTstate0 + here->HICUMibpbi_Vrth); |
||||
|
|
||||
|
Ibpci_Vbpci = *(ckt->CKTstate0 + here->HICUMibpci_Vbpci); |
||||
|
Ibpci_Vrth = *(ckt->CKTstate0 + here->HICUMibpci_Vrth); |
||||
|
|
||||
|
Isici_Vsici = *(ckt->CKTstate0 + here->HICUMisici_Vsici); |
||||
|
Isici_Vrth = *(ckt->CKTstate0 + here->HICUMisici_Vrth); |
||||
|
|
||||
|
Ibpsi_Vbpci = *(ckt->CKTstate0 + here->HICUMibpsi_Vbpci); |
||||
|
Ibpsi_Vsici = *(ckt->CKTstate0 + here->HICUMibpsi_Vsici); |
||||
|
Ibpsi_Vrth = *(ckt->CKTstate0 + here->HICUMibpsi_Vrth); |
||||
|
|
||||
|
Ith_Vrth = *(ckt->CKTstate0 + here->HICUMith_Vrth); |
||||
|
Ith_Vbiei = *(ckt->CKTstate0 + here->HICUMith_Vbiei); |
||||
|
Ith_Vbici = *(ckt->CKTstate0 + here->HICUMith_Vbici); |
||||
|
Ith_Vbpbi = *(ckt->CKTstate0 + here->HICUMith_Vbpbi); |
||||
|
Ith_Vbpci = *(ckt->CKTstate0 + here->HICUMith_Vbpci); |
||||
|
Ith_Vbpei = *(ckt->CKTstate0 + here->HICUMith_Vbpei); |
||||
|
Ith_Vciei = *(ckt->CKTstate0 + here->HICUMith_Vciei); |
||||
|
Ith_Vsici = *(ckt->CKTstate0 + here->HICUMith_Vsici); |
||||
|
Ith_Vcic = *(ckt->CKTstate0 + here->HICUMith_Vcic); |
||||
|
Ith_Vbbp = *(ckt->CKTstate0 + here->HICUMith_Vbbp); |
||||
|
Ith_Veie = *(ckt->CKTstate0 + here->HICUMith_Veie); |
||||
|
|
||||
|
Ixf1_Vbiei = *(ckt->CKTstate0 + here->HICUMixf1_Vbiei); |
||||
|
Ixf1_Vbici = *(ckt->CKTstate0 + here->HICUMixf1_Vbici); |
||||
|
Ixf1_Vxf2 = *(ckt->CKTstate0 + here->HICUMixf1_Vxf2); |
||||
|
Ixf1_Vxf1 = *(ckt->CKTstate0 + here->HICUMixf1_Vxf1); |
||||
|
Ixf1_Vrth = *(ckt->CKTstate0 + here->HICUMixf1_Vrth); |
||||
|
|
||||
|
Ixf2_Vbiei = *(ckt->CKTstate0 + here->HICUMixf2_Vbiei); |
||||
|
Ixf2_Vbici = *(ckt->CKTstate0 + here->HICUMixf2_Vbici); |
||||
|
Ixf2_Vxf2 = *(ckt->CKTstate0 + here->HICUMixf2_Vxf2); |
||||
|
Ixf2_Vxf1 = *(ckt->CKTstate0 + here->HICUMixf2_Vxf1); |
||||
|
Ixf2_Vrth = *(ckt->CKTstate0 + here->HICUMixf2_Vrth); |
||||
|
|
||||
|
Ixf_Vbiei = *(ckt->CKTstate0 + here->HICUMixf_Vbiei); |
||||
|
Ixf_Vbici = *(ckt->CKTstate0 + here->HICUMixf_Vbici); |
||||
|
Ixf_Vxf = *(ckt->CKTstate0 + here->HICUMixf_Vxf); |
||||
|
Ixf_Vrth = *(ckt->CKTstate0 + here->HICUMixf_Vrth); |
||||
|
|
||||
|
//////////////////////////////////// |
||||
|
////////// The real part ///////// |
||||
|
//////////////////////////////////// |
||||
|
|
||||
|
// Stamp element: Ibiei |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibiei_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ibiei_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -Ibiei_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Ibiei_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibiei_Vbici; |
||||
|
*(here->HICUMemitEICollCIPtr) += Ibiei_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += -Ibiei_Vbici; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Ibiei_Vbici; |
||||
|
|
||||
|
// Stamp element: Ibpei |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpei_Vbpei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ibpei_Vbpei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr) += -Ibpei_Vbpei; |
||||
|
*(here->HICUMemitEIBaseBPPtr) += -Ibpei_Vbpei;; |
||||
|
|
||||
|
// Stamp element: Ibici |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibici_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr) += Ibici_Vbici; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -Ibici_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += -Ibici_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibici_Vbiei; |
||||
|
*(here->HICUMcollCIEmitEIPtr) += Ibici_Vbiei; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -Ibici_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -Ibici_Vbiei; |
||||
|
|
||||
|
// Stamp element: Iciei |
||||
|
*(here->HICUMcollCIBaseBIPtr) += Iciei_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Iciei_Vbiei; |
||||
|
*(here->HICUMcollCIEmitEIPtr) += -Iciei_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Iciei_Vbiei; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += Iciei_Vbici; |
||||
|
*(here->HICUMemitEICollCIPtr) += Iciei_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr) += -Iciei_Vbici; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Iciei_Vbici; |
||||
|
if (nqs) { |
||||
|
*(here->HICUMcollCIXf2Ptr) += Iciei_Vxf2; |
||||
|
*(here->HICUMemitEIXf2Ptr) += -Iciei_Vxf2; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// Stamp element: Ibpci |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpci_Vbpci; |
||||
|
*(here->HICUMcollCICollCIPtr) += Ibpci_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpci_Vbpci; |
||||
|
*(here->HICUMcollCIBaseBPPtr) += -Ibpci_Vbpci; |
||||
|
|
||||
|
// Stamp element: Rcx |
||||
|
*(here->HICUMcollCollPtr) += Icic_Vcic; |
||||
|
*(here->HICUMcollCICollCIPtr) += Icic_Vcic; |
||||
|
*(here->HICUMcollCICollPtr) += -Icic_Vcic; |
||||
|
*(here->HICUMcollCollCIPtr) += -Icic_Vcic; |
||||
|
|
||||
|
// Stamp element: Rbx |
||||
|
*(here->HICUMbaseBasePtr) += Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBPBasePtr) += -Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBaseBPPtr) += -Ibbp_Vbbp; |
||||
|
|
||||
|
// Stamp element: Re |
||||
|
*(here->HICUMemitEmitPtr) += Ieie_Veie; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ieie_Veie; |
||||
|
*(here->HICUMemitEIEmitPtr) += -Ieie_Veie; |
||||
|
*(here->HICUMemitEmitEIPtr) += -Ieie_Veie; |
||||
|
|
||||
|
// Stamp element: Ibpbi |
||||
|
if (here->HICUMrbi>0.0) { |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += -Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBPPtr) += -Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr) += -Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += -Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += -Ibpbi_Vbici; |
||||
|
}; |
||||
|
|
||||
|
// Stamp element: Isici |
||||
|
*(here->HICUMsubsSISubsSIPtr) += Isici_Vsici; |
||||
|
*(here->HICUMcollCICollCIPtr) += Isici_Vsici; |
||||
|
*(here->HICUMsubsSICollCIPtr) += -Isici_Vsici; |
||||
|
*(here->HICUMcollCISubsSIPtr) += -Isici_Vsici;; |
||||
|
|
||||
|
// Stamp element: Ibpsi |
||||
|
*(here->HICUMbaseBPSubsSIPtr) += Ibpsi_Vsici; |
||||
|
*(here->HICUMsubsSICollCIPtr) += Ibpsi_Vsici; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpsi_Vsici; |
||||
|
*(here->HICUMsubsSISubsSIPtr) += -Ibpsi_Vsici; |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpsi_Vbpci; |
||||
|
*(here->HICUMsubsSICollCIPtr) += Ibpsi_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpsi_Vbpci; |
||||
|
*(here->HICUMsubsSIBaseBPPtr) += -Ibpsi_Vbpci;; |
||||
|
|
||||
|
// Stamp element: Rsu |
||||
|
*(here->HICUMsubsSubsPtr) += Isis_Vsis; |
||||
|
*(here->HICUMsubsSISubsSIPtr) += Isis_Vsis; |
||||
|
*(here->HICUMsubsSISubsPtr) += -Isis_Vsis; |
||||
|
*(here->HICUMsubsSubsSIPtr) += -Isis_Vsis; |
||||
|
|
||||
|
if (nqs) { |
||||
|
//Ixf1 |
||||
|
*(here->HICUMxf1BaseBIPtr) += +Ixf1_Vbiei; |
||||
|
*(here->HICUMxf1EmitEIPtr) += -Ixf1_Vbiei; |
||||
|
*(here->HICUMxf1BaseBIPtr) += +Ixf1_Vbici; |
||||
|
*(here->HICUMxf1CollCIPtr) += -Ixf1_Vbici; |
||||
|
*(here->HICUMxf1Xf2Ptr) += +Ixf1_Vxf2; |
||||
|
*(here->HICUMxf1Xf1Ptr) += +Ixf1_Vxf1; |
||||
|
//Ixf2 |
||||
|
*(here->HICUMxf2BaseBIPtr) += +Ixf2_Vbiei; |
||||
|
*(here->HICUMxf2EmitEIPtr) += -Ixf2_Vbiei; |
||||
|
*(here->HICUMxf2BaseBIPtr) += +Ixf2_Vbici; |
||||
|
*(here->HICUMxf2CollCIPtr) += -Ixf2_Vbici; |
||||
|
*(here->HICUMxf2Xf2Ptr) += +Ixf2_Vxf2; |
||||
|
*(here->HICUMxf2Xf1Ptr) += +Ixf2_Vxf1; |
||||
|
//Ixf |
||||
|
*(here->HICUMxfBaseBIPtr) += +Ixf_Vbiei; |
||||
|
*(here->HICUMxfEmitEIPtr) += -Ixf_Vbiei; |
||||
|
*(here->HICUMxfBaseBIPtr) += +Ixf_Vbici; |
||||
|
*(here->HICUMxfCollCIPtr) += -Ixf_Vbici; |
||||
|
*(here->HICUMxfXfPtr) += +Ixf_Vxf; |
||||
|
} |
||||
|
|
||||
|
//////////////////////////////////// |
||||
|
////////// The complex part ////// |
||||
|
//////////////////////////////////// |
||||
|
|
||||
|
//Qrbi |
||||
|
XQrbi_Vbpbi = *(ckt->CKTstate0 + here->HICUMcqrbi) * ckt->CKTomega; |
||||
|
XQrbi_Vbiei = here->HICUMqrbi_Vbiei * ckt->CKTomega; |
||||
|
XQrbi_Vbici = here->HICUMqrbi_Vbici * ckt->CKTomega; |
||||
|
XQrbi_Vrth = here->HICUMqrbi_Vrth * ckt->CKTomega; |
||||
|
//Qjei |
||||
|
XQjei_Vbiei = *(ckt->CKTstate0 + here->HICUMcqjei) * ckt->CKTomega; |
||||
|
XQjei_Vrth = here->HICUMqjei_Vrth * ckt->CKTomega; |
||||
|
//Qf |
||||
|
XQf_Vbiei = *(ckt->CKTstate0 + here->HICUMcqf) * ckt->CKTomega; |
||||
|
XQf_Vbici = here->HICUMqf_Vbici * ckt->CKTomega; |
||||
|
XQf_Vrth = here->HICUMqf_Vrth * ckt->CKTomega; |
||||
|
XQf_Vxf = here->HICUMqf_Vxf * ckt->CKTomega; |
||||
|
//Qr |
||||
|
XQr_Vbici = *(ckt->CKTstate0 + here->HICUMcqr) * ckt->CKTomega; |
||||
|
XQr_Vbiei = here->HICUMqr_Vbiei * ckt->CKTomega; |
||||
|
XQr_Vrth = here->HICUMqr_Vrth * ckt->CKTomega; |
||||
|
//Qjci |
||||
|
XQjci_Vbici = *(ckt->CKTstate0 + here->HICUMcqjci) * ckt->CKTomega; |
||||
|
XQjci_Vrth = here->HICUMqjci_Vrth * ckt->CKTomega; |
||||
|
//Qjep |
||||
|
XQjep_Vbpei = *(ckt->CKTstate0 + here->HICUMcqjep) * ckt->CKTomega; |
||||
|
XQjep_Vrth = here->HICUMqjep_Vrth * ckt->CKTomega; |
||||
|
//Qjcx_i |
||||
|
Xqjcx0_t_i_Vbci = *(ckt->CKTstate0 + here->HICUMcqcx0_t_i) * ckt->CKTomega; |
||||
|
Xqjcx0_t_i_Vrth = here->HICUMqjcx0_i_Vrth * ckt->CKTomega; |
||||
|
//Qjcx_ii |
||||
|
Xqjcx0_t_ii_Vbpci = *(ckt->CKTstate0 + here->HICUMcqcx0_t_ii) * ckt->CKTomega; |
||||
|
Xqjcx0_t_ii_Vrth = here->HICUMqjcx0_ii_Vrth * ckt->CKTomega; |
||||
|
//Qdsu |
||||
|
XQdsu_Vbpci = *(ckt->CKTstate0 + here->HICUMcqdsu) * ckt->CKTomega; |
||||
|
XQdsu_Vsici = here->HICUMqdsu_Vsici * ckt->CKTomega; |
||||
|
XQdsu_Vrth = here->HICUMqdsu_Vrth * ckt->CKTomega; |
||||
|
//Qjs |
||||
|
XQjs_Vsici = *(ckt->CKTstate0 + here->HICUMcqjs) * ckt->CKTomega; |
||||
|
XQjs_Vrth = here->HICUMqjs_Vrth * ckt->CKTomega; |
||||
|
//Qscp |
||||
|
XQscp_Vsc = *(ckt->CKTstate0 + here->HICUMcqscp) * ckt->CKTomega; |
||||
|
XQscp_Vrth = here->HICUMqscp_Vrth * ckt->CKTomega; |
||||
|
//Qbepar1 |
||||
|
XQbepar1_Vbe = *(ckt->CKTstate0 + here->HICUMcqbepar1) * ckt->CKTomega; |
||||
|
//Qbepar2 |
||||
|
XQbepar2_Vbpe = *(ckt->CKTstate0 + here->HICUMcqbepar2) * ckt->CKTomega; |
||||
|
//Qbcpar1 |
||||
|
XQbcpar1_Vbci = *(ckt->CKTstate0 + here->HICUMcqbcpar1) * ckt->CKTomega; |
||||
|
//Qbcpar2 |
||||
|
XQbcpar2_Vbpci = *(ckt->CKTstate0 + here->HICUMcqbcpar2) * ckt->CKTomega; |
||||
|
//Qsu |
||||
|
XQsu_Vsis = *(ckt->CKTstate0 + here->HICUMcqsu) * ckt->CKTomega; |
||||
|
//Qcth |
||||
|
XQcth_Vrth = *(ckt->CKTstate0 + here->HICUMcqcth) * ckt->CKTomega; |
||||
|
//Qxf |
||||
|
XQxf_Vxf = *(ckt->CKTstate0 + here->HICUMcqxf) * ckt->CKTomega; |
||||
|
XQxf1_Vxf1 = *(ckt->CKTstate0 + here->HICUMcqxf1) * ckt->CKTomega; |
||||
|
XQxf2_Vxf2 = *(ckt->CKTstate0 + here->HICUMcqxf2) * ckt->CKTomega; |
||||
|
|
||||
|
//Qrbi f_bp=+ f_bi=- |
||||
|
if (here->HICUMrbi>0.0) { |
||||
|
*(here->HICUMbaseBPBaseBPPtr + 1) += XQrbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += XQrbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += -XQrbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBPPtr + 1) += -XQrbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += XQrbi_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr + 1) += XQrbi_Vbiei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr + 1) += -XQrbi_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += -XQrbi_Vbiei; |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += XQrbi_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr + 1) += XQrbi_Vbici; |
||||
|
*(here->HICUMbaseBPCollCIPtr + 1) += -XQrbi_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += -XQrbi_Vbici; |
||||
|
} |
||||
|
//Qjei |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += XQjei_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr + 1) += XQjei_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr + 1) += -XQjei_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr + 1) += -XQjei_Vbiei; |
||||
|
//Qf f_Bi=+ f_Ei =- |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQf_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr +1) += XQf_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr +1) += -XQf_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr +1) += -XQf_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQf_Vbici; |
||||
|
*(here->HICUMemitEICollCIPtr +1) += XQf_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQf_Vbici; |
||||
|
*(here->HICUMemitEIBaseBIPtr +1) += -XQf_Vbici; |
||||
|
if (nqs) { |
||||
|
*(here->HICUMbaseBIXfPtr +1) += XQf_Vxf; |
||||
|
*(here->HICUMemitEIXfPtr +1) += -XQf_Vxf; |
||||
|
} |
||||
|
//Qjci |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQjci_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQjci_Vbici; |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQjci_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQjci_Vbici; |
||||
|
//Qr f_bi = + f_ci=- |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQr_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQr_Vbici; |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQr_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQr_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQr_Vbiei; |
||||
|
*(here->HICUMcollCIEmitEIPtr +1) += XQr_Vbiei; |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQr_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr +1) += -XQr_Vbiei; |
||||
|
//Qjep |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQjep_Vbpei; |
||||
|
*(here->HICUMemitEIEmitEIPtr +1) += XQjep_Vbpei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr +1) += -XQjep_Vbpei; |
||||
|
*(here->HICUMemitEIBaseBPPtr +1) += -XQjep_Vbpei; |
||||
|
//Qjcx_i |
||||
|
*(here->HICUMbaseBasePtr +1) += Xqjcx0_t_i_Vbci; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += Xqjcx0_t_i_Vbci; |
||||
|
*(here->HICUMbaseCollCIPtr +1) += -Xqjcx0_t_i_Vbci; |
||||
|
*(here->HICUMcollCIBasePtr +1) += -Xqjcx0_t_i_Vbci; |
||||
|
//Qjcx_ii |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += Xqjcx0_t_ii_Vbpci; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += Xqjcx0_t_ii_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -Xqjcx0_t_ii_Vbpci; |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -Xqjcx0_t_ii_Vbpci; |
||||
|
//Qdsu f_bp=+ f_ci=- |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQdsu_Vbpci; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQdsu_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQdsu_Vbpci; |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -XQdsu_Vbpci; |
||||
|
*(here->HICUMbaseBPSubsSIPtr +1) += XQdsu_Vsici; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQdsu_Vsici; |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQdsu_Vsici; |
||||
|
*(here->HICUMcollCISubsSIPtr +1) += -XQdsu_Vsici; |
||||
|
//Qjs |
||||
|
*(here->HICUMsubsSISubsSIPtr +1) += XQjs_Vsici; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQjs_Vsici; |
||||
|
*(here->HICUMsubsSICollCIPtr +1) += -XQjs_Vsici; |
||||
|
*(here->HICUMcollCISubsSIPtr +1) += -XQjs_Vsici; |
||||
|
//Qscp |
||||
|
*(here->HICUMsubsSubsPtr + 1) += XQscp_Vsc; |
||||
|
*(here->HICUMcollCollPtr + 1) += XQscp_Vsc; |
||||
|
*(here->HICUMcollSubsPtr + 1) += -XQscp_Vsc; |
||||
|
*(here->HICUMsubsCollPtr + 1) += -XQscp_Vsc; |
||||
|
//Qbepar1 |
||||
|
*(here->HICUMbaseBasePtr + 1) += XQbepar1_Vbe; |
||||
|
*(here->HICUMemitEmitPtr + 1) += XQbepar1_Vbe; |
||||
|
*(here->HICUMbaseEmitPtr + 1) += -XQbepar1_Vbe; |
||||
|
*(here->HICUMemitBasePtr + 1) += -XQbepar1_Vbe; |
||||
|
//Qbepar2 |
||||
|
*(here->HICUMbaseBPBaseBPPtr + 1) += XQbepar2_Vbpe; |
||||
|
*(here->HICUMemitEmitPtr + 1) += XQbepar2_Vbpe; |
||||
|
*(here->HICUMemitBaseBPPtr + 1) += -XQbepar2_Vbpe; |
||||
|
*(here->HICUMbaseBPEmitPtr + 1) += -XQbepar2_Vbpe; |
||||
|
//Qbcpar1 |
||||
|
*(here->HICUMbaseBasePtr + 1) += XQbcpar1_Vbci; |
||||
|
*(here->HICUMcollCICollCIPtr + 1) += XQbcpar1_Vbci; |
||||
|
*(here->HICUMbaseCollCIPtr + 1) += -XQbcpar1_Vbci; |
||||
|
*(here->HICUMcollCIBasePtr + 1) += -XQbcpar1_Vbci; |
||||
|
//Qbcpar2 |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQbcpar2_Vbpci; |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQbcpar2_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQbcpar2_Vbpci; |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -XQbcpar2_Vbpci; |
||||
|
//Qsu |
||||
|
*(here->HICUMsubsSubsPtr + 1) += XQsu_Vsis; |
||||
|
*(here->HICUMsubsSISubsSIPtr + 1) += XQsu_Vsis; |
||||
|
*(here->HICUMsubsSISubsPtr + 1) += -XQsu_Vsis; |
||||
|
*(here->HICUMsubsSubsSIPtr + 1) += -XQsu_Vsis; |
||||
|
if (nqs) { |
||||
|
//Qxf1 |
||||
|
*(here->HICUMxf1Xf1Ptr + 1) += +XQxf1_Vxf1; |
||||
|
//Qxf2 |
||||
|
*(here->HICUMxf2Xf2Ptr + 1) += +XQxf2_Vxf2; |
||||
|
//Qxf |
||||
|
*(here->HICUMxfXfPtr + 1) += +XQxf_Vxf; |
||||
|
} |
||||
|
|
||||
|
// Stamps with SH |
||||
|
if (selfheat) { |
||||
|
// Stamp element: Ibiei f_Bi = + f_Ei = - |
||||
|
*(here->HICUMbaseBItempPtr) += Ibiei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Ibiei_Vrth; |
||||
|
// Stamp element: Ibpei f_Bp = + f_Ei = - |
||||
|
// with respect to Potential Vrth |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Ibpei_Vrth; |
||||
|
// Stamp element: Ibici f_Bi = + f_Ci = - |
||||
|
*(here->HICUMbaseBItempPtr) += Ibici_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Ibici_Vrth; |
||||
|
// Stamp element: Iciei f_Ci = + f_Ei = - |
||||
|
*(here->HICUMcollCItempPtr) += Iciei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Iciei_Vrth; |
||||
|
// Stamp element: Ibpci f_Bp = + f_Ci = - |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpci_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Ibpci_Vrth; |
||||
|
// Stamp element: Rcx f_Ci = + f_C = - |
||||
|
*(here->HICUMcollCItempPtr) += Icic_Vrth; |
||||
|
*(here->HICUMcollTempPtr) += -Icic_Vrth; |
||||
|
// Stamp element: Rbx f_B = + f_Bp = - |
||||
|
*(here->HICUMbaseTempPtr) += Ibbp_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr) += -Ibbp_Vrth; |
||||
|
// Stamp element: Re f_Ei = + f_E = - |
||||
|
*(here->HICUMemitEItempPtr) += Ieie_Vrth; |
||||
|
*(here->HICUMemitTempPtr) += -Ieie_Vrth; |
||||
|
// Stamp element: Rbi f_Bp = + f_Bi = - |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpbi_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr) += -Ibpbi_Vrth; |
||||
|
// Stamp element: Isici f_Si = + f_Ci = - |
||||
|
*(here->HICUMsubsSItempPtr) += Isici_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Isici_Vrth; |
||||
|
// Branch: bpsi, Stamp element: Its |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpsi_Vrth; |
||||
|
*(here->HICUMsubsSItempPtr) += -Ibpsi_Vrth; |
||||
|
if (nqs) { |
||||
|
// Stamp element: Ixf f_xf = + |
||||
|
*(here->HICUMxfTempPtr) += Ixf_Vrth; |
||||
|
// Stamp element: Ixf1 f_xf1 = + |
||||
|
*(here->HICUMxf1TempPtr) += Ixf1_Vrth; |
||||
|
// Stamp element: Ixf2 f_xf2 = + |
||||
|
*(here->HICUMxf2TempPtr) += Ixf2_Vrth; |
||||
|
} |
||||
|
|
||||
|
// Stamp element: Rth f_T = + |
||||
|
*(here->HICUMtempTempPtr) += Irth_Vrth; |
||||
|
|
||||
|
// Stamp element: Ith f_T = - Ith |
||||
|
// with respect to Potential Vrth |
||||
|
*(here->HICUMtempTempPtr) += -Ith_Vrth; |
||||
|
// with respect to Potential Vbiei |
||||
|
*(here->HICUMtempBaseBIPtr) += -Ith_Vbiei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vbiei; |
||||
|
// with respect to Potential Vbici |
||||
|
*(here->HICUMtempBaseBIPtr) += -Ith_Vbici; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vbici; |
||||
|
// with respect to Potential Vciei |
||||
|
*(here->HICUMtempCollCIPtr) += -Ith_Vciei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vciei; |
||||
|
// with respect to Potential Vbpei |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vbpei; |
||||
|
// with respect to Potential Vbpci |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpci; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vbpci; |
||||
|
// with respect to Potential Vsici |
||||
|
*(here->HICUMtempSubsSIPtr) += -Ith_Vsici; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vsici; |
||||
|
// with respect to Potential Vbpbi |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpbi; |
||||
|
*(here->HICUMtempBaseBIPtr) += +Ith_Vbpbi; |
||||
|
// with respect to Potential Vcic |
||||
|
*(here->HICUMtempCollCIPtr) += -Ith_Vcic; |
||||
|
*(here->HICUMtempCollPtr) += +Ith_Vcic; |
||||
|
// with respect to Potential Vbbp |
||||
|
*(here->HICUMtempBasePtr) += -Ith_Vbbp; |
||||
|
*(here->HICUMtempBaseBPPtr) += +Ith_Vbbp; |
||||
|
// with respect to Potential Veie |
||||
|
*(here->HICUMtempEmitEIPtr) += -Ith_Veie; |
||||
|
*(here->HICUMtempEmitPtr) += +Ith_Veie; |
||||
|
|
||||
|
//the charges |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQrbi_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += -XQrbi_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQjei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQjei_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQf_Vrth; |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQf_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQr_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQr_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQjci_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQjci_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +XQjep_Vrth; |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQjep_Vrth; |
||||
|
*(here->HICUMbaseTempPtr + 1) += +Xqjcx0_t_i_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -Xqjcx0_t_i_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +Xqjcx0_t_ii_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -Xqjcx0_t_ii_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +XQdsu_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQdsu_Vrth; |
||||
|
*(here->HICUMsubsSItempPtr + 1) += +XQjs_Vrth; |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQjs_Vrth; |
||||
|
*(here->HICUMsubsTempPtr + 1) += +XQscp_Vrth; |
||||
|
*(here->HICUMcollTempPtr + 1) += -XQscp_Vrth; |
||||
|
*(here->HICUMtempTempPtr + 1) += +XQcth_Vrth; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,251 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine gives access to the internal device |
||||
|
* parameters for HICUMs |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/const.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/ifsim.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
/*ARGSUSED*/ |
||||
|
int |
||||
|
HICUMask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue *select) |
||||
|
{ |
||||
|
HICUMinstance *here = (HICUMinstance*)instPtr; |
||||
|
|
||||
|
NG_IGNORE(select); |
||||
|
double g_be; |
||||
|
IFvalue IC, IB, RPIi, RPIx, GMi; |
||||
|
IFvalue CPIi, CPIx, CMUi, CMUx; |
||||
|
IFvalue rcx_t, re_t, rb, BETAAC; |
||||
|
|
||||
|
switch(which) { |
||||
|
case HICUM_AREA: |
||||
|
value->rValue = here->HICUMarea; |
||||
|
return(OK); |
||||
|
case HICUM_OFF: |
||||
|
value->iValue = here->HICUMoff; |
||||
|
return(OK); |
||||
|
case HICUM_TEMP: |
||||
|
value->rValue = here->HICUMtemp - CONSTCtoK; |
||||
|
return(OK); |
||||
|
case HICUM_M: |
||||
|
value->rValue = here->HICUMm; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_COLLNODE: |
||||
|
value->iValue = here->HICUMcollNode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_BASENODE: |
||||
|
value->iValue = here->HICUMbaseNode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_EMITNODE: |
||||
|
value->iValue = here->HICUMemitNode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_SUBSNODE: |
||||
|
value->iValue = here->HICUMsubsNode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_COLLCINODE: |
||||
|
value->iValue = here->HICUMcollCINode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_BASEBPNODE: |
||||
|
value->iValue = here->HICUMbaseBPNode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_BASEBINODE: |
||||
|
value->iValue = here->HICUMbaseBINode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_EMITEINODE: |
||||
|
value->iValue = here->HICUMemitEINode; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_SUBSSINODE: |
||||
|
value->iValue = here->HICUMsubsSINode; |
||||
|
return(OK); |
||||
|
/* voltages */ |
||||
|
case HICUM_QUEST_VBE: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMbaseNode)-*(ckt->CKTstate0 + here->HICUMemitNode); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VBBP: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMbaseNode)-*(ckt->CKTstate0 + here->HICUMbaseBPNode); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VBC: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMbaseNode)-*(ckt->CKTstate0 + here->HICUMcollNode); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VCE: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMcollNode)-*(ckt->CKTstate0 + here->HICUMemitNode); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VSC: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMcollNode)-*(ckt->CKTstate0 + here->HICUMsubsNode); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VBIEI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMvbiei); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VBPBI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMvbpbi); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VBICI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMvbici); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_VCIEI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMvbiei) - *(ckt->CKTstate0 + here->HICUMvbici); |
||||
|
return(OK); |
||||
|
/* currents */ |
||||
|
case HICUM_QUEST_CC: |
||||
|
// value->rValue = 0.0; |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMiciei) - |
||||
|
*(ckt->CKTstate0 + here->HICUMibici) - |
||||
|
*(ckt->CKTstate0 + here->HICUMibpci) - |
||||
|
*(ckt->CKTstate0 + here->HICUMisici); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CB: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMibiei) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibici) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpci) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpsi); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CE: |
||||
|
value->rValue = - *(ckt->CKTstate0 + here->HICUMibiei) - |
||||
|
*(ckt->CKTstate0 + here->HICUMibpei) - |
||||
|
*(ckt->CKTstate0 + here->HICUMiciei); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CS: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMisici) - |
||||
|
*(ckt->CKTstate0 + here->HICUMibpsi); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CAVL: |
||||
|
value->rValue = here->HICUMiavl; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CBEI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMibiei); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CBCI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMibici); |
||||
|
return(OK); |
||||
|
|
||||
|
/* resistances */ |
||||
|
case HICUM_QUEST_RCX_T: |
||||
|
value->rValue = here->HICUMrcx_t.rpart; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RE_T: |
||||
|
value->rValue = here->HICUMre_t.rpart; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_IT: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMiciei); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RBI: |
||||
|
value->rValue = here->HICUMrbi; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RB: |
||||
|
value->rValue = here->HICUMrbi + here->HICUMrbx_t.rpart; |
||||
|
return(OK); |
||||
|
/* transconductances and capacitances */ |
||||
|
case HICUM_QUEST_BETADC: |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CC, &IC, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CB, &IB, select); |
||||
|
if (IB.rValue != 0.0) { |
||||
|
value->rValue = IC.rValue/IB.rValue; |
||||
|
} else { |
||||
|
value->rValue = 0.0; |
||||
|
} |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_GMI: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMiciei_Vbiei); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_GMS: |
||||
|
value->rValue = *(ckt->CKTstate0 + here->HICUMibpsi_Vbpci); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RPII: |
||||
|
value->rValue = 1/( *(ckt->CKTstate0 + here->HICUMibiei_Vbiei) ); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RPIX: |
||||
|
value->rValue = 1/( *(ckt->CKTstate0 + here->HICUMibpei_Vbpei) ); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RMUI: |
||||
|
value->rValue = 1/( *(ckt->CKTstate0 + here->HICUMibici_Vbici) + ckt->CKTgmin); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_RMUX: |
||||
|
value->rValue = 1/( *(ckt->CKTstate0 + here->HICUMibpci_Vbpci) + ckt->CKTgmin); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_ROI: |
||||
|
value->rValue = 1/( *(ckt->CKTstate0 + here->HICUMiciei_Vbiei) + ckt->CKTgmin); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CPII: |
||||
|
value->rValue = here->HICUMcapjei + here->HICUMcapdeix; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CPIX: |
||||
|
value->rValue = here->HICUMcapjep + here->HICUMcbepar_scaled; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CMUI: |
||||
|
value->rValue = here->HICUMcapjci + here->HICUMcapdci; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CMUX: |
||||
|
value->rValue = here->HICUMcapjcx_t_i + here->HICUMcapjcx_t_ii + here->HICUMcbcpar_scaled + here->HICUMcapdsu; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CCS: |
||||
|
value->rValue = here->HICUMcapjs + here->HICUMcapscp; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_CRBI: |
||||
|
value->rValue = here->HICUMcaprbi; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_BETAAC: |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_RPII, &RPIi, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_RPIX, &RPIx, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_GMI, &GMi, select); |
||||
|
g_be = 1/(RPIi.rValue + RPIx.rValue); |
||||
|
if (g_be > 0.0) { |
||||
|
value->rValue = GMi.rValue/g_be; |
||||
|
} else { |
||||
|
value->rValue = 0.0; |
||||
|
} |
||||
|
return(OK); |
||||
|
/* transit time */ |
||||
|
case HICUM_QUEST_TF: |
||||
|
value->rValue = here->HICUMtf; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_FT: |
||||
|
// FT = GMi/(2*`M_PI*(CPIi+CPIx+CMUi+CMUx+(rcx_t+re_t+(re_t+rb)/BETAAC)*GMi*(CMUi+CMUx))); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_GMI, &GMi, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CPII, &CPIi, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CPIX, &CPIx, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CMUI, &CMUi, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_CMUX, &CMUx, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_RCX_T, &rcx_t, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_RE_T, &re_t, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_RB, &rb, select); |
||||
|
HICUMask(ckt, instPtr, HICUM_QUEST_BETAAC, &BETAAC, select); |
||||
|
|
||||
|
value->rValue = GMi.rValue/( |
||||
|
2 * M_PI * ( |
||||
|
CPIi.rValue + CPIx.rValue + |
||||
|
CMUi.rValue + CMUx.rValue + |
||||
|
(rcx_t.rValue + re_t.rValue + (re_t.rValue + rb.rValue)/BETAAC.rValue) |
||||
|
) * GMi.rValue * ( |
||||
|
CMUi.rValue + CMUx.rValue |
||||
|
) |
||||
|
); |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_ICK: |
||||
|
value->rValue = here->HICUMick; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_POWER: |
||||
|
value->rValue = here->HICUMpterm; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_TK: |
||||
|
value->rValue = here->HICUMtemp; |
||||
|
return(OK); |
||||
|
case HICUM_QUEST_DTSH: |
||||
|
value->rValue = here->HICUMdtemp_sh; |
||||
|
return(OK); |
||||
|
default: |
||||
|
return(E_BADPARM); |
||||
|
} |
||||
|
/* NOTREACHED */ |
||||
|
} |
||||
@ -0,0 +1,221 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine performs the device convergence test for |
||||
|
* HICUMs in the circuit. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
int |
||||
|
HICUMconvTest(GENmodel *inModel, CKTcircuit *ckt) |
||||
|
{ |
||||
|
HICUMinstance *here; |
||||
|
HICUMmodel *model = (HICUMmodel *) inModel; |
||||
|
double tol; |
||||
|
double delvbiei; |
||||
|
double delvbici; |
||||
|
double delvbpei; |
||||
|
double delvbpbi; |
||||
|
double delvbpci; |
||||
|
double delvsici; |
||||
|
double delvrth; |
||||
|
double delvciei; |
||||
|
double delvcic; |
||||
|
double delvbbp; |
||||
|
double delveie; |
||||
|
|
||||
|
double ibieihat; |
||||
|
double ibicihat; |
||||
|
double icieihat; |
||||
|
double ibpeihat; |
||||
|
double ibpbihat; |
||||
|
double ibpcihat; |
||||
|
double ibpsihat; |
||||
|
double isicihat; |
||||
|
double volatile ithhat; |
||||
|
|
||||
|
|
||||
|
double Vbiei, Vbici, Vciei, Vbpei, Vbpbi, Vbpci, Vbci, Vsici, Vrth, Vcic, Vbbp, Veie; |
||||
|
double Ibiei, Ibici, Iciei, Ibpei, Ibpbi, Ibpci, Ibpsi, Isici, Ith; |
||||
|
|
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
for(here=HICUMinstances(model);here!=NULL;here = HICUMnextInstance(here)) { |
||||
|
|
||||
|
Vbci = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollCINode)); |
||||
|
Vbiei= model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBINode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMemitEINode)); |
||||
|
Vbici = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBINode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollCINode)); |
||||
|
Vbpei = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBPNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMemitEINode)); |
||||
|
Vbpbi = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBPNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBINode)); |
||||
|
Vbpci = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBPNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollCINode)); |
||||
|
Vsici = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMsubsSINode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollCINode)); |
||||
|
Vcic = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollCINode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMcollNode)); |
||||
|
Vbbp = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMbaseBPNode)); |
||||
|
Veie = model->HICUMtype*( |
||||
|
*(ckt->CKTrhsOld+here->HICUMemitNode)- |
||||
|
*(ckt->CKTrhsOld+here->HICUMemitEINode)); |
||||
|
|
||||
|
Vciei = Vbiei - Vbici; |
||||
|
Vrth = model->HICUMtype*(*(ckt->CKTrhsOld+here->HICUMtempNode)); |
||||
|
|
||||
|
delvrth = Vrth - *(ckt->CKTstate0 + here->HICUMvrth); |
||||
|
delvbiei = Vbiei - *(ckt->CKTstate0 + here->HICUMvbiei); |
||||
|
delvbici = Vbici - *(ckt->CKTstate0 + here->HICUMvbici); |
||||
|
delvbpei = Vbpei - *(ckt->CKTstate0 + here->HICUMvbpei); |
||||
|
delvbpbi = Vbpbi - *(ckt->CKTstate0 + here->HICUMvbpbi); |
||||
|
delvbpci = Vbpci - *(ckt->CKTstate0 + here->HICUMvbpci); |
||||
|
delvsici = Vsici - *(ckt->CKTstate0 + here->HICUMvsici); |
||||
|
delvciei = delvbiei-delvbici; |
||||
|
delvcic = Vcic - *(ckt->CKTstate0 + here->HICUMvcic); |
||||
|
delvbbp = Vbbp - *(ckt->CKTstate0 + here->HICUMvbbp); |
||||
|
delveie = Veie - *(ckt->CKTstate0 + here->HICUMveie); |
||||
|
|
||||
|
//todo: maybe add ibiei_Vxf |
||||
|
ibieihat = *(ckt->CKTstate0 + here->HICUMibiei) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibiei_Vbiei)*delvbiei + |
||||
|
*(ckt->CKTstate0 + here->HICUMibiei_Vrth)*delvrth + |
||||
|
*(ckt->CKTstate0 + here->HICUMibiei_Vbici)*delvbici; |
||||
|
ibicihat = *(ckt->CKTstate0 + here->HICUMibici) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibici_Vbici)*delvbici+ |
||||
|
*(ckt->CKTstate0 + here->HICUMibici_Vrth)*delvrth+ |
||||
|
*(ckt->CKTstate0 + here->HICUMibici_Vbiei)*delvbiei; |
||||
|
icieihat = *(ckt->CKTstate0 + here->HICUMiciei) + |
||||
|
*(ckt->CKTstate0 + here->HICUMiciei_Vbiei)*delvbiei + |
||||
|
*(ckt->CKTstate0 + here->HICUMiciei_Vrth)*delvrth + |
||||
|
*(ckt->CKTstate0 + here->HICUMiciei_Vbici)*delvbici; |
||||
|
ibpeihat = *(ckt->CKTstate0 + here->HICUMibpei) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpei_Vrth)*delvrth+ |
||||
|
*(ckt->CKTstate0 + here->HICUMibpei_Vbpei)*delvbpei; |
||||
|
ibpbihat = *(ckt->CKTstate0 + here->HICUMibpbi) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpbi_Vbiei)*delvbiei + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpbi_Vrth)*delvrth + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpbi_Vbici)*delvbici; |
||||
|
ibpcihat = *(ckt->CKTstate0 + here->HICUMibpci) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpci_Vrth)*delvrth+ |
||||
|
*(ckt->CKTstate0 + here->HICUMibpci_Vbpci)*delvbici; |
||||
|
ibpsihat = *(ckt->CKTstate0 + here->HICUMibpsi) + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpsi_Vbpci)*delvbpci + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpsi_Vrth)*delvrth + |
||||
|
*(ckt->CKTstate0 + here->HICUMibpsi_Vsici)*delvsici; |
||||
|
isicihat = *(ckt->CKTstate0 + here->HICUMisici) + |
||||
|
*(ckt->CKTstate0 + here->HICUMisici_Vrth)*delvrth+ |
||||
|
*(ckt->CKTstate0 + here->HICUMisici_Vsici)*delvsici; |
||||
|
ithhat = *(ckt->CKTstate0 + here->HICUMith) + |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vrth)*delvrth+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbiei)*delvbiei+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbici)*delvbici+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbpbi)*delvbpbi+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbpci)*delvbpci+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbpei)*delvbpei+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vciei)*delvciei+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vsici)*delvsici+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vcic)*delvcic+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Vbbp)*delvbbp+ |
||||
|
*(ckt->CKTstate0 + here->HICUMith_Veie)*delveie; |
||||
|
|
||||
|
Ibiei = *(ckt->CKTstate0 + here->HICUMibiei); |
||||
|
Ibici = *(ckt->CKTstate0 + here->HICUMibici); |
||||
|
Iciei = *(ckt->CKTstate0 + here->HICUMiciei); |
||||
|
Ibpei = *(ckt->CKTstate0 + here->HICUMibpei); |
||||
|
Ibpbi = *(ckt->CKTstate0 + here->HICUMibpbi); |
||||
|
Ibpci = *(ckt->CKTstate0 + here->HICUMibpci); |
||||
|
Ibpsi = *(ckt->CKTstate0 + here->HICUMibpsi); |
||||
|
Isici = *(ckt->CKTstate0 + here->HICUMisici); |
||||
|
Ith = *(ckt->CKTstate0 + here->HICUMith); |
||||
|
|
||||
|
/* |
||||
|
* check convergence |
||||
|
*/ |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibieihat),fabs(Ibiei))+ckt->CKTabstol; |
||||
|
if (fabs(ibieihat-Ibiei) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibicihat),fabs(Ibici))+ckt->CKTabstol; |
||||
|
if (fabs(ibicihat-Ibici) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(icieihat),fabs(Iciei))+ckt->CKTabstol; |
||||
|
if (fabs(icieihat-Iciei) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibpeihat),fabs(Ibpei))+ckt->CKTabstol; |
||||
|
if (fabs(ibpeihat-Ibpei) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibpbihat),fabs(Ibpbi))+ckt->CKTabstol; |
||||
|
if (fabs(ibpbihat-Ibpbi) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibpcihat),fabs(Ibpci))+ckt->CKTabstol; |
||||
|
if (fabs(ibpcihat-Ibpci) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ibpsihat),fabs(Ibpsi))+ckt->CKTabstol; |
||||
|
if (fabs(ibpsihat-Ibpsi) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(isicihat),fabs(Isici))+ckt->CKTabstol; |
||||
|
if (fabs(isicihat-Isici) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} else { |
||||
|
tol=ckt->CKTreltol*MAX(fabs(ithhat),fabs(Ith))+ckt->CKTabstol; |
||||
|
if (fabs(ithhat-Ith) > tol) { |
||||
|
ckt->CKTnoncon++; |
||||
|
ckt->CKTtroubleElt = (GENinstance *) here; |
||||
|
return(OK); /* no reason to continue - we've failed... */ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
1180
src/spicelib/devices/hicum2/hicum2defs.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,27 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
#ifndef __HICUMEXT_H |
||||
|
#define __HICUMEXT_H |
||||
|
|
||||
|
|
||||
|
extern int HICUMacLoad(GENmodel *,CKTcircuit*); |
||||
|
extern int HICUMask(CKTcircuit *,GENinstance*,int,IFvalue*,IFvalue*); |
||||
|
extern int HICUMconvTest(GENmodel*,CKTcircuit*); |
||||
|
extern int HICUMdelete(GENinstance*); |
||||
|
extern int HICUMgetic(GENmodel*,CKTcircuit*); |
||||
|
//extern int HICUMload(GENmodel*,CKTcircuit*);//moved to hicumL2.hpp |
||||
|
extern int HICUMmAsk(CKTcircuit*,GENmodel*,int,IFvalue*); |
||||
|
extern int HICUMmParam(int,IFvalue*,GENmodel*); |
||||
|
extern int HICUMparam(int,IFvalue*,GENinstance*,IFvalue*); |
||||
|
extern int HICUMpzLoad(GENmodel*, CKTcircuit*, SPcomplex*); |
||||
|
extern int HICUMsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); |
||||
|
extern int HICUMunsetup(GENmodel*,CKTcircuit*); |
||||
|
// extern int HICUMtemp(GENmodel*,CKTcircuit*); // moved to hicum2temp.hpp |
||||
|
extern int HICUMtrunc(GENmodel*,CKTcircuit*,double*); |
||||
|
extern int HICUMnoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); |
||||
|
extern int HICUMsoaCheck(CKTcircuit *, GENmodel *); |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,51 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine gets the device initial conditions for the HICUMs |
||||
|
* from the RHS vector |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
|
||||
|
int |
||||
|
HICUMgetic(GENmodel *inModel, CKTcircuit *ckt) |
||||
|
{ |
||||
|
|
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
HICUMinstance *here; |
||||
|
/* |
||||
|
* grab initial conditions out of rhs array. User specified, so use |
||||
|
* external nodes to get values |
||||
|
*/ |
||||
|
|
||||
|
for( ; model ; model = HICUMnextModel(model)) { |
||||
|
for(here = HICUMinstances(model); here ; here = HICUMnextInstance(here)) { |
||||
|
|
||||
|
if(!here->HICUMicVBEGiven) { |
||||
|
here->HICUMicVBE = |
||||
|
*(ckt->CKTrhs + here->HICUMbaseNode) - |
||||
|
*(ckt->CKTrhs + here->HICUMemitNode); |
||||
|
} |
||||
|
if(!here->HICUMicVCEGiven) { |
||||
|
here->HICUMicVCE = |
||||
|
*(ckt->CKTrhs + here->HICUMcollNode) - |
||||
|
*(ckt->CKTrhs + here->HICUMemitNode); |
||||
|
} |
||||
|
if(!here->HICUMicVCSGiven) { |
||||
|
here->HICUMicVCS = |
||||
|
*(ckt->CKTrhs + here->HICUMcollNode) - |
||||
|
*(ckt->CKTrhs + here->HICUMsubsNode); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
|
||||
|
#include "ngspice/config.h" |
||||
|
|
||||
|
#include "ngspice/devdefs.h" |
||||
|
|
||||
|
#include "hicum2itf.h" |
||||
|
#include "hicum2ext.h" |
||||
|
#include "hicum2init.h" |
||||
|
#include "hicumL2.hpp" |
||||
|
#include "hicumL2temp.hpp" |
||||
|
|
||||
|
|
||||
|
SPICEdev HICUMinfo = { |
||||
|
.DEVpublic = { |
||||
|
.name = "hicum2", |
||||
|
.description = "High Current Model for BJT", |
||||
|
.terms = &HICUMnSize, |
||||
|
.numNames = &HICUMnSize, |
||||
|
.termNames = HICUMnames, |
||||
|
.numInstanceParms = &HICUMpTSize, |
||||
|
.instanceParms = HICUMpTable, |
||||
|
.numModelParms = &HICUMmPTSize, |
||||
|
.modelParms = HICUMmPTable, |
||||
|
.flags = DEV_DEFAULT, |
||||
|
|
||||
|
#ifdef XSPICE |
||||
|
.cm_func = NULL, |
||||
|
.num_conn = 0, |
||||
|
.conn = NULL, |
||||
|
.num_param = 0, |
||||
|
.param = NULL, |
||||
|
.num_inst_var = 0, |
||||
|
.inst_var = NULL, |
||||
|
#endif |
||||
|
}, |
||||
|
|
||||
|
.DEVparam = HICUMparam, |
||||
|
.DEVmodParam = HICUMmParam, |
||||
|
.DEVload = HICUMload, |
||||
|
.DEVsetup = HICUMsetup, |
||||
|
.DEVunsetup = HICUMunsetup, |
||||
|
.DEVpzSetup = HICUMsetup, |
||||
|
.DEVtemperature = HICUMtemp, |
||||
|
.DEVtrunc = HICUMtrunc, |
||||
|
.DEVfindBranch = NULL, |
||||
|
.DEVacLoad = HICUMacLoad, |
||||
|
.DEVaccept = NULL, |
||||
|
.DEVdestroy = NULL, |
||||
|
.DEVmodDelete = NULL, |
||||
|
.DEVdelete = NULL, |
||||
|
.DEVsetic = HICUMgetic, |
||||
|
.DEVask = HICUMask, |
||||
|
.DEVmodAsk = HICUMmAsk, |
||||
|
.DEVpzLoad = HICUMpzLoad, |
||||
|
.DEVconvTest = HICUMconvTest, |
||||
|
.DEVsenSetup = NULL, |
||||
|
.DEVsenLoad = NULL, |
||||
|
.DEVsenUpdate = NULL, |
||||
|
.DEVsenAcLoad = NULL, |
||||
|
.DEVsenPrint = NULL, |
||||
|
.DEVsenTrunc = NULL, |
||||
|
.DEVdisto = NULL, |
||||
|
.DEVnoise = HICUMnoise, |
||||
|
.DEVsoaCheck = HICUMsoaCheck, |
||||
|
.DEVinstSize = &HICUMiSize, |
||||
|
.DEVmodSize = &HICUMmSize, |
||||
|
|
||||
|
#ifdef CIDER |
||||
|
.DEVdump = NULL, |
||||
|
.DEVacct = NULL, |
||||
|
#endif |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
SPICEdev * |
||||
|
get_hicum_info(void) |
||||
|
{ |
||||
|
return &HICUMinfo; |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
|
||||
|
#ifndef _HICUMINIT_H |
||||
|
#define _HICUMINIT_H |
||||
|
|
||||
|
extern IFparm HICUMpTable[ ]; |
||||
|
extern IFparm HICUMmPTable[ ]; |
||||
|
extern char *HICUMnames[ ]; |
||||
|
extern int HICUMpTSize; |
||||
|
extern int HICUMmPTSize; |
||||
|
extern int HICUMnSize; |
||||
|
extern int HICUMiSize; |
||||
|
extern int HICUMmSize; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,11 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
#ifndef DEV_HICUM |
||||
|
#define DEV_HICUM |
||||
|
|
||||
|
extern SPICEdev *get_hicum_info(void); |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,460 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/const.h" |
||||
|
#include "ngspice/ifsim.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "ngspice/devdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
#define MIN_R 0.001 |
||||
|
|
||||
|
/*ARGSUSED*/ |
||||
|
int |
||||
|
HICUMmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel*)instPtr; |
||||
|
|
||||
|
NG_IGNORE(ckt); |
||||
|
|
||||
|
switch(which) { |
||||
|
|
||||
|
//Circuit simulator specific parameters |
||||
|
case HICUM_MOD_TYPE: |
||||
|
if (model->HICUMtype == NPN) |
||||
|
value->sValue = "npn"; |
||||
|
else |
||||
|
value->sValue = "pnp"; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TNOM: |
||||
|
value->rValue = model->HICUMtnom; |
||||
|
return(OK); |
||||
|
|
||||
|
case HICUM_MOD_VERSION : |
||||
|
value->sValue = model->HICUMversion; |
||||
|
return(OK); |
||||
|
|
||||
|
//Transfer current |
||||
|
case HICUM_MOD_C10: |
||||
|
value->rValue = model->HICUMc10; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_QP0: |
||||
|
value->rValue = model->HICUMqp0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ICH: |
||||
|
value->rValue = model->HICUMich; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_HF0: |
||||
|
value->rValue = model->HICUMhf0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_HFE: |
||||
|
value->rValue = model->HICUMhfe; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_HFC: |
||||
|
value->rValue = model->HICUMhfc; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_HJEI: |
||||
|
value->rValue = model->HICUMhjei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AHJEI: |
||||
|
value->rValue = model->HICUMahjei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RHJEI: |
||||
|
value->rValue = model->HICUMrhjei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_HJCI: |
||||
|
value->rValue = model->HICUMhjci; |
||||
|
return(OK); |
||||
|
|
||||
|
//Base-Emitter diode: |
||||
|
case HICUM_MOD_IBEIS: |
||||
|
value->rValue = model->HICUMibeis; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MBEI: |
||||
|
value->rValue = model->HICUMmbei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IREIS: |
||||
|
value->rValue = model->HICUMireis; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MREI: |
||||
|
value->rValue = model->HICUMmrei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IBEPS: |
||||
|
value->rValue = model->HICUMibeps; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MBEP: |
||||
|
value->rValue = model->HICUMmbep; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IREPS: |
||||
|
value->rValue = model->HICUMireps; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MREP: |
||||
|
value->rValue = model->HICUMmrep; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MCF: |
||||
|
value->rValue = model->HICUMmcf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TBHREC: |
||||
|
value->rValue = model->HICUMtbhrec; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IBCIS: |
||||
|
value->rValue = model->HICUMibcis; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MBCI: |
||||
|
value->rValue = model->HICUMmbci; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IBCXS: |
||||
|
value->rValue = model->HICUMibcxs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MBCX: |
||||
|
value->rValue = model->HICUMmbcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_IBETS: |
||||
|
value->rValue = model->HICUMibets; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ABET: |
||||
|
value->rValue = model->HICUMabet; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TUNODE: |
||||
|
value->rValue = model->HICUMtunode = value->iValue; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FAVL: |
||||
|
value->rValue = model->HICUMfavl; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_QAVL: |
||||
|
value->rValue = model->HICUMqavl; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_KAVL: |
||||
|
value->rValue = model->HICUMkavl; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALFAV: |
||||
|
value->rValue = model->HICUMalfav; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALQAV: |
||||
|
value->rValue = model->HICUMalqav; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALKAV: |
||||
|
value->rValue = model->HICUMalkav; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RBI0: |
||||
|
value->rValue = model->HICUMrbi0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RBX: |
||||
|
value->rValue = model->HICUMrbx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FGEO: |
||||
|
value->rValue = model->HICUMfgeo; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FDQR0: |
||||
|
value->rValue = model->HICUMfdqr0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FCRBI: |
||||
|
value->rValue = model->HICUMfcrbi; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FQI: |
||||
|
value->rValue = model->HICUMfqi; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RE: |
||||
|
value->rValue = model->HICUMre; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RCX: |
||||
|
value->rValue = model->HICUMrcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ITSS: |
||||
|
value->rValue = model->HICUMitss; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MSF: |
||||
|
value->rValue = model->HICUMmsf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ISCS: |
||||
|
value->rValue = model->HICUMiscs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_MSC: |
||||
|
value->rValue = model->HICUMmsc; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TSF: |
||||
|
value->rValue = model->HICUMtsf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RSU: |
||||
|
value->rValue = model->HICUMrsu; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CSU: |
||||
|
value->rValue = model->HICUMcsu; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CJEI0: |
||||
|
value->rValue = model->HICUMcjei0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDEI: |
||||
|
value->rValue = model->HICUMvdei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZEI: |
||||
|
value->rValue = model->HICUMzei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AJEI: |
||||
|
value->rValue = model->HICUMajei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CJEP0: |
||||
|
value->rValue = model->HICUMcjep0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDEP: |
||||
|
value->rValue = model->HICUMvdep; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZEP: |
||||
|
value->rValue = model->HICUMzep; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AJEP: |
||||
|
value->rValue = model->HICUMajep; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CJCI0: |
||||
|
value->rValue = model->HICUMcjci0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDCI: |
||||
|
value->rValue = model->HICUMvdci; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZCI: |
||||
|
value->rValue = model->HICUMzci; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VPTCI: |
||||
|
value->rValue = model->HICUMvptci; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CJCX0: |
||||
|
value->rValue = model->HICUMcjcx0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDCX: |
||||
|
value->rValue = model->HICUMvdcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZCX: |
||||
|
value->rValue = model->HICUMzcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VPTCX: |
||||
|
value->rValue = model->HICUMvptcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FBCPAR: |
||||
|
value->rValue = model->HICUMfbcpar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FBEPAR: |
||||
|
value->rValue = model->HICUMfbepar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CJS0: |
||||
|
value->rValue = model->HICUMcjs0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDS: |
||||
|
value->rValue = model->HICUMvds; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZS: |
||||
|
value->rValue = model->HICUMzs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VPTS: |
||||
|
value->rValue = model->HICUMvpts; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CSCP0: |
||||
|
value->rValue = model->HICUMcscp0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VDSP: |
||||
|
value->rValue = model->HICUMvdsp; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZSP: |
||||
|
value->rValue = model->HICUMzsp; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VPTSP: |
||||
|
value->rValue = model->HICUMvptsp; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_T0: |
||||
|
value->rValue = model->HICUMt0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_DT0H: |
||||
|
value->rValue = model->HICUMdt0h; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TBVL: |
||||
|
value->rValue = model->HICUMtbvl; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TEF0: |
||||
|
value->rValue = model->HICUMtef0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_GTFE: |
||||
|
value->rValue = model->HICUMgtfe; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_THCS: |
||||
|
value->rValue = model->HICUMthcs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AHC: |
||||
|
value->rValue = model->HICUMahc; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FTHC: |
||||
|
value->rValue = model->HICUMfthc; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RCI0: |
||||
|
value->rValue = model->HICUMrci0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VLIM: |
||||
|
value->rValue = model->HICUMvlim; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VCES: |
||||
|
value->rValue = model->HICUMvces; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VPT: |
||||
|
value->rValue = model->HICUMvpt; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AICK: |
||||
|
value->rValue = model->HICUMaick; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_DELCK: |
||||
|
value->rValue = model->HICUMdelck; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_TR: |
||||
|
value->rValue = model->HICUMtr; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VCBAR: |
||||
|
value->rValue = model->HICUMvcbar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ICBAR: |
||||
|
value->rValue = model->HICUMicbar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ACBAR: |
||||
|
value->rValue = model->HICUMacbar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CBEPAR: |
||||
|
value->rValue = model->HICUMcbepar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CBCPAR: |
||||
|
value->rValue = model->HICUMcbcpar; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALQF: |
||||
|
value->rValue = model->HICUMalqf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALIT: |
||||
|
value->rValue = model->HICUMalit; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FLNQS: |
||||
|
value->iValue = model->HICUMflnqs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_KF: |
||||
|
value->rValue = model->HICUMkf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AF: |
||||
|
value->rValue = model->HICUMaf; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CFBE: |
||||
|
value->rValue = model->HICUMcfbe; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FLCONO: |
||||
|
value->iValue = model->HICUMflcono; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_KFRE: |
||||
|
value->rValue = model->HICUMkfre; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_AFRE: |
||||
|
value->rValue = model->HICUMafre; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_LATB: |
||||
|
value->rValue = model->HICUMlatb; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_LATL: |
||||
|
value->rValue = model->HICUMlatl; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VGB: |
||||
|
value->rValue = model->HICUMvgb; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALT0: |
||||
|
value->rValue = model->HICUMalt0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_KT0: |
||||
|
value->rValue = model->HICUMkt0; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETACI: |
||||
|
value->rValue = model->HICUMzetaci; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALVS: |
||||
|
value->rValue = model->HICUMalvs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALCES: |
||||
|
value->rValue = model->HICUMalces; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETARBI: |
||||
|
value->rValue = model->HICUMzetarbi; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETARBX: |
||||
|
value->rValue = model->HICUMzetarbx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETARCX: |
||||
|
value->rValue = model->HICUMzetarcx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETARE: |
||||
|
value->rValue = model->HICUMzetare; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETACX: |
||||
|
value->rValue = model->HICUMzetacx; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VGE: |
||||
|
value->rValue = model->HICUMvge; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VGC: |
||||
|
value->rValue = model->HICUMvgc; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VGS: |
||||
|
value->rValue = model->HICUMvgs; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_F1VG: |
||||
|
value->rValue = model->HICUMf1vg; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_F2VG: |
||||
|
value->rValue = model->HICUMf2vg; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETACT: |
||||
|
value->rValue = model->HICUMzetact; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETABET: |
||||
|
value->rValue = model->HICUMzetabet; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALB: |
||||
|
value->rValue = model->HICUMalb; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_DVGBE: |
||||
|
value->rValue = model->HICUMdvgbe; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETAHJEI: |
||||
|
value->rValue = model->HICUMzetahjei; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETAVGBE: |
||||
|
value->rValue = model->HICUMzetavgbe; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FLSH: |
||||
|
value->iValue = model->HICUMflsh; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_RTH: |
||||
|
value->rValue = model->HICUMrth; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ZETARTH: |
||||
|
value->rValue = model->HICUMzetarth; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_ALRTH: |
||||
|
value->rValue = model->HICUMalrth; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_CTH: |
||||
|
value->rValue = model->HICUMcth; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_FLCOMP: |
||||
|
value->rValue = model->HICUMflcomp; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VBE_MAX: |
||||
|
value->rValue = model->HICUMvbeMax; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VBC_MAX: |
||||
|
value->rValue = model->HICUMvbcMax; |
||||
|
return(OK); |
||||
|
case HICUM_MOD_VCE_MAX: |
||||
|
value->rValue = model->HICUMvceMax; |
||||
|
return(OK); |
||||
|
|
||||
|
default: |
||||
|
return(E_BADPARM); |
||||
|
} |
||||
|
/* NOTREACHED */ |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,634 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine sets model parameters for |
||||
|
* HICUMs in the circuit. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/const.h" |
||||
|
#include "ngspice/ifsim.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
int |
||||
|
HICUMmParam(int param, IFvalue *value, GENmodel *inModel) |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
|
||||
|
switch(param) { |
||||
|
|
||||
|
//Circuit simulator specific parameters |
||||
|
|
||||
|
case HICUM_MOD_NPN: |
||||
|
if(value->iValue) { |
||||
|
model->HICUMtype = NPN; |
||||
|
} |
||||
|
break; |
||||
|
case HICUM_MOD_PNP: |
||||
|
if(value->iValue) { |
||||
|
model->HICUMtype = PNP; |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case HICUM_MOD_TNOM: |
||||
|
model->HICUMtnom = value->rValue+CONSTCtoK; |
||||
|
model->HICUMtnomGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
case HICUM_MOD_VERSION : |
||||
|
model->HICUMversion = value->sValue; |
||||
|
model->HICUMversionGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Transfer current |
||||
|
case HICUM_MOD_C10: |
||||
|
model->HICUMc10 = value->rValue; |
||||
|
model->HICUMc10Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_QP0: |
||||
|
model->HICUMqp0 = value->rValue; |
||||
|
model->HICUMqp0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ICH: |
||||
|
model->HICUMich = value->rValue; |
||||
|
model->HICUMichGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_HF0: |
||||
|
model->HICUMhf0 = value->rValue; |
||||
|
model->HICUMhf0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_HFE: |
||||
|
model->HICUMhfe = value->rValue; |
||||
|
model->HICUMhfeGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_HFC: |
||||
|
model->HICUMhfc = value->rValue; |
||||
|
model->HICUMhfcGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_HJEI: |
||||
|
model->HICUMhjei = value->rValue; |
||||
|
model->HICUMhjeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AHJEI: |
||||
|
model->HICUMahjei = value->rValue; |
||||
|
model->HICUMahjeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RHJEI: |
||||
|
model->HICUMrhjei = value->rValue; |
||||
|
model->HICUMrhjeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_HJCI: |
||||
|
model->HICUMhjci = value->rValue; |
||||
|
model->HICUMhjciGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Base-Emitter diode: |
||||
|
case HICUM_MOD_IBEIS: |
||||
|
model->HICUMibeis = value->rValue; |
||||
|
model->HICUMibeisGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MBEI: |
||||
|
model->HICUMmbei = value->rValue; |
||||
|
model->HICUMmbeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_IREIS: |
||||
|
model->HICUMireis = value->rValue; |
||||
|
model->HICUMireisGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MREI: |
||||
|
model->HICUMmrei = value->rValue; |
||||
|
model->HICUMmreiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_IBEPS: |
||||
|
model->HICUMibeps = value->rValue; |
||||
|
model->HICUMibepsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MBEP: |
||||
|
model->HICUMmbep = value->rValue; |
||||
|
model->HICUMmbepGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_IREPS: |
||||
|
model->HICUMireps = value->rValue; |
||||
|
model->HICUMirepsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MREP: |
||||
|
model->HICUMmrep = value->rValue; |
||||
|
model->HICUMmrepGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MCF: |
||||
|
model->HICUMmcf = value->rValue; |
||||
|
model->HICUMmcfGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Transit time for excess recombination current at b-c barrier |
||||
|
case HICUM_MOD_TBHREC: |
||||
|
model->HICUMtbhrec = value->rValue; |
||||
|
model->HICUMtbhrecGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Base-Collector diode currents |
||||
|
case HICUM_MOD_IBCIS: |
||||
|
model->HICUMibcis = value->rValue; |
||||
|
model->HICUMibcisGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MBCI: |
||||
|
model->HICUMmbci = value->rValue; |
||||
|
model->HICUMmbciGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_IBCXS: |
||||
|
model->HICUMibcxs = value->rValue; |
||||
|
model->HICUMibcxsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MBCX: |
||||
|
model->HICUMmbcx = value->rValue; |
||||
|
model->HICUMmbcxGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Base-Emitter tunneling current |
||||
|
case HICUM_MOD_IBETS: |
||||
|
model->HICUMibets = value->rValue; |
||||
|
model->HICUMibetsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ABET: |
||||
|
model->HICUMabet = value->rValue; |
||||
|
model->HICUMabetGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_TUNODE: |
||||
|
model->HICUMtunode = value->iValue; |
||||
|
model->HICUMtunodeGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Base-Collector avalanche current |
||||
|
case HICUM_MOD_FAVL: |
||||
|
model->HICUMfavl = value->rValue; |
||||
|
model->HICUMfavlGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_QAVL: |
||||
|
model->HICUMqavl = value->rValue; |
||||
|
model->HICUMqavlGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_KAVL: |
||||
|
model->HICUMkavl = value->rValue; |
||||
|
model->HICUMkavlGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALFAV: |
||||
|
model->HICUMalfav = value->rValue; |
||||
|
model->HICUMalfavGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALQAV: |
||||
|
model->HICUMalqav = value->rValue; |
||||
|
model->HICUMalqavGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALKAV: |
||||
|
model->HICUMalkav = value->rValue; |
||||
|
model->HICUMalkavGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Series resistances |
||||
|
case HICUM_MOD_RBI0: |
||||
|
model->HICUMrbi0 = value->rValue; |
||||
|
model->HICUMrbi0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RBX: |
||||
|
model->HICUMrbx = value->rValue; |
||||
|
model->HICUMrbxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FGEO: |
||||
|
model->HICUMfgeo = value->rValue; |
||||
|
model->HICUMfgeoGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FDQR0: |
||||
|
model->HICUMfdqr0 = value->rValue; |
||||
|
model->HICUMfdqr0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FCRBI: |
||||
|
model->HICUMfcrbi = value->rValue; |
||||
|
model->HICUMfcrbiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FQI: |
||||
|
model->HICUMfqi = value->rValue; |
||||
|
model->HICUMfqiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RE: |
||||
|
model->HICUMre = value->rValue; |
||||
|
model->HICUMreGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RCX: |
||||
|
model->HICUMrcx = value->rValue; |
||||
|
model->HICUMrcxGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Substrate transistor |
||||
|
case HICUM_MOD_ITSS: |
||||
|
model->HICUMitss = value->rValue; |
||||
|
model->HICUMitssGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MSF: |
||||
|
model->HICUMmsf = value->rValue; |
||||
|
model->HICUMmsfGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ISCS: |
||||
|
model->HICUMiscs = value->rValue; |
||||
|
model->HICUMiscsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_MSC: |
||||
|
model->HICUMmsc = value->rValue; |
||||
|
model->HICUMmscGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_TSF: |
||||
|
model->HICUMtsf = value->rValue; |
||||
|
model->HICUMtsfGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Intra-device substrate coupling |
||||
|
case HICUM_MOD_RSU: |
||||
|
model->HICUMrsu = value->rValue; |
||||
|
model->HICUMrsuGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CSU: |
||||
|
model->HICUMcsu = value->rValue; |
||||
|
model->HICUMcsuGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Depletion Capacitances |
||||
|
case HICUM_MOD_CJEI0: |
||||
|
model->HICUMcjei0 = value->rValue; |
||||
|
model->HICUMcjei0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDEI: |
||||
|
model->HICUMvdei = value->rValue; |
||||
|
model->HICUMvdeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZEI: |
||||
|
model->HICUMzei = value->rValue; |
||||
|
model->HICUMzeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AJEI: |
||||
|
model->HICUMajei = value->rValue; |
||||
|
model->HICUMajeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CJEP0: |
||||
|
model->HICUMcjep0 = value->rValue; |
||||
|
model->HICUMcjep0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDEP: |
||||
|
model->HICUMvdep = value->rValue; |
||||
|
model->HICUMvdepGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZEP: |
||||
|
model->HICUMzep = value->rValue; |
||||
|
model->HICUMzepGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AJEP: |
||||
|
model->HICUMajep = value->rValue; |
||||
|
model->HICUMajepGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CJCI0: |
||||
|
model->HICUMcjci0 = value->rValue; |
||||
|
model->HICUMcjci0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDCI: |
||||
|
model->HICUMvdci = value->rValue; |
||||
|
model->HICUMvdciGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZCI: |
||||
|
model->HICUMzci = value->rValue; |
||||
|
model->HICUMzciGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VPTCI: |
||||
|
model->HICUMvptci = value->rValue; |
||||
|
model->HICUMvptciGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CJCX0: |
||||
|
model->HICUMcjcx0 = value->rValue; |
||||
|
model->HICUMcjcx0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDCX: |
||||
|
model->HICUMvdcx = value->rValue; |
||||
|
model->HICUMvdcxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZCX: |
||||
|
model->HICUMzcx = value->rValue; |
||||
|
model->HICUMzcxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VPTCX: |
||||
|
model->HICUMvptcx = value->rValue; |
||||
|
model->HICUMvptcxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FBCPAR: |
||||
|
model->HICUMfbcpar = value->rValue; |
||||
|
model->HICUMfbcparGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FBEPAR: |
||||
|
model->HICUMfbepar = value->rValue; |
||||
|
model->HICUMfbeparGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CJS0: |
||||
|
model->HICUMcjs0 = value->rValue; |
||||
|
model->HICUMcjs0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDS: |
||||
|
model->HICUMvds = value->rValue; |
||||
|
model->HICUMvdsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZS: |
||||
|
model->HICUMzs = value->rValue; |
||||
|
model->HICUMzsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VPTS: |
||||
|
model->HICUMvpts = value->rValue; |
||||
|
model->HICUMvptsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CSCP0: |
||||
|
model->HICUMcscp0 = value->rValue; |
||||
|
model->HICUMcscp0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VDSP: |
||||
|
model->HICUMvdsp = value->rValue; |
||||
|
model->HICUMvdspGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZSP: |
||||
|
model->HICUMzsp = value->rValue; |
||||
|
model->HICUMzspGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VPTSP: |
||||
|
model->HICUMvptsp = value->rValue; |
||||
|
model->HICUMvptspGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Diffusion Capacitances |
||||
|
case HICUM_MOD_T0: |
||||
|
model->HICUMt0 = value->rValue; |
||||
|
model->HICUMt0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_DT0H: |
||||
|
model->HICUMdt0h = value->rValue; |
||||
|
model->HICUMdt0hGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_TBVL: |
||||
|
model->HICUMtbvl = value->rValue; |
||||
|
model->HICUMtbvlGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_TEF0: |
||||
|
model->HICUMtef0 = value->rValue; |
||||
|
model->HICUMtef0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_GTFE: |
||||
|
model->HICUMgtfe = value->rValue; |
||||
|
model->HICUMgtfeGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_THCS: |
||||
|
model->HICUMthcs = value->rValue; |
||||
|
model->HICUMthcsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AHC: |
||||
|
model->HICUMahc = value->rValue; |
||||
|
model->HICUMahcGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FTHC: |
||||
|
model->HICUMfthc = value->rValue; |
||||
|
model->HICUMfthcGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RCI0: |
||||
|
model->HICUMrci0 = value->rValue; |
||||
|
model->HICUMrci0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VLIM: |
||||
|
model->HICUMvlim = value->rValue; |
||||
|
model->HICUMvlimGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VCES: |
||||
|
model->HICUMvces = value->rValue; |
||||
|
model->HICUMvcesGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VPT: |
||||
|
model->HICUMvpt = value->rValue; |
||||
|
model->HICUMvptGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AICK: |
||||
|
model->HICUMaick = value->rValue; |
||||
|
model->HICUMaickGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_DELCK: |
||||
|
model->HICUMdelck = value->rValue; |
||||
|
model->HICUMdelckGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_TR: |
||||
|
model->HICUMtr = value->rValue; |
||||
|
model->HICUMtrGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VCBAR: |
||||
|
model->HICUMvcbar = value->rValue; |
||||
|
model->HICUMvcbarGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ICBAR: |
||||
|
model->HICUMicbar = value->rValue; |
||||
|
model->HICUMicbarGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ACBAR: |
||||
|
model->HICUMacbar = value->rValue; |
||||
|
model->HICUMacbarGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Isolation Capacitances |
||||
|
case HICUM_MOD_CBEPAR: |
||||
|
model->HICUMcbepar = value->rValue; |
||||
|
model->HICUMcbeparGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CBCPAR: |
||||
|
model->HICUMcbcpar = value->rValue; |
||||
|
model->HICUMcbcparGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Non-quasi-static Effect |
||||
|
case HICUM_MOD_ALQF: |
||||
|
model->HICUMalqf = value->rValue; |
||||
|
model->HICUMalqfGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALIT: |
||||
|
model->HICUMalit = value->rValue; |
||||
|
model->HICUMalitGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FLNQS: |
||||
|
model->HICUMflnqs = value->iValue; |
||||
|
model->HICUMflnqsGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Noise |
||||
|
case HICUM_MOD_KF: |
||||
|
model->HICUMkf = value->rValue; |
||||
|
model->HICUMkfGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AF: |
||||
|
model->HICUMaf = value->rValue; |
||||
|
model->HICUMafGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CFBE: |
||||
|
model->HICUMcfbe = value->iValue; |
||||
|
model->HICUMcfbeGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_FLCONO: |
||||
|
model->HICUMflcono = value->iValue; |
||||
|
model->HICUMflconoGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_KFRE: |
||||
|
model->HICUMkfre = value->rValue; |
||||
|
model->HICUMkfreGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_AFRE: |
||||
|
model->HICUMafre = value->rValue; |
||||
|
model->HICUMafreGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Lateral Geometry Scaling (at high current densities) |
||||
|
case HICUM_MOD_LATB: |
||||
|
model->HICUMlatb = value->rValue; |
||||
|
model->HICUMlatbGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_LATL: |
||||
|
model->HICUMlatl = value->rValue; |
||||
|
model->HICUMlatlGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Temperature dependence |
||||
|
case HICUM_MOD_VGB: |
||||
|
model->HICUMvgb = value->rValue; |
||||
|
model->HICUMvgbGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALT0: |
||||
|
model->HICUMalt0 = value->rValue; |
||||
|
model->HICUMalt0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_KT0: |
||||
|
model->HICUMkt0 = value->rValue; |
||||
|
model->HICUMkt0Given = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETACI: |
||||
|
model->HICUMzetaci = value->rValue; |
||||
|
model->HICUMzetaciGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALVS: |
||||
|
model->HICUMalvs = value->rValue; |
||||
|
model->HICUMalvsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALCES: |
||||
|
model->HICUMalces = value->rValue; |
||||
|
model->HICUMalcesGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETARBI: |
||||
|
model->HICUMzetarbi = value->rValue; |
||||
|
model->HICUMzetarbiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETARBX: |
||||
|
model->HICUMzetarbx = value->rValue; |
||||
|
model->HICUMzetarbxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETARCX: |
||||
|
model->HICUMzetarcx = value->rValue; |
||||
|
model->HICUMzetarcxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETARE: |
||||
|
model->HICUMzetare = value->rValue; |
||||
|
model->HICUMzetareGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETACX: |
||||
|
model->HICUMzetacx = value->rValue; |
||||
|
model->HICUMzetacxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VGE: |
||||
|
model->HICUMvge = value->rValue; |
||||
|
model->HICUMvgeGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VGC: |
||||
|
model->HICUMvgc = value->rValue; |
||||
|
model->HICUMvgcGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VGS: |
||||
|
model->HICUMvgs = value->rValue; |
||||
|
model->HICUMvgsGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_F1VG: |
||||
|
model->HICUMf1vg = value->rValue; |
||||
|
model->HICUMf1vgGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_F2VG: |
||||
|
model->HICUMf2vg = value->rValue; |
||||
|
model->HICUMf2vgGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETACT: |
||||
|
model->HICUMzetact = value->rValue; |
||||
|
model->HICUMzetactGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETABET: |
||||
|
model->HICUMzetabet = value->rValue; |
||||
|
model->HICUMzetabetGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALB: |
||||
|
model->HICUMalb = value->rValue; |
||||
|
model->HICUMalbGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_DVGBE: |
||||
|
model->HICUMdvgbe = value->rValue; |
||||
|
model->HICUMdvgbeGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETAHJEI: |
||||
|
model->HICUMzetahjei = value->rValue; |
||||
|
model->HICUMzetahjeiGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETAVGBE: |
||||
|
model->HICUMzetavgbe = value->rValue; |
||||
|
model->HICUMzetavgbeGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Self-Heating |
||||
|
case HICUM_MOD_FLSH: |
||||
|
model->HICUMflsh = value->iValue; |
||||
|
model->HICUMflshGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_RTH: |
||||
|
model->HICUMrth = value->rValue; |
||||
|
model->HICUMrthGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ZETARTH: |
||||
|
model->HICUMzetarth = value->rValue; |
||||
|
model->HICUMzetarthGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_ALRTH: |
||||
|
model->HICUMalrth = value->rValue; |
||||
|
model->HICUMalrthGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_CTH: |
||||
|
model->HICUMcth = value->rValue; |
||||
|
model->HICUMcthGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//Compatibility with V2.1 |
||||
|
case HICUM_MOD_FLCOMP: |
||||
|
model->HICUMflcomp = value->rValue; |
||||
|
model->HICUMflcompGiven = TRUE; |
||||
|
break; |
||||
|
|
||||
|
//SOA-check |
||||
|
case HICUM_MOD_VBE_MAX: |
||||
|
model->HICUMvbeMax = value->rValue; |
||||
|
model->HICUMvbeMaxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VBC_MAX: |
||||
|
model->HICUMvbcMax = value->rValue; |
||||
|
model->HICUMvbcMaxGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_MOD_VCE_MAX: |
||||
|
model->HICUMvceMax = value->rValue; |
||||
|
model->HICUMvceMaxGiven = TRUE; |
||||
|
break; |
||||
|
default: |
||||
|
return(E_BADPARM); |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,293 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "ngspice/iferrmsg.h" |
||||
|
#include "ngspice/noisedef.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
/* |
||||
|
* HICUMnoise (mode, operation, firstModel, ckt, data, OnDens) |
||||
|
* |
||||
|
* This routine names and evaluates all of the noise sources |
||||
|
* associated with HICUM's. It starts with the model *firstModel and |
||||
|
* traverses all of its insts. It then proceeds to any other models |
||||
|
* on the linked list. The total output noise density generated by |
||||
|
* all of the HICUM's is summed with the variable "OnDens". |
||||
|
*/ |
||||
|
|
||||
|
|
||||
|
int |
||||
|
HICUMnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, Ndata *data, double *OnDens) |
||||
|
{ |
||||
|
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; |
||||
|
|
||||
|
HICUMmodel *firstModel = (HICUMmodel *) genmodel; |
||||
|
HICUMmodel *model; |
||||
|
HICUMinstance *here; |
||||
|
double tempOnoise; |
||||
|
double tempInoise; |
||||
|
double noizDens[HICUMNSRCS]; |
||||
|
double lnNdens[HICUMNSRCS]; |
||||
|
int i; |
||||
|
|
||||
|
double Ibbp_Vbbp; |
||||
|
double Icic_Vcic; |
||||
|
double Ibpbi_Vbpbi; |
||||
|
double Ieie_Veie; |
||||
|
double Isis_Vsis; |
||||
|
|
||||
|
/* define the names of the noise sources */ |
||||
|
|
||||
|
static char *HICUMnNames[HICUMNSRCS] = { |
||||
|
/* Note that we have to keep the order consistent with the |
||||
|
strchr definitions in HICUMdefs.h */ |
||||
|
"_rcx", /* thermal noise due to rcx */ |
||||
|
"_rbx", /* thermal noise due to rbx */ |
||||
|
"_rbi", /* thermal noise due to rbi */ |
||||
|
"_re", /* thermal noise due to re */ |
||||
|
"_rsu", /* thermal noise due to rsu */ |
||||
|
"_iavl", /* shot noise due to iavl */ |
||||
|
"_ibci", /* shot noise due to ibci */ |
||||
|
"_ibep", /* shot noise due to ibep */ |
||||
|
"_ijbcx", /* shot noise due to ijbcx */ |
||||
|
"_ijsc", /* shot noise due to ijsc */ |
||||
|
"_it", /* shot noise due to iciei */ |
||||
|
"_ibei", /* shot noise due to ibiei */ |
||||
|
"_1overfbe", /* flicker (1/f) noise ibe */ |
||||
|
"_1overfre", /* flicker (1/f) noise re */ |
||||
|
"" /* total transistor noise */ |
||||
|
}; |
||||
|
|
||||
|
for (model=firstModel; model != NULL; model=HICUMnextModel(model)) { |
||||
|
for (here=HICUMinstances(model); here != NULL; |
||||
|
here=HICUMnextInstance(here)) { |
||||
|
|
||||
|
// get all derivatives of branch DC currents |
||||
|
if(model->HICUMrcxGiven && model->HICUMrcx != 0) { |
||||
|
Icic_Vcic = 1/here->HICUMrcx_t.rpart; |
||||
|
} else { |
||||
|
Icic_Vcic = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrbxGiven && model->HICUMrbx != 0) { |
||||
|
Ibbp_Vbbp = 1/here->HICUMrbx_t.rpart; |
||||
|
} else { |
||||
|
Ibbp_Vbbp = 0.0; |
||||
|
} |
||||
|
if(model->HICUMreGiven && model->HICUMre != 0) { |
||||
|
Ieie_Veie = 1/here->HICUMre_t.rpart; |
||||
|
} else { |
||||
|
Ieie_Veie = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrsuGiven && model->HICUMrsu != 0) { |
||||
|
Isis_Vsis = 1/model->HICUMrsu*here->HICUMm; |
||||
|
} else { |
||||
|
Isis_Vsis = 0.0; |
||||
|
} |
||||
|
if(here->HICUMrbi > 0) { |
||||
|
Ibpbi_Vbpbi = 1/here->HICUMrbi; |
||||
|
} else { |
||||
|
Ibpbi_Vbpbi = 0.0; |
||||
|
} |
||||
|
|
||||
|
switch (operation) { |
||||
|
|
||||
|
case N_OPEN: |
||||
|
|
||||
|
/* see if we have to to produce a summary report */ |
||||
|
/* if so, name all the noise generators */ |
||||
|
|
||||
|
if (job->NStpsSm != 0) { |
||||
|
switch (mode) { |
||||
|
|
||||
|
case N_DENS: |
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
NOISE_ADD_OUTVAR(ckt, data, "onoise_%s%s", here->HICUMname, HICUMnNames[i]); |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case INT_NOIZ: |
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
NOISE_ADD_OUTVAR(ckt, data, "onoise_total_%s%s", here->HICUMname, HICUMnNames[i]); |
||||
|
NOISE_ADD_OUTVAR(ckt, data, "inoise_total_%s%s", here->HICUMname, HICUMnNames[i]); |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case N_CALC: |
||||
|
switch (mode) { |
||||
|
|
||||
|
case N_DENS: |
||||
|
NevalSrc(&noizDens[HICUMRCNOIZ],&lnNdens[HICUMRCNOIZ], |
||||
|
ckt,THERMNOISE,here->HICUMcollCINode,here->HICUMcollNode, |
||||
|
Icic_Vcic); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMRBNOIZ],&lnNdens[HICUMRBNOIZ], |
||||
|
ckt,THERMNOISE,here->HICUMbaseNode,here->HICUMbaseBPNode, |
||||
|
Ibbp_Vbbp); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMRBINOIZ],&lnNdens[HICUMRBINOIZ], |
||||
|
ckt,THERMNOISE,here->HICUMbaseBPNode,here->HICUMbaseBINode, |
||||
|
Ibpbi_Vbpbi); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMRENOIZ],&lnNdens[HICUMRENOIZ], |
||||
|
ckt,THERMNOISE,here->HICUMemitEINode,here->HICUMemitNode, |
||||
|
Ieie_Veie); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMRSNOIZ],&lnNdens[HICUMRSNOIZ], |
||||
|
ckt,THERMNOISE,here->HICUMsubsSINode,here->HICUMsubsNode, |
||||
|
Isis_Vsis); |
||||
|
|
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIAVLNOIZ],&lnNdens[HICUMIAVLNOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMcollCINode,here->HICUMbaseBINode, |
||||
|
here->HICUMiavl); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIBCINOIZ],&lnNdens[HICUMIBCINOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMbaseBINode,here->HICUMcollCINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMibici)+here->HICUMiavl); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIBEPNOIZ],&lnNdens[HICUMIBEPNOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMbaseBPNode,here->HICUMemitEINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMibpei)); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIBCXNOIZ],&lnNdens[HICUMIBCXNOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMbaseBPNode,here->HICUMcollCINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMibpci)); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIJSCNOIZ],&lnNdens[HICUMIJSCNOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMsubsSINode,here->HICUMcollCINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMisici)); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMITNOIZ],&lnNdens[HICUMITNOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMcollCINode,here->HICUMemitEINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMit)); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMIBEINOIZ],&lnNdens[HICUMIBEINOIZ], |
||||
|
ckt,SHOTNOISE,here->HICUMbaseBINode,here->HICUMemitEINode, |
||||
|
*(ckt->CKTstate0 + here->HICUMibiei)); |
||||
|
|
||||
|
|
||||
|
if (model->HICUMcfbe == -1) { |
||||
|
NevalSrc(&noizDens[HICUMFLBENOIZ], NULL, ckt, |
||||
|
N_GAIN,here->HICUMbaseBINode, here->HICUMemitEINode, |
||||
|
(double)0.0); |
||||
|
} else { |
||||
|
NevalSrc(&noizDens[HICUMFLBENOIZ], NULL, ckt, |
||||
|
N_GAIN,here->HICUMbaseBPNode, here->HICUMemitEINode, |
||||
|
(double)0.0); |
||||
|
} |
||||
|
noizDens[HICUMFLBENOIZ] *= here->HICUMkf_scaled * |
||||
|
exp(model->HICUMaf * |
||||
|
log(MAX(fabs((*(ckt->CKTstate0 + here->HICUMibiei)+*(ckt->CKTstate0 + here->HICUMibpei))),N_MINLOG))) / |
||||
|
data->freq; |
||||
|
lnNdens[HICUMFLBENOIZ] = |
||||
|
log(MAX(noizDens[HICUMFLBENOIZ],N_MINLOG)); |
||||
|
|
||||
|
NevalSrc(&noizDens[HICUMFLRENOIZ], NULL, ckt, |
||||
|
N_GAIN,here->HICUMemitEINode, here->HICUMemitNode, |
||||
|
(double)0.0); |
||||
|
noizDens[HICUMFLRENOIZ] *= here->HICUMkfre_scaled * |
||||
|
exp(model->HICUMafre * |
||||
|
log(MAX(fabs(*(ckt->CKTstate0 + here->HICUMieie)),N_MINLOG))) / |
||||
|
data->freq; |
||||
|
lnNdens[HICUMFLRENOIZ] = |
||||
|
log(MAX(noizDens[HICUMFLRENOIZ],N_MINLOG)); |
||||
|
|
||||
|
|
||||
|
noizDens[HICUMTOTNOIZ] = noizDens[HICUMRCNOIZ] + |
||||
|
noizDens[HICUMRBNOIZ] + |
||||
|
noizDens[HICUMRBINOIZ] + |
||||
|
noizDens[HICUMRENOIZ] + |
||||
|
noizDens[HICUMRSNOIZ] + |
||||
|
noizDens[HICUMIAVLNOIZ] + |
||||
|
noizDens[HICUMIBCINOIZ] + |
||||
|
noizDens[HICUMIBEPNOIZ] + |
||||
|
noizDens[HICUMIBCXNOIZ] + |
||||
|
noizDens[HICUMIJSCNOIZ] + |
||||
|
noizDens[HICUMITNOIZ] + |
||||
|
noizDens[HICUMIBEINOIZ] + |
||||
|
noizDens[HICUMFLBENOIZ] + |
||||
|
noizDens[HICUMFLRENOIZ]; |
||||
|
|
||||
|
|
||||
|
lnNdens[HICUMTOTNOIZ] = |
||||
|
log(noizDens[HICUMTOTNOIZ]); |
||||
|
|
||||
|
*OnDens += noizDens[HICUMTOTNOIZ]; |
||||
|
|
||||
|
if (data->delFreq == 0.0) { |
||||
|
|
||||
|
/* if we haven't done any previous integration, we need to */ |
||||
|
/* initialize our "history" variables */ |
||||
|
|
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
here->HICUMnVar[LNLSTDENS][i] = lnNdens[i]; |
||||
|
} |
||||
|
|
||||
|
/* clear out our integration variables if it's the first pass */ |
||||
|
|
||||
|
if (data->freq == job->NstartFreq) { |
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
here->HICUMnVar[OUTNOIZ][i] = 0.0; |
||||
|
here->HICUMnVar[INNOIZ][i] = 0.0; |
||||
|
} |
||||
|
} |
||||
|
} else { /* data->delFreq != 0.0 (we have to integrate) */ |
||||
|
|
||||
|
/* In order to get the best curve fit, we have to integrate each component separately */ |
||||
|
|
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
if (i != HICUMTOTNOIZ) { |
||||
|
tempOnoise = Nintegrate(noizDens[i], lnNdens[i], |
||||
|
here->HICUMnVar[LNLSTDENS][i], data); |
||||
|
tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , |
||||
|
lnNdens[i] + data->lnGainInv, |
||||
|
here->HICUMnVar[LNLSTDENS][i] + data->lnGainInv, |
||||
|
data); |
||||
|
here->HICUMnVar[LNLSTDENS][i] = lnNdens[i]; |
||||
|
data->outNoiz += tempOnoise; |
||||
|
data->inNoise += tempInoise; |
||||
|
if (job->NStpsSm != 0) { |
||||
|
here->HICUMnVar[OUTNOIZ][i] += tempOnoise; |
||||
|
here->HICUMnVar[OUTNOIZ][HICUMTOTNOIZ] += tempOnoise; |
||||
|
here->HICUMnVar[INNOIZ][i] += tempInoise; |
||||
|
here->HICUMnVar[INNOIZ][HICUMTOTNOIZ] += tempInoise; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if (data->prtSummary) { |
||||
|
for (i=0; i < HICUMNSRCS; i++) { /* print a summary report */ |
||||
|
data->outpVector[data->outNumber++] = noizDens[i]; |
||||
|
} |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case INT_NOIZ: /* already calculated, just output */ |
||||
|
if (job->NStpsSm != 0) { |
||||
|
for (i=0; i < HICUMNSRCS; i++) { |
||||
|
data->outpVector[data->outNumber++] = here->HICUMnVar[OUTNOIZ][i]; |
||||
|
data->outpVector[data->outNumber++] = here->HICUMnVar[INNOIZ][i]; |
||||
|
} |
||||
|
} /* if */ |
||||
|
break; |
||||
|
} /* switch (mode) */ |
||||
|
break; |
||||
|
|
||||
|
case N_CLOSE: |
||||
|
return (OK); /* do nothing, the main calling routine will close */ |
||||
|
break; /* the plots */ |
||||
|
} /* switch (operation) */ |
||||
|
} /* for here */ |
||||
|
} /* for model */ |
||||
|
|
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine sets instance parameters for |
||||
|
* HICUMs in the circuit. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/const.h" |
||||
|
#include "ngspice/ifsim.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
|
||||
|
/* ARGSUSED */ |
||||
|
int |
||||
|
HICUMparam(int param, IFvalue *value, GENinstance *instPtr, IFvalue *select) |
||||
|
{ |
||||
|
HICUMinstance *here = (HICUMinstance*)instPtr; |
||||
|
|
||||
|
NG_IGNORE(select); |
||||
|
|
||||
|
switch(param) { |
||||
|
case HICUM_AREA: |
||||
|
here->HICUMarea = value->rValue; |
||||
|
here->HICUMareaGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_OFF: |
||||
|
here->HICUMoff = (value->iValue != 0); |
||||
|
break; |
||||
|
case HICUM_TEMP: |
||||
|
here->HICUMtemp = value->rValue+CONSTCtoK; |
||||
|
here->HICUMtempGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_DTEMP: |
||||
|
here->HICUMdtemp = value->rValue; |
||||
|
here->HICUMdtempGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_M: |
||||
|
here->HICUMm = value->rValue; |
||||
|
here->HICUMmGiven = TRUE; |
||||
|
break; |
||||
|
case HICUM_IC : |
||||
|
switch(value->v.numValue) { |
||||
|
case 3: |
||||
|
here->HICUMicVCS = *(value->v.vec.rVec+2); |
||||
|
here->HICUMicVCSGiven = TRUE; |
||||
|
/* fallthrough */ |
||||
|
case 2: |
||||
|
here->HICUMicVCE = *(value->v.vec.rVec+1); |
||||
|
here->HICUMicVCEGiven = TRUE; |
||||
|
/* fallthrough */ |
||||
|
case 1: |
||||
|
here->HICUMicVBE = *(value->v.vec.rVec); |
||||
|
here->HICUMicVBEGiven = TRUE; |
||||
|
break; |
||||
|
default: |
||||
|
return(E_BADPARM); |
||||
|
} |
||||
|
break; |
||||
|
default: |
||||
|
return(E_BADPARM); |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,758 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Function to load the COMPLEX circuit matrix using the |
||||
|
* small signal parameters saved during a previous DC operating |
||||
|
* point analysis. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
int |
||||
|
HICUMpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) |
||||
|
{ |
||||
|
HICUMinstance *here; |
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
double Ibpei_Vbpei; |
||||
|
double Ibpei_Vrth; |
||||
|
|
||||
|
double Ibiei_Vbiei; |
||||
|
double Ibiei_Vxf; |
||||
|
double Ibiei_Vbici; |
||||
|
double Ibiei_Vrth; |
||||
|
|
||||
|
double Ibici_Vbici; |
||||
|
double Ibici_Vbiei; |
||||
|
double Ibici_Vrth; |
||||
|
|
||||
|
double Ibpci_Vbpci; |
||||
|
double Ibpci_Vrth; |
||||
|
|
||||
|
double Isici_Vsici; |
||||
|
double Isici_Vrth; |
||||
|
|
||||
|
double Iciei_Vbiei; |
||||
|
double Iciei_Vbici; |
||||
|
double Iciei_Vrth; |
||||
|
double Iciei_Vxf2; |
||||
|
|
||||
|
|
||||
|
double Ibpbi_Vbpbi; |
||||
|
double Ibpbi_Vbici; |
||||
|
double Ibpbi_Vbiei; |
||||
|
double Ibpbi_Vrth; |
||||
|
|
||||
|
double Isis_Vsis; |
||||
|
double Icic_Vcic, Icic_Vrth; |
||||
|
double Ieie_Veie, Ieie_Vrth; |
||||
|
double Ibbp_Vbbp, Ibbp_Vrth; |
||||
|
double Irth_Vrth; |
||||
|
|
||||
|
double Ibpsi_Vbpci; |
||||
|
double Ibpsi_Vsici; |
||||
|
double Ibpsi_Vrth; |
||||
|
|
||||
|
double XQrbi_Vbpbi; |
||||
|
double XQrbi_Vbiei; |
||||
|
double XQrbi_Vbici; |
||||
|
double XQrbi_Vrth; |
||||
|
double XQjei_Vbiei; |
||||
|
double XQjei_Vrth; |
||||
|
double XQjci_Vbici; |
||||
|
double XQjci_Vrth; |
||||
|
double XQjep_Vbpei; |
||||
|
double XQjep_Vrth; |
||||
|
double volatile Xqjcx0_t_i_Vbci; |
||||
|
double Xqjcx0_t_i_Vrth; |
||||
|
double volatile Xqjcx0_t_ii_Vbpci; |
||||
|
double Xqjcx0_t_ii_Vrth; |
||||
|
double XQdsu_Vbpci; |
||||
|
double XQdsu_Vsici; |
||||
|
double XQdsu_Vrth; |
||||
|
double XQjs_Vsici; |
||||
|
double XQjs_Vrth; |
||||
|
double XQscp_Vsc; |
||||
|
double XQscp_Vrth; |
||||
|
double XQbepar1_Vbe; |
||||
|
double XQbepar2_Vbpe; |
||||
|
double XQbcpar1_Vbci; |
||||
|
double XQbcpar2_Vbpci; |
||||
|
double XQsu_Vsis; |
||||
|
double XQcth_Vrth; |
||||
|
double XQf_Vbiei; |
||||
|
double XQf_Vbici; |
||||
|
double XQf_Vrth; |
||||
|
double XQf_Vxf; |
||||
|
double XQr_Vrth; |
||||
|
double XQr_Vbiei; |
||||
|
double XQr_Vbici; |
||||
|
|
||||
|
double XQxf_Vxf; |
||||
|
double XQxf1_Vxf1; |
||||
|
double XQxf2_Vxf2; |
||||
|
|
||||
|
double Ixf1_Vbiei; |
||||
|
double Ixf1_Vbici; |
||||
|
double Ixf1_Vxf2 ; |
||||
|
double Ixf1_Vxf1 ; |
||||
|
double Ixf1_Vrth ; |
||||
|
|
||||
|
double Ixf2_Vbiei; |
||||
|
double Ixf2_Vbici; |
||||
|
double Ixf2_Vxf2 ; |
||||
|
double Ixf2_Vxf1 ; |
||||
|
double Ixf2_Vrth ; |
||||
|
|
||||
|
double Ixf_Vbiei ; |
||||
|
double Ixf_Vbici ; |
||||
|
double Ixf_Vxf ; |
||||
|
double Ixf_Vrth ; |
||||
|
|
||||
|
double Ith_Vrth, Ith_Vbiei, Ith_Vbici, Ith_Vbpbi, Ith_Vbpci, Ith_Vbpei, Ith_Vciei, Ith_Vsici, Ith_Vcic, Ith_Vbbp, Ith_Veie; |
||||
|
|
||||
|
/* loop through all the models */ |
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
|
||||
|
int selfheat = ( (model->HICUMflsh > 0) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0)); |
||||
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0)); |
||||
|
|
||||
|
/* loop through all the instances of the model */ |
||||
|
for( here = HICUMinstances(model); here!= NULL; |
||||
|
here = HICUMnextInstance(here)) { |
||||
|
|
||||
|
|
||||
|
// get all derivatives of branch DC currents |
||||
|
if(model->HICUMrcxGiven && model->HICUMrcx != 0) { |
||||
|
Icic_Vcic = 1/here->HICUMrcx_t.rpart; |
||||
|
Icic_Vrth = -*(ckt->CKTstate0 + here->HICUMvcic)/here->HICUMrcx_t.rpart/here->HICUMrcx_t.rpart*here->HICUMrcx_t.dpart; |
||||
|
} else { |
||||
|
Icic_Vcic = 0.0; |
||||
|
Icic_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrbxGiven && model->HICUMrbx != 0) { |
||||
|
Ibbp_Vbbp = 1/here->HICUMrbx_t.rpart; |
||||
|
Ibbp_Vrth = -*(ckt->CKTstate0 + here->HICUMvbbp)/here->HICUMrbx_t.rpart/here->HICUMrbx_t.rpart*here->HICUMrbx_t.dpart; |
||||
|
} else { |
||||
|
Ibbp_Vbbp = 0.0; |
||||
|
Ibbp_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMreGiven && model->HICUMre != 0) { |
||||
|
Ieie_Veie = 1/here->HICUMre_t.rpart; |
||||
|
Ieie_Vrth = -*(ckt->CKTstate0 + here->HICUMveie)/here->HICUMre_t.rpart/here->HICUMre_t.rpart*here->HICUMre_t.dpart; |
||||
|
} else { |
||||
|
Ieie_Veie = 0.0; |
||||
|
Ieie_Vrth = 0.0; |
||||
|
} |
||||
|
if(model->HICUMrsuGiven && model->HICUMrsu != 0) { |
||||
|
Isis_Vsis = 1/model->HICUMrsu*here->HICUMm; |
||||
|
} else { |
||||
|
Isis_Vsis = 0.0; |
||||
|
} |
||||
|
if(selfheat) { |
||||
|
Irth_Vrth = (1/here->HICUMrth_t.rpart - *(ckt->CKTstate0 + here->HICUMvrth)/(here->HICUMrth_t.rpart*here->HICUMrth_t.rpart) * here->HICUMrth_t.dpart); |
||||
|
} else { |
||||
|
Irth_Vrth = 0.0; |
||||
|
} |
||||
|
|
||||
|
Ibiei_Vbiei = *(ckt->CKTstate0 + here->HICUMibiei_Vbiei); |
||||
|
Ibiei_Vxf = *(ckt->CKTstate0 + here->HICUMibiei_Vxf); |
||||
|
Ibiei_Vbici = *(ckt->CKTstate0 + here->HICUMibiei_Vbici); |
||||
|
Ibiei_Vrth = *(ckt->CKTstate0 + here->HICUMibiei_Vrth); |
||||
|
|
||||
|
Ibpei_Vbpei = *(ckt->CKTstate0 + here->HICUMibpei_Vbpei); |
||||
|
Ibpei_Vrth = *(ckt->CKTstate0 + here->HICUMibpei_Vrth); |
||||
|
|
||||
|
Iciei_Vbiei = *(ckt->CKTstate0 + here->HICUMiciei_Vbiei); |
||||
|
Iciei_Vbici = *(ckt->CKTstate0 + here->HICUMiciei_Vbici); |
||||
|
Iciei_Vrth = *(ckt->CKTstate0 + here->HICUMiciei_Vrth); |
||||
|
Iciei_Vxf2 = *(ckt->CKTstate0 + here->HICUMiciei_Vxf2); |
||||
|
|
||||
|
Ibici_Vbici = *(ckt->CKTstate0 + here->HICUMibici_Vbici); |
||||
|
Ibici_Vbiei = *(ckt->CKTstate0 + here->HICUMibici_Vbiei); |
||||
|
Ibici_Vrth = *(ckt->CKTstate0 + here->HICUMibici_Vrth); |
||||
|
|
||||
|
Ibpbi_Vbpbi = *(ckt->CKTstate0 + here->HICUMibpbi_Vbpbi); |
||||
|
Ibpbi_Vbiei = *(ckt->CKTstate0 + here->HICUMibpbi_Vbiei); |
||||
|
Ibpbi_Vbici = *(ckt->CKTstate0 + here->HICUMibpbi_Vbici); |
||||
|
Ibpbi_Vrth = *(ckt->CKTstate0 + here->HICUMibpbi_Vrth); |
||||
|
|
||||
|
Ibpci_Vbpci = *(ckt->CKTstate0 + here->HICUMibpci_Vbpci); |
||||
|
Ibpci_Vrth = *(ckt->CKTstate0 + here->HICUMibpci_Vrth); |
||||
|
|
||||
|
Isici_Vsici = *(ckt->CKTstate0 + here->HICUMisici_Vsici); |
||||
|
Isici_Vrth = *(ckt->CKTstate0 + here->HICUMisici_Vrth); |
||||
|
|
||||
|
Ibpsi_Vbpci = *(ckt->CKTstate0 + here->HICUMibpsi_Vbpci); |
||||
|
Ibpsi_Vsici = *(ckt->CKTstate0 + here->HICUMibpsi_Vsici); |
||||
|
Ibpsi_Vrth = *(ckt->CKTstate0 + here->HICUMibpsi_Vrth); |
||||
|
|
||||
|
Ith_Vrth = *(ckt->CKTstate0 + here->HICUMith_Vrth); |
||||
|
Ith_Vbiei = *(ckt->CKTstate0 + here->HICUMith_Vbiei); |
||||
|
Ith_Vbici = *(ckt->CKTstate0 + here->HICUMith_Vbici); |
||||
|
Ith_Vbpbi = *(ckt->CKTstate0 + here->HICUMith_Vbpbi); |
||||
|
Ith_Vbpci = *(ckt->CKTstate0 + here->HICUMith_Vbpci); |
||||
|
Ith_Vbpei = *(ckt->CKTstate0 + here->HICUMith_Vbpei); |
||||
|
Ith_Vciei = *(ckt->CKTstate0 + here->HICUMith_Vciei); |
||||
|
Ith_Vsici = *(ckt->CKTstate0 + here->HICUMith_Vsici); |
||||
|
Ith_Vcic = *(ckt->CKTstate0 + here->HICUMith_Vcic); |
||||
|
Ith_Vbbp = *(ckt->CKTstate0 + here->HICUMith_Vbbp); |
||||
|
Ith_Veie = *(ckt->CKTstate0 + here->HICUMith_Veie); |
||||
|
|
||||
|
Ixf1_Vbiei = *(ckt->CKTstate0 + here->HICUMixf1_Vbiei); |
||||
|
Ixf1_Vbici = *(ckt->CKTstate0 + here->HICUMixf1_Vbici); |
||||
|
Ixf1_Vxf2 = *(ckt->CKTstate0 + here->HICUMixf1_Vxf2); |
||||
|
Ixf1_Vxf1 = *(ckt->CKTstate0 + here->HICUMixf1_Vxf1); |
||||
|
Ixf1_Vrth = *(ckt->CKTstate0 + here->HICUMixf1_Vrth); |
||||
|
|
||||
|
Ixf2_Vbiei = *(ckt->CKTstate0 + here->HICUMixf2_Vbiei); |
||||
|
Ixf2_Vbici = *(ckt->CKTstate0 + here->HICUMixf2_Vbici); |
||||
|
Ixf2_Vxf2 = *(ckt->CKTstate0 + here->HICUMixf2_Vxf2); |
||||
|
Ixf2_Vxf1 = *(ckt->CKTstate0 + here->HICUMixf2_Vxf1); |
||||
|
Ixf2_Vrth = *(ckt->CKTstate0 + here->HICUMixf2_Vrth); |
||||
|
|
||||
|
Ixf_Vbiei = *(ckt->CKTstate0 + here->HICUMixf_Vbiei); |
||||
|
Ixf_Vbici = *(ckt->CKTstate0 + here->HICUMixf_Vbici); |
||||
|
Ixf_Vxf = *(ckt->CKTstate0 + here->HICUMixf_Vxf); |
||||
|
Ixf_Vrth = *(ckt->CKTstate0 + here->HICUMixf_Vrth); |
||||
|
|
||||
|
//////////////////////////////////// |
||||
|
////////// The real part ///////// |
||||
|
//////////////////////////////////// |
||||
|
|
||||
|
// Stamp element: Ibiei |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibiei_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ibiei_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -Ibiei_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Ibiei_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibiei_Vbici; |
||||
|
*(here->HICUMemitEICollCIPtr) += Ibiei_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += -Ibiei_Vbici; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Ibiei_Vbici; |
||||
|
|
||||
|
// Stamp element: Ibpei |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpei_Vbpei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ibpei_Vbpei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr) += -Ibpei_Vbpei; |
||||
|
*(here->HICUMemitEIBaseBPPtr) += -Ibpei_Vbpei;; |
||||
|
|
||||
|
// Stamp element: Ibici |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibici_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr) += Ibici_Vbici; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -Ibici_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += -Ibici_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibici_Vbiei; |
||||
|
*(here->HICUMcollCIEmitEIPtr) += Ibici_Vbiei; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -Ibici_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -Ibici_Vbiei; |
||||
|
|
||||
|
// Stamp element: Iciei |
||||
|
*(here->HICUMcollCIBaseBIPtr) += Iciei_Vbiei; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Iciei_Vbiei; |
||||
|
*(here->HICUMcollCIEmitEIPtr) += -Iciei_Vbiei; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Iciei_Vbiei; |
||||
|
*(here->HICUMcollCIBaseBIPtr) += Iciei_Vbici; |
||||
|
*(here->HICUMemitEICollCIPtr) += Iciei_Vbici; |
||||
|
*(here->HICUMcollCICollCIPtr) += -Iciei_Vbici; |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -Iciei_Vbici; |
||||
|
if (nqs) { |
||||
|
*(here->HICUMcollCIXf2Ptr) += Iciei_Vxf2; |
||||
|
*(here->HICUMemitEIXf2Ptr) += -Iciei_Vxf2; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// Stamp element: Ibpci |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpci_Vbpci; |
||||
|
*(here->HICUMcollCICollCIPtr) += Ibpci_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpci_Vbpci; |
||||
|
*(here->HICUMcollCIBaseBPPtr) += -Ibpci_Vbpci; |
||||
|
|
||||
|
// Stamp element: Rcx |
||||
|
*(here->HICUMcollCollPtr) += Icic_Vcic; |
||||
|
*(here->HICUMcollCICollCIPtr) += Icic_Vcic; |
||||
|
*(here->HICUMcollCICollPtr) += -Icic_Vcic; |
||||
|
*(here->HICUMcollCollCIPtr) += -Icic_Vcic; |
||||
|
|
||||
|
// Stamp element: Rbx |
||||
|
*(here->HICUMbaseBasePtr) += Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBPBasePtr) += -Ibbp_Vbbp; |
||||
|
*(here->HICUMbaseBaseBPPtr) += -Ibbp_Vbbp; |
||||
|
|
||||
|
// Stamp element: Re |
||||
|
*(here->HICUMemitEmitPtr) += Ieie_Veie; |
||||
|
*(here->HICUMemitEIEmitEIPtr) += Ieie_Veie; |
||||
|
*(here->HICUMemitEIEmitPtr) += -Ieie_Veie; |
||||
|
*(here->HICUMemitEmitEIPtr) += -Ieie_Veie; |
||||
|
|
||||
|
// Stamp element: Ibpbi |
||||
|
if (here->HICUMrbi>0.0) { |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += -Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBIBaseBPPtr) += -Ibpbi_Vbpbi; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBPEmitEIPtr) += -Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += -Ibpbi_Vbiei; |
||||
|
*(here->HICUMbaseBPBaseBIPtr) += Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBICollCIPtr) += Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpbi_Vbici; |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += -Ibpbi_Vbici; |
||||
|
}; |
||||
|
|
||||
|
// Stamp element: Isici |
||||
|
*(here->HICUMsubsSISubsSIPtr) += Isici_Vsici; |
||||
|
*(here->HICUMcollCICollCIPtr) += Isici_Vsici; |
||||
|
*(here->HICUMsubsSICollCIPtr) += -Isici_Vsici; |
||||
|
*(here->HICUMcollCISubsSIPtr) += -Isici_Vsici;; |
||||
|
|
||||
|
// Stamp element: Ibpsi |
||||
|
*(here->HICUMbaseBPSubsSIPtr) += Ibpsi_Vsici; |
||||
|
*(here->HICUMsubsSICollCIPtr) += Ibpsi_Vsici; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpsi_Vsici; |
||||
|
*(here->HICUMsubsSISubsSIPtr) += -Ibpsi_Vsici; |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Ibpsi_Vbpci; |
||||
|
*(here->HICUMsubsSICollCIPtr) += Ibpsi_Vbpci; |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Ibpsi_Vbpci; |
||||
|
*(here->HICUMsubsSIBaseBPPtr) += -Ibpsi_Vbpci;; |
||||
|
|
||||
|
// Stamp element: Rsu |
||||
|
*(here->HICUMsubsSubsPtr) += Isis_Vsis; |
||||
|
*(here->HICUMsubsSISubsSIPtr) += Isis_Vsis; |
||||
|
*(here->HICUMsubsSISubsPtr) += -Isis_Vsis; |
||||
|
*(here->HICUMsubsSubsSIPtr) += -Isis_Vsis; |
||||
|
|
||||
|
if (nqs) { |
||||
|
//Ixf1 |
||||
|
*(here->HICUMxf1BaseBIPtr) += +Ixf1_Vbiei; |
||||
|
*(here->HICUMxf1EmitEIPtr) += -Ixf1_Vbiei; |
||||
|
*(here->HICUMxf1BaseBIPtr) += +Ixf1_Vbici; |
||||
|
*(here->HICUMxf1CollCIPtr) += -Ixf1_Vbici; |
||||
|
*(here->HICUMxf1Xf2Ptr) += +Ixf1_Vxf2; |
||||
|
*(here->HICUMxf1Xf1Ptr) += +Ixf1_Vxf1; |
||||
|
//Ixf2 |
||||
|
*(here->HICUMxf2BaseBIPtr) += +Ixf2_Vbiei; |
||||
|
*(here->HICUMxf2EmitEIPtr) += -Ixf2_Vbiei; |
||||
|
*(here->HICUMxf2BaseBIPtr) += +Ixf2_Vbici; |
||||
|
*(here->HICUMxf2CollCIPtr) += -Ixf2_Vbici; |
||||
|
*(here->HICUMxf2Xf2Ptr) += +Ixf2_Vxf2; |
||||
|
*(here->HICUMxf2Xf1Ptr) += +Ixf2_Vxf1; |
||||
|
//Ixf |
||||
|
*(here->HICUMxfBaseBIPtr) += +Ixf_Vbiei; |
||||
|
*(here->HICUMxfEmitEIPtr) += -Ixf_Vbiei; |
||||
|
*(here->HICUMxfBaseBIPtr) += +Ixf_Vbici; |
||||
|
*(here->HICUMxfCollCIPtr) += -Ixf_Vbici; |
||||
|
*(here->HICUMxfXfPtr) += +Ixf_Vxf; |
||||
|
} |
||||
|
|
||||
|
//////////////////////////////////// |
||||
|
////////// The complex part ////// |
||||
|
//////////////////////////////////// |
||||
|
|
||||
|
//Qrbi |
||||
|
XQrbi_Vbpbi = *(ckt->CKTstate0 + here->HICUMcqrbi); |
||||
|
XQrbi_Vbiei = here->HICUMqrbi_Vbiei; |
||||
|
XQrbi_Vbici = here->HICUMqrbi_Vbici; |
||||
|
XQrbi_Vrth = here->HICUMqrbi_Vrth; |
||||
|
//Qjei |
||||
|
XQjei_Vbiei = *(ckt->CKTstate0 + here->HICUMcqjei); |
||||
|
XQjei_Vrth = here->HICUMqjei_Vrth; |
||||
|
//Qf |
||||
|
XQf_Vbiei = *(ckt->CKTstate0 + here->HICUMcqf); |
||||
|
XQf_Vbici = here->HICUMqf_Vbici; |
||||
|
XQf_Vrth = here->HICUMqf_Vrth; |
||||
|
XQf_Vxf = here->HICUMqf_Vxf; |
||||
|
//Qr |
||||
|
XQr_Vbici = *(ckt->CKTstate0 + here->HICUMcqr); |
||||
|
XQr_Vbiei = here->HICUMqr_Vbiei; |
||||
|
XQr_Vrth = here->HICUMqr_Vrth; |
||||
|
//Qjci |
||||
|
XQjci_Vbici = *(ckt->CKTstate0 + here->HICUMcqjci); |
||||
|
XQjci_Vrth = here->HICUMqjci_Vrth; |
||||
|
//Qjep |
||||
|
XQjep_Vbpei = *(ckt->CKTstate0 + here->HICUMcqjep); |
||||
|
XQjep_Vrth = here->HICUMqjep_Vrth; |
||||
|
//Qjcx_i |
||||
|
Xqjcx0_t_i_Vbci = *(ckt->CKTstate0 + here->HICUMcqcx0_t_i); |
||||
|
Xqjcx0_t_i_Vrth = here->HICUMqjcx0_i_Vrth; |
||||
|
//Qjcx_ii |
||||
|
Xqjcx0_t_ii_Vbpci = *(ckt->CKTstate0 + here->HICUMcqcx0_t_ii); |
||||
|
Xqjcx0_t_ii_Vrth = here->HICUMqjcx0_ii_Vrth; |
||||
|
//Qdsu |
||||
|
XQdsu_Vbpci = *(ckt->CKTstate0 + here->HICUMcqdsu); |
||||
|
XQdsu_Vsici = here->HICUMqdsu_Vsici; |
||||
|
XQdsu_Vrth = here->HICUMqdsu_Vrth; |
||||
|
//Qjs |
||||
|
XQjs_Vsici = *(ckt->CKTstate0 + here->HICUMcqjs); |
||||
|
XQjs_Vrth = here->HICUMqjs_Vrth; |
||||
|
//Qscp |
||||
|
XQscp_Vsc = *(ckt->CKTstate0 + here->HICUMcqscp); |
||||
|
XQscp_Vrth = here->HICUMqscp_Vrth; |
||||
|
//Qbepar1 |
||||
|
XQbepar1_Vbe = *(ckt->CKTstate0 + here->HICUMcqbepar1); |
||||
|
//Qbepar2 |
||||
|
XQbepar2_Vbpe = *(ckt->CKTstate0 + here->HICUMcqbepar2); |
||||
|
//Qbcpar1 |
||||
|
XQbcpar1_Vbci = *(ckt->CKTstate0 + here->HICUMcqbcpar1); |
||||
|
//Qbcpar2 |
||||
|
XQbcpar2_Vbpci = *(ckt->CKTstate0 + here->HICUMcqbcpar2); |
||||
|
//Qsu |
||||
|
XQsu_Vsis = *(ckt->CKTstate0 + here->HICUMcqsu); |
||||
|
//Qcth |
||||
|
XQcth_Vrth = *(ckt->CKTstate0 + here->HICUMcqcth); |
||||
|
//Qxf |
||||
|
XQxf_Vxf = *(ckt->CKTstate0 + here->HICUMcqxf); |
||||
|
XQxf1_Vxf1 = *(ckt->CKTstate0 + here->HICUMcqxf1); |
||||
|
XQxf2_Vxf2 = *(ckt->CKTstate0 + here->HICUMcqxf2); |
||||
|
|
||||
|
//Qrbi f_bp=+ f_bi=- |
||||
|
if (here->HICUMrbi>0.0) { |
||||
|
*(here->HICUMbaseBPBaseBPPtr + 1) += XQrbi_Vbpbi*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr ) += XQrbi_Vbpbi*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += XQrbi_Vbpbi*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr ) += XQrbi_Vbpbi*(s->real); |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += -XQrbi_Vbpbi*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBIPtr ) += -XQrbi_Vbpbi*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBPPtr + 1) += -XQrbi_Vbpbi*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBPPtr ) += -XQrbi_Vbpbi*(s->real); |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += XQrbi_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBIPtr ) += XQrbi_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIEmitEIPtr + 1) += XQrbi_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIEmitEIPtr ) += XQrbi_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBPEmitEIPtr + 1) += -XQrbi_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBPEmitEIPtr ) += -XQrbi_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += -XQrbi_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr ) += -XQrbi_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBPBaseBIPtr + 1) += XQrbi_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBIPtr ) += XQrbi_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBICollCIPtr + 1) += XQrbi_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBICollCIPtr ) += XQrbi_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBPCollCIPtr + 1) += -XQrbi_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBPCollCIPtr ) += -XQrbi_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += -XQrbi_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr ) += -XQrbi_Vbici*(s->real); |
||||
|
}; |
||||
|
//Qjei |
||||
|
*(here->HICUMbaseBIBaseBIPtr + 1) += XQjei_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr ) += XQjei_Vbiei*(s->real); |
||||
|
*(here->HICUMemitEIEmitEIPtr + 1) += XQjei_Vbiei*(s->imag); |
||||
|
*(here->HICUMemitEIEmitEIPtr ) += XQjei_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIEmitEIPtr + 1) += -XQjei_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIEmitEIPtr ) += -XQjei_Vbiei*(s->real); |
||||
|
*(here->HICUMemitEIBaseBIPtr + 1) += -XQjei_Vbiei*(s->imag); |
||||
|
*(here->HICUMemitEIBaseBIPtr ) += -XQjei_Vbiei*(s->real); |
||||
|
//Qf f_Bi=+ f_Ei =- |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQf_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += XQf_Vbiei*(s->real); |
||||
|
*(here->HICUMemitEIEmitEIPtr +1) += XQf_Vbiei*(s->imag); |
||||
|
*(here->HICUMemitEIEmitEIPtr) += XQf_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIEmitEIPtr +1) += -XQf_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -XQf_Vbiei*(s->real); |
||||
|
*(here->HICUMemitEIBaseBIPtr +1) += -XQf_Vbiei*(s->imag); |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -XQf_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQf_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += XQf_Vbici*(s->real); |
||||
|
*(here->HICUMemitEICollCIPtr +1) += XQf_Vbici*(s->imag); |
||||
|
*(here->HICUMemitEICollCIPtr) += XQf_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQf_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBICollCIPtr) += -XQf_Vbici*(s->real); |
||||
|
*(here->HICUMemitEIBaseBIPtr +1) += -XQf_Vbici*(s->imag); |
||||
|
*(here->HICUMemitEIBaseBIPtr) += -XQf_Vbici*(s->real); |
||||
|
if (nqs) { |
||||
|
*(here->HICUMbaseBIXfPtr +1) += XQf_Vxf*(s->imag); |
||||
|
*(here->HICUMbaseBIXfPtr ) += XQf_Vxf*(s->real); |
||||
|
*(here->HICUMemitEIXfPtr +1) += -XQf_Vxf*(s->imag); |
||||
|
*(here->HICUMemitEIXfPtr ) += -XQf_Vxf*(s->real); |
||||
|
} |
||||
|
//Qjci |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQjci_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += XQjci_Vbici*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQjci_Vbici*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQjci_Vbici*(s->real); |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQjci_Vbici*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -XQjci_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQjci_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBICollCIPtr) += -XQjci_Vbici*(s->real); |
||||
|
//Qr f_bi = + f_ci=- |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQr_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += XQr_Vbici*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQr_Vbici*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQr_Vbici*(s->real); |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQr_Vbici*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -XQr_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBICollCIPtr +1) += -XQr_Vbici*(s->imag); |
||||
|
*(here->HICUMbaseBICollCIPtr) += -XQr_Vbici*(s->real); |
||||
|
*(here->HICUMbaseBIBaseBIPtr +1) += XQr_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIBaseBIPtr) += XQr_Vbiei*(s->real); |
||||
|
*(here->HICUMcollCIEmitEIPtr +1) += XQr_Vbiei*(s->imag); |
||||
|
*(here->HICUMcollCIEmitEIPtr) += XQr_Vbiei*(s->real); |
||||
|
*(here->HICUMcollCIBaseBIPtr +1) += -XQr_Vbiei*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBIPtr) += -XQr_Vbiei*(s->real); |
||||
|
*(here->HICUMbaseBIEmitEIPtr +1) += -XQr_Vbiei*(s->imag); |
||||
|
*(here->HICUMbaseBIEmitEIPtr) += -XQr_Vbiei*(s->real); |
||||
|
//Qjep |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQjep_Vbpei*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += XQjep_Vbpei*(s->real); |
||||
|
*(here->HICUMemitEIEmitEIPtr +1) += XQjep_Vbpei*(s->imag); |
||||
|
*(here->HICUMemitEIEmitEIPtr) += XQjep_Vbpei*(s->real); |
||||
|
*(here->HICUMbaseBPEmitEIPtr +1) += -XQjep_Vbpei*(s->imag); |
||||
|
*(here->HICUMbaseBPEmitEIPtr) += -XQjep_Vbpei*(s->real); |
||||
|
*(here->HICUMemitEIBaseBPPtr +1) += -XQjep_Vbpei*(s->imag); |
||||
|
*(here->HICUMemitEIBaseBPPtr) += -XQjep_Vbpei*(s->real); |
||||
|
//Qjcx_i |
||||
|
*(here->HICUMbaseBasePtr +1) += Xqjcx0_t_i_Vbci*(s->imag); |
||||
|
*(here->HICUMbaseBasePtr) += Xqjcx0_t_i_Vbci*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += Xqjcx0_t_i_Vbci*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += Xqjcx0_t_i_Vbci*(s->real); |
||||
|
*(here->HICUMbaseCollCIPtr +1) += -Xqjcx0_t_i_Vbci*(s->imag); |
||||
|
*(here->HICUMbaseCollCIPtr) += -Xqjcx0_t_i_Vbci*(s->real); |
||||
|
*(here->HICUMcollCIBasePtr +1) += -Xqjcx0_t_i_Vbci*(s->imag); |
||||
|
*(here->HICUMcollCIBasePtr) += -Xqjcx0_t_i_Vbci*(s->real); |
||||
|
//Qjcx_ii |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += Xqjcx0_t_ii_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += Xqjcx0_t_ii_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += Xqjcx0_t_ii_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += Xqjcx0_t_ii_Vbpci*(s->real); |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -Xqjcx0_t_ii_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -Xqjcx0_t_ii_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -Xqjcx0_t_ii_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBPPtr) += -Xqjcx0_t_ii_Vbpci*(s->real); |
||||
|
//Qdsu f_bp=+ f_ci=- |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQdsu_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += XQdsu_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQdsu_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQdsu_Vbpci*(s->real); |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQdsu_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -XQdsu_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -XQdsu_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBPPtr) += -XQdsu_Vbpci*(s->real); |
||||
|
*(here->HICUMbaseBPSubsSIPtr +1) += XQdsu_Vsici*(s->imag); |
||||
|
*(here->HICUMbaseBPSubsSIPtr) += XQdsu_Vsici*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQdsu_Vsici*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQdsu_Vsici*(s->real); |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQdsu_Vsici*(s->imag); |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -XQdsu_Vsici*(s->real); |
||||
|
*(here->HICUMcollCISubsSIPtr +1) += -XQdsu_Vsici*(s->imag); |
||||
|
*(here->HICUMcollCISubsSIPtr) += -XQdsu_Vsici*(s->real); |
||||
|
//Qjs |
||||
|
*(here->HICUMsubsSISubsSIPtr +1) += XQjs_Vsici*(s->imag); |
||||
|
*(here->HICUMsubsSISubsSIPtr) += XQjs_Vsici*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQjs_Vsici*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQjs_Vsici*(s->real); |
||||
|
*(here->HICUMsubsSICollCIPtr +1) += -XQjs_Vsici*(s->imag); |
||||
|
*(here->HICUMsubsSICollCIPtr) += -XQjs_Vsici*(s->real); |
||||
|
*(here->HICUMcollCISubsSIPtr +1) += -XQjs_Vsici*(s->imag); |
||||
|
*(here->HICUMcollCISubsSIPtr) += -XQjs_Vsici*(s->real); |
||||
|
//Qscp |
||||
|
*(here->HICUMsubsSubsPtr + 1) += XQscp_Vsc*(s->imag); |
||||
|
*(here->HICUMsubsSubsPtr ) += XQscp_Vsc*(s->real); |
||||
|
*(here->HICUMcollCollPtr + 1) += XQscp_Vsc*(s->imag); |
||||
|
*(here->HICUMcollCollPtr ) += XQscp_Vsc*(s->real); |
||||
|
*(here->HICUMcollSubsPtr + 1) += -XQscp_Vsc*(s->imag); |
||||
|
*(here->HICUMcollSubsPtr ) += -XQscp_Vsc*(s->real); |
||||
|
*(here->HICUMsubsCollPtr + 1) += -XQscp_Vsc*(s->imag); |
||||
|
*(here->HICUMsubsCollPtr ) += -XQscp_Vsc*(s->real); |
||||
|
//Qbepar1 |
||||
|
*(here->HICUMbaseBasePtr + 1) += XQbepar1_Vbe*(s->imag); |
||||
|
*(here->HICUMbaseBasePtr ) += XQbepar1_Vbe*(s->real); |
||||
|
*(here->HICUMemitEmitPtr + 1) += XQbepar1_Vbe*(s->imag); |
||||
|
*(here->HICUMemitEmitPtr ) += XQbepar1_Vbe*(s->real); |
||||
|
*(here->HICUMbaseEmitPtr + 1) += -XQbepar1_Vbe*(s->imag); |
||||
|
*(here->HICUMbaseEmitPtr ) += -XQbepar1_Vbe*(s->real); |
||||
|
*(here->HICUMemitBasePtr + 1) += -XQbepar1_Vbe*(s->imag); |
||||
|
*(here->HICUMemitBasePtr ) += -XQbepar1_Vbe*(s->real); |
||||
|
//Qbepar2 |
||||
|
*(here->HICUMbaseBPBaseBPPtr + 1) += XQbepar2_Vbpe*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr ) += XQbepar2_Vbpe*(s->real); |
||||
|
*(here->HICUMemitEmitPtr + 1) += XQbepar2_Vbpe*(s->imag); |
||||
|
*(here->HICUMemitEmitPtr ) += XQbepar2_Vbpe*(s->real); |
||||
|
*(here->HICUMemitBaseBPPtr + 1) += -XQbepar2_Vbpe*(s->imag); |
||||
|
*(here->HICUMemitBaseBPPtr ) += -XQbepar2_Vbpe*(s->real); |
||||
|
*(here->HICUMbaseBPEmitPtr + 1) += -XQbepar2_Vbpe*(s->imag); |
||||
|
*(here->HICUMbaseBPEmitPtr ) += -XQbepar2_Vbpe*(s->real); |
||||
|
//Qbcpar1 |
||||
|
*(here->HICUMbaseBasePtr + 1) += XQbcpar1_Vbci*(s->imag); |
||||
|
*(here->HICUMbaseBasePtr ) += XQbcpar1_Vbci*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr + 1) += XQbcpar1_Vbci*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr ) += XQbcpar1_Vbci*(s->real); |
||||
|
*(here->HICUMbaseCollCIPtr + 1) += -XQbcpar1_Vbci*(s->imag); |
||||
|
*(here->HICUMbaseCollCIPtr ) += -XQbcpar1_Vbci*(s->real); |
||||
|
*(here->HICUMcollCIBasePtr + 1) += -XQbcpar1_Vbci*(s->imag); |
||||
|
*(here->HICUMcollCIBasePtr ) += -XQbcpar1_Vbci*(s->real); |
||||
|
//Qbcpar2 |
||||
|
*(here->HICUMbaseBPBaseBPPtr +1) += XQbcpar2_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPBaseBPPtr) += XQbcpar2_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCICollCIPtr +1) += XQbcpar2_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCICollCIPtr) += XQbcpar2_Vbpci*(s->real); |
||||
|
*(here->HICUMbaseBPCollCIPtr +1) += -XQbcpar2_Vbpci*(s->imag); |
||||
|
*(here->HICUMbaseBPCollCIPtr) += -XQbcpar2_Vbpci*(s->real); |
||||
|
*(here->HICUMcollCIBaseBPPtr +1) += -XQbcpar2_Vbpci*(s->imag); |
||||
|
*(here->HICUMcollCIBaseBPPtr) += -XQbcpar2_Vbpci*(s->real); |
||||
|
//Qsu |
||||
|
*(here->HICUMsubsSubsPtr + 1) += XQsu_Vsis*(s->imag); |
||||
|
*(here->HICUMsubsSubsPtr ) += XQsu_Vsis*(s->real); |
||||
|
*(here->HICUMsubsSISubsSIPtr + 1) += XQsu_Vsis*(s->imag); |
||||
|
*(here->HICUMsubsSISubsSIPtr ) += XQsu_Vsis*(s->real); |
||||
|
*(here->HICUMsubsSISubsPtr + 1) += -XQsu_Vsis*(s->imag); |
||||
|
*(here->HICUMsubsSISubsPtr ) += -XQsu_Vsis*(s->real); |
||||
|
*(here->HICUMsubsSubsSIPtr + 1) += -XQsu_Vsis*(s->imag); |
||||
|
*(here->HICUMsubsSubsSIPtr ) += -XQsu_Vsis*(s->real); |
||||
|
if (nqs) { |
||||
|
//Qxf1 |
||||
|
*(here->HICUMxf1Xf1Ptr + 1) += +XQxf1_Vxf1*(s->imag); |
||||
|
*(here->HICUMxf1Xf1Ptr) += +XQxf1_Vxf1*(s->real); |
||||
|
//Qxf2 |
||||
|
*(here->HICUMxf2Xf2Ptr + 1) += +XQxf2_Vxf2*(s->imag); |
||||
|
*(here->HICUMxf2Xf2Ptr ) += +XQxf2_Vxf2*(s->real); |
||||
|
//Qxf |
||||
|
*(here->HICUMxfXfPtr + 1) += +XQxf_Vxf*(s->imag); |
||||
|
*(here->HICUMxfXfPtr ) += +XQxf_Vxf*(s->real); |
||||
|
} |
||||
|
|
||||
|
// Stamps with SH |
||||
|
if (selfheat) { |
||||
|
// Stamp element: Ibiei f_Bi = + f_Ei = - |
||||
|
*(here->HICUMbaseBItempPtr) += Ibiei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Ibiei_Vrth; |
||||
|
// Stamp element: Ibpei f_Bp = + f_Ei = - |
||||
|
// with respect to Potential Vrth |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Ibpei_Vrth; |
||||
|
// Stamp element: Ibici f_Bi = + f_Ci = - |
||||
|
*(here->HICUMbaseBItempPtr) += Ibici_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Ibici_Vrth; |
||||
|
// Stamp element: Iciei f_Ci = + f_Ei = - |
||||
|
*(here->HICUMcollCItempPtr) += Iciei_Vrth; |
||||
|
*(here->HICUMemitEItempPtr) += -Iciei_Vrth; |
||||
|
// Stamp element: Ibpci f_Bp = + f_Ci = - |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpci_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Ibpci_Vrth; |
||||
|
// Stamp element: Rcx f_Ci = + f_C = - |
||||
|
*(here->HICUMcollCItempPtr) += Icic_Vrth; |
||||
|
*(here->HICUMcollTempPtr) += -Icic_Vrth; |
||||
|
// Stamp element: Rbx f_B = + f_Bp = - |
||||
|
*(here->HICUMbaseTempPtr) += Ibbp_Vrth; |
||||
|
*(here->HICUMbaseBPtempPtr) += -Ibbp_Vrth; |
||||
|
// Stamp element: Re f_Ei = + f_E = - |
||||
|
*(here->HICUMemitEItempPtr) += Ieie_Vrth; |
||||
|
*(here->HICUMemitTempPtr) += -Ieie_Vrth; |
||||
|
if (here->HICUMrbi>0.0) { |
||||
|
// Stamp element: Rbi f_Bp = + f_Bi = - |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpbi_Vrth; |
||||
|
*(here->HICUMbaseBItempPtr) += -Ibpbi_Vrth; |
||||
|
}; |
||||
|
// Stamp element: Isici f_Si = + f_Ci = - |
||||
|
*(here->HICUMsubsSItempPtr) += Isici_Vrth; |
||||
|
*(here->HICUMcollCItempPtr) += -Isici_Vrth; |
||||
|
// Branch: bpsi, Stamp element: Its |
||||
|
*(here->HICUMbaseBPtempPtr) += Ibpsi_Vrth; |
||||
|
*(here->HICUMsubsSItempPtr) += -Ibpsi_Vrth; |
||||
|
if (nqs) { |
||||
|
// Stamp element: Ixf f_xf = + |
||||
|
*(here->HICUMxfTempPtr) += Ixf_Vrth; |
||||
|
// Stamp element: Ixf1 f_xf1 = + |
||||
|
*(here->HICUMxf1TempPtr) += Ixf1_Vrth; |
||||
|
// Stamp element: Ixf2 f_xf2 = + |
||||
|
*(here->HICUMxf2TempPtr) += Ixf2_Vrth; |
||||
|
} |
||||
|
|
||||
|
// Stamp element: Rth f_T = + |
||||
|
*(here->HICUMtempTempPtr) += Irth_Vrth; |
||||
|
|
||||
|
// Stamp element: Ith f_T = - Ith |
||||
|
// with respect to Potential Vrth |
||||
|
*(here->HICUMtempTempPtr) += -Ith_Vrth; |
||||
|
// with respect to Potential Vbiei |
||||
|
*(here->HICUMtempBaseBIPtr) += -Ith_Vbiei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vbiei; |
||||
|
// with respect to Potential Vbici |
||||
|
*(here->HICUMtempBaseBIPtr) += -Ith_Vbici; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vbici; |
||||
|
// with respect to Potential Vciei |
||||
|
*(here->HICUMtempCollCIPtr) += -Ith_Vciei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vciei; |
||||
|
// with respect to Potential Vbpei |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpei; |
||||
|
*(here->HICUMtempEmitEIPtr) += +Ith_Vbpei; |
||||
|
// with respect to Potential Vbpci |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpci; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vbpci; |
||||
|
// with respect to Potential Vsici |
||||
|
*(here->HICUMtempSubsSIPtr) += -Ith_Vsici; |
||||
|
*(here->HICUMtempCollCIPtr) += +Ith_Vsici; |
||||
|
// with respect to Potential Vbpbi |
||||
|
*(here->HICUMtempBaseBPPtr) += -Ith_Vbpbi; |
||||
|
*(here->HICUMtempBaseBIPtr) += +Ith_Vbpbi; |
||||
|
// with respect to Potential Vcic |
||||
|
*(here->HICUMtempCollCIPtr) += -Ith_Vcic; |
||||
|
*(here->HICUMtempCollPtr) += +Ith_Vcic; |
||||
|
// with respect to Potential Vbbp |
||||
|
*(here->HICUMtempBasePtr) += -Ith_Vbbp; |
||||
|
*(here->HICUMtempBaseBPPtr) += +Ith_Vbbp; |
||||
|
// with respect to Potential Veie |
||||
|
*(here->HICUMtempEmitEIPtr) += -Ith_Veie; |
||||
|
*(here->HICUMtempEmitPtr) += +Ith_Veie; |
||||
|
|
||||
|
//the charges |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQrbi_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBItempPtr ) += +XQrbi_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += -XQrbi_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBPtempPtr ) += -XQrbi_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQjei_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBItempPtr ) += +XQjei_Vrth*(s->real); |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQjei_Vrth*(s->imag); |
||||
|
*(here->HICUMemitEItempPtr ) += -XQjei_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQf_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBItempPtr ) += +XQf_Vrth*(s->real); |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQf_Vrth*(s->imag); |
||||
|
*(here->HICUMemitEItempPtr ) += -XQf_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQr_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBItempPtr ) += +XQr_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQr_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -XQr_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBItempPtr + 1) += +XQjci_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBItempPtr ) += +XQjci_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQjci_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -XQjci_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +XQjep_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBPtempPtr ) += +XQjep_Vrth*(s->real); |
||||
|
*(here->HICUMemitEItempPtr + 1) += -XQjep_Vrth*(s->imag); |
||||
|
*(here->HICUMemitEItempPtr ) += -XQjep_Vrth*(s->real); |
||||
|
*(here->HICUMbaseTempPtr + 1) += +Xqjcx0_t_i_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseTempPtr ) += +Xqjcx0_t_i_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -Xqjcx0_t_i_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -Xqjcx0_t_i_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +Xqjcx0_t_ii_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBPtempPtr ) += +Xqjcx0_t_ii_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -Xqjcx0_t_ii_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -Xqjcx0_t_ii_Vrth*(s->real); |
||||
|
*(here->HICUMbaseBPtempPtr + 1) += +XQdsu_Vrth*(s->imag); |
||||
|
*(here->HICUMbaseBPtempPtr ) += +XQdsu_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQdsu_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -XQdsu_Vrth*(s->real); |
||||
|
*(here->HICUMsubsSItempPtr + 1) += +XQjs_Vrth*(s->imag); |
||||
|
*(here->HICUMsubsSItempPtr ) += +XQjs_Vrth*(s->real); |
||||
|
*(here->HICUMcollCItempPtr + 1) += -XQjs_Vrth*(s->imag); |
||||
|
*(here->HICUMcollCItempPtr ) += -XQjs_Vrth*(s->real); |
||||
|
*(here->HICUMsubsTempPtr + 1) += +XQscp_Vrth*(s->imag); |
||||
|
*(here->HICUMsubsTempPtr ) += +XQscp_Vrth*(s->real); |
||||
|
*(here->HICUMcollTempPtr + 1) += -XQscp_Vrth*(s->imag); |
||||
|
*(here->HICUMcollTempPtr ) += -XQscp_Vrth*(s->real); |
||||
|
*(here->HICUMtempTempPtr + 1) += +XQcth_Vrth*(s->imag); |
||||
|
*(here->HICUMtempTempPtr ) += +XQcth_Vrth*(s->real); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
@ -0,0 +1,863 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine should only be called when circuit topology |
||||
|
* changes, since its computations do not depend on most |
||||
|
* device or model parameters, only on topology (as |
||||
|
* affected by emitter, collector, and base resistances) |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "ngspice/smpdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/const.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/ifsim.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
int |
||||
|
HICUMsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) |
||||
|
/* load the HICUM structure with those pointers needed later |
||||
|
* for fast matrix loading |
||||
|
*/ |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
HICUMinstance *here; |
||||
|
int error; |
||||
|
CKTnode *tmp; |
||||
|
|
||||
|
/* loop through all the transistor models */ |
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
|
||||
|
//Circuit simulator specific parameters |
||||
|
if(model->HICUMtype != NPN && model->HICUMtype != PNP) |
||||
|
model->HICUMtype = NPN; |
||||
|
|
||||
|
if(!model->HICUMtnomGiven) |
||||
|
model->HICUMtnom = ckt->CKTnomTemp; |
||||
|
|
||||
|
if (!model->HICUMversionGiven) |
||||
|
model->HICUMversion = copy("2.4.0"); |
||||
|
|
||||
|
//Transfer current |
||||
|
if(!model->HICUMc10Given) |
||||
|
model->HICUMc10 = 2e-30; |
||||
|
|
||||
|
if(!model->HICUMqp0Given) |
||||
|
model->HICUMqp0 = 2e-14; |
||||
|
|
||||
|
if(!model->HICUMichGiven) |
||||
|
model->HICUMich = 0.0; |
||||
|
|
||||
|
if(!model->HICUMhf0Given) |
||||
|
model->HICUMhf0 = 1.0; |
||||
|
|
||||
|
if(!model->HICUMhfeGiven) |
||||
|
model->HICUMhfe = 1.0; |
||||
|
|
||||
|
if(!model->HICUMhfcGiven) |
||||
|
model->HICUMhfc = 1.0; |
||||
|
|
||||
|
if(!model->HICUMhjeiGiven) |
||||
|
model->HICUMhjei = 1.0; |
||||
|
|
||||
|
if(!model->HICUMahjeiGiven) |
||||
|
model->HICUMahjei = 0.0; |
||||
|
|
||||
|
if(!model->HICUMrhjeiGiven) |
||||
|
model->HICUMrhjei = 1.0; |
||||
|
|
||||
|
if(!model->HICUMhjciGiven) |
||||
|
model->HICUMhjci = 1.0; |
||||
|
|
||||
|
//Base-Emitter diode; |
||||
|
if(!model->HICUMibeisGiven) |
||||
|
model->HICUMibeis = 1e-18; |
||||
|
|
||||
|
if(!model->HICUMmbeiGiven) |
||||
|
model->HICUMmbei = 1.0; |
||||
|
|
||||
|
if(!model->HICUMireisGiven) |
||||
|
model->HICUMireis = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmreiGiven) |
||||
|
model->HICUMmrei = 2.0; |
||||
|
|
||||
|
if(!model->HICUMibepsGiven) |
||||
|
model->HICUMibeps = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmbepGiven) |
||||
|
model->HICUMmbep = 1.0; |
||||
|
|
||||
|
if(!model->HICUMirepsGiven) |
||||
|
model->HICUMireps = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmrepGiven) |
||||
|
model->HICUMmrep = 2.0; |
||||
|
|
||||
|
if(!model->HICUMmcfGiven) |
||||
|
model->HICUMmcf = 1.0; |
||||
|
|
||||
|
//Transit time for excess recombination current at b-c barrier |
||||
|
if(!model->HICUMtbhrecGiven) |
||||
|
model->HICUMtbhrec = 0.0; |
||||
|
|
||||
|
//Base-Collector diode currents |
||||
|
if(!model->HICUMibcisGiven) |
||||
|
model->HICUMibcis = 1e-16; |
||||
|
|
||||
|
if(!model->HICUMmbciGiven) |
||||
|
model->HICUMmbci = 1.0; |
||||
|
|
||||
|
if(!model->HICUMibcxsGiven) |
||||
|
model->HICUMibcxs = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmbcxGiven) |
||||
|
model->HICUMmbcx = 1.0; |
||||
|
|
||||
|
//Base-Emitter tunneling current |
||||
|
if(!model->HICUMibetsGiven) |
||||
|
model->HICUMibets = 0.0; |
||||
|
|
||||
|
if(!model->HICUMabetGiven) |
||||
|
model->HICUMabet = 40.0; |
||||
|
|
||||
|
if(!model->HICUMtunodeGiven) |
||||
|
model->HICUMtunode = 1; |
||||
|
|
||||
|
//Base-Collector avalanche current |
||||
|
if(!model->HICUMfavlGiven) |
||||
|
model->HICUMfavl = 0.0; |
||||
|
|
||||
|
if(!model->HICUMqavlGiven) |
||||
|
model->HICUMqavl = 0.0; |
||||
|
|
||||
|
if(!model->HICUMkavlGiven) |
||||
|
model->HICUMkavl = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalfavGiven) |
||||
|
model->HICUMalfav = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalqavGiven) |
||||
|
model->HICUMalqav = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalkavGiven) |
||||
|
model->HICUMalkav = 0.0; |
||||
|
|
||||
|
//Series resistances |
||||
|
if(!model->HICUMrbi0Given) |
||||
|
model->HICUMrbi0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMrbxGiven) |
||||
|
model->HICUMrbx = 0.0; |
||||
|
|
||||
|
if(!model->HICUMfgeoGiven) |
||||
|
model->HICUMfgeo = 0.6557; |
||||
|
|
||||
|
if(!model->HICUMfdqr0Given) |
||||
|
model->HICUMfdqr0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMfcrbiGiven) |
||||
|
model->HICUMfcrbi = 0.0; |
||||
|
|
||||
|
if(!model->HICUMfqiGiven) |
||||
|
model->HICUMfqi = 1.0; |
||||
|
|
||||
|
if(!model->HICUMreGiven) |
||||
|
model->HICUMre = 0.0; |
||||
|
|
||||
|
if(!model->HICUMrcxGiven) |
||||
|
model->HICUMrcx = 0.0; |
||||
|
|
||||
|
//Substrate transistor |
||||
|
if(!model->HICUMitssGiven) |
||||
|
model->HICUMitss = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmsfGiven) |
||||
|
model->HICUMmsf = 1.0; |
||||
|
|
||||
|
if(!model->HICUMiscsGiven) |
||||
|
model->HICUMiscs = 0.0; |
||||
|
|
||||
|
if(!model->HICUMmscGiven) |
||||
|
model->HICUMmsc = 1.0; |
||||
|
|
||||
|
if(!model->HICUMtsfGiven) |
||||
|
model->HICUMtsf = 0.0; |
||||
|
|
||||
|
//Intra-device substrate coupling |
||||
|
if(!model->HICUMrsuGiven) |
||||
|
model->HICUMrsu = 0.0; |
||||
|
|
||||
|
if(!model->HICUMcsuGiven) |
||||
|
model->HICUMcsu = 0.0; |
||||
|
|
||||
|
//Depletion Capacitances |
||||
|
if(!model->HICUMcjei0Given) |
||||
|
model->HICUMcjei0 = 1.0e-20; |
||||
|
|
||||
|
if(!model->HICUMvdeiGiven) |
||||
|
model->HICUMvdei = 0.9; |
||||
|
|
||||
|
if(!model->HICUMzeiGiven) |
||||
|
model->HICUMzei = 0.5; |
||||
|
|
||||
|
if(!model->HICUMajeiGiven) |
||||
|
model->HICUMajei = 2.5; |
||||
|
|
||||
|
if(!model->HICUMcjep0Given) |
||||
|
model->HICUMcjep0 = 1.0e-20; |
||||
|
|
||||
|
if(!model->HICUMvdepGiven) |
||||
|
model->HICUMvdep = 0.9; |
||||
|
|
||||
|
if(!model->HICUMzepGiven) |
||||
|
model->HICUMzep = 0.5; |
||||
|
|
||||
|
if(!model->HICUMajepGiven) |
||||
|
model->HICUMajep = 2.5; |
||||
|
|
||||
|
if(!model->HICUMcjci0Given) |
||||
|
model->HICUMcjci0 = 1.0e-20; |
||||
|
|
||||
|
if(!model->HICUMvdciGiven) |
||||
|
model->HICUMvdci = 0.7; |
||||
|
|
||||
|
if(!model->HICUMzciGiven) |
||||
|
model->HICUMzci = 0.4; |
||||
|
|
||||
|
if(!model->HICUMvptciGiven) |
||||
|
model->HICUMvptci = 100.0; |
||||
|
|
||||
|
if(!model->HICUMcjcx0Given) |
||||
|
model->HICUMcjcx0 = 1.0e-20; |
||||
|
|
||||
|
if(!model->HICUMvdcxGiven) |
||||
|
model->HICUMvdcx = 0.7; |
||||
|
|
||||
|
if(!model->HICUMzcxGiven) |
||||
|
model->HICUMzcx = 0.4; |
||||
|
|
||||
|
if(!model->HICUMvptcxGiven) |
||||
|
model->HICUMvptcx = 100.0; |
||||
|
|
||||
|
if(!model->HICUMfbcparGiven) |
||||
|
model->HICUMfbcpar = 0.0; |
||||
|
|
||||
|
if(!model->HICUMfbeparGiven) |
||||
|
model->HICUMfbepar = 1.0; |
||||
|
|
||||
|
if(!model->HICUMcjs0Given) |
||||
|
model->HICUMcjs0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMvdsGiven) |
||||
|
model->HICUMvds = 0.6; |
||||
|
|
||||
|
if(!model->HICUMzsGiven) |
||||
|
model->HICUMzs = 0.5; |
||||
|
|
||||
|
if(!model->HICUMvptsGiven) |
||||
|
model->HICUMvpts = 100.0; |
||||
|
|
||||
|
if(!model->HICUMcscp0Given) |
||||
|
model->HICUMcscp0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMvdspGiven) |
||||
|
model->HICUMvdsp = 0.6; |
||||
|
|
||||
|
if(!model->HICUMzspGiven) |
||||
|
model->HICUMzsp = 0.5; |
||||
|
|
||||
|
if(!model->HICUMvptspGiven) |
||||
|
model->HICUMvptsp = 100.0; |
||||
|
|
||||
|
//Diffusion Capacitances |
||||
|
if(!model->HICUMt0Given) |
||||
|
model->HICUMt0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMdt0hGiven) |
||||
|
model->HICUMdt0h = 0.0; |
||||
|
|
||||
|
if(!model->HICUMtbvlGiven) |
||||
|
model->HICUMtbvl = 0.0; |
||||
|
|
||||
|
if(!model->HICUMtef0Given) |
||||
|
model->HICUMtef0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMgtfeGiven) |
||||
|
model->HICUMgtfe = 1.0; |
||||
|
|
||||
|
if(!model->HICUMthcsGiven) |
||||
|
model->HICUMthcs = 0.0; |
||||
|
|
||||
|
if(!model->HICUMahcGiven) |
||||
|
model->HICUMahc = 0.1; |
||||
|
|
||||
|
if(!model->HICUMfthcGiven) |
||||
|
model->HICUMfthc = 0.0; |
||||
|
|
||||
|
if(!model->HICUMrci0Given) |
||||
|
model->HICUMrci0 = 150; |
||||
|
|
||||
|
if(!model->HICUMvlimGiven) |
||||
|
model->HICUMvlim = 0.5; |
||||
|
|
||||
|
if(!model->HICUMvcesGiven) |
||||
|
model->HICUMvces = 0.1; |
||||
|
|
||||
|
if(!model->HICUMvptGiven) |
||||
|
model->HICUMvpt = 100.0; |
||||
|
|
||||
|
if(!model->HICUMaickGiven) |
||||
|
model->HICUMaick = 1.0e-03; |
||||
|
|
||||
|
if(!model->HICUMdelckGiven) |
||||
|
model->HICUMdelck = 2.0; |
||||
|
|
||||
|
if(!model->HICUMtrGiven) |
||||
|
model->HICUMtr = 0.0; |
||||
|
|
||||
|
if(!model->HICUMvcbarGiven) |
||||
|
model->HICUMvcbar = 0.0; |
||||
|
|
||||
|
if(!model->HICUMicbarGiven) |
||||
|
model->HICUMicbar = 0.0; |
||||
|
|
||||
|
if(!model->HICUMacbarGiven) |
||||
|
model->HICUMacbar = 0.01; |
||||
|
|
||||
|
//Isolation Capacitances |
||||
|
if(!model->HICUMcbeparGiven) |
||||
|
model->HICUMcbepar = 0.0; |
||||
|
|
||||
|
if(!model->HICUMcbcparGiven) |
||||
|
model->HICUMcbcpar = 0.0; |
||||
|
|
||||
|
//Non-quasi-static Effect |
||||
|
if(!model->HICUMalqfGiven) |
||||
|
model->HICUMalqf = 0.167; |
||||
|
|
||||
|
if(!model->HICUMalitGiven) |
||||
|
model->HICUMalit = 0.333; |
||||
|
|
||||
|
if(!model->HICUMflnqsGiven) |
||||
|
model->HICUMflnqs = 0; |
||||
|
|
||||
|
//Noise |
||||
|
if(!model->HICUMkfGiven) |
||||
|
model->HICUMkf = 0.0; |
||||
|
|
||||
|
if(!model->HICUMafGiven) |
||||
|
model->HICUMaf = 2.0; |
||||
|
|
||||
|
if(!model->HICUMcfbeGiven) |
||||
|
model->HICUMcfbe = -1; |
||||
|
|
||||
|
if(!model->HICUMflconoGiven) |
||||
|
model->HICUMflcono = 0; |
||||
|
|
||||
|
if(!model->HICUMkfreGiven) |
||||
|
model->HICUMkfre = 0.0; |
||||
|
|
||||
|
if(!model->HICUMafreGiven) |
||||
|
model->HICUMafre = 2.0; |
||||
|
|
||||
|
//Lateral Geometry Scaling (at high current densities) |
||||
|
if(!model->HICUMlatbGiven) |
||||
|
model->HICUMlatb = 0.0; |
||||
|
|
||||
|
if(!model->HICUMlatlGiven) |
||||
|
model->HICUMlatl = 0.0; |
||||
|
|
||||
|
//Temperature dependence |
||||
|
if(!model->HICUMvgbGiven) |
||||
|
model->HICUMvgb = 1.17; |
||||
|
|
||||
|
if(!model->HICUMalt0Given) |
||||
|
model->HICUMalt0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMkt0Given) |
||||
|
model->HICUMkt0 = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetaciGiven) |
||||
|
model->HICUMzetaci = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalvsGiven) |
||||
|
model->HICUMalvs = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalcesGiven) |
||||
|
model->HICUMalces = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetarbiGiven) |
||||
|
model->HICUMzetarbi = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetarbxGiven) |
||||
|
model->HICUMzetarbx = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetarcxGiven) |
||||
|
model->HICUMzetarcx = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetareGiven) |
||||
|
model->HICUMzetare = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetacxGiven) |
||||
|
model->HICUMzetacx = 1.0; |
||||
|
|
||||
|
if(!model->HICUMvgeGiven) |
||||
|
model->HICUMvge = 1.17; |
||||
|
|
||||
|
if(!model->HICUMvgcGiven) |
||||
|
model->HICUMvgc = 1.17; |
||||
|
|
||||
|
if(!model->HICUMvgsGiven) |
||||
|
model->HICUMvgs = 1.17; |
||||
|
|
||||
|
if(!model->HICUMf1vgGiven) |
||||
|
model->HICUMf1vg = -1.02377e-4; |
||||
|
|
||||
|
if(!model->HICUMf2vgGiven) |
||||
|
model->HICUMf2vg = 4.3215e-4; |
||||
|
|
||||
|
if(!model->HICUMzetactGiven) |
||||
|
model->HICUMzetact = 3.0; |
||||
|
|
||||
|
if(!model->HICUMzetabetGiven) |
||||
|
model->HICUMzetabet = 3.5; |
||||
|
|
||||
|
if(!model->HICUMalbGiven) |
||||
|
model->HICUMalb = 0.0; |
||||
|
|
||||
|
if(!model->HICUMdvgbeGiven) |
||||
|
model->HICUMdvgbe = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetahjeiGiven) |
||||
|
model->HICUMzetahjei = 1.0; |
||||
|
|
||||
|
if(!model->HICUMzetavgbeGiven) |
||||
|
model->HICUMzetavgbe = 1.0; |
||||
|
|
||||
|
//Self-Heating |
||||
|
if(!model->HICUMflshGiven) |
||||
|
model->HICUMflsh = 0; |
||||
|
|
||||
|
if(!model->HICUMrthGiven) |
||||
|
model->HICUMrth = 0.0; |
||||
|
|
||||
|
if(!model->HICUMzetarthGiven) |
||||
|
model->HICUMzetarth = 0.0; |
||||
|
|
||||
|
if(!model->HICUMalrthGiven) |
||||
|
model->HICUMalrth = 0.0; |
||||
|
|
||||
|
if(!model->HICUMcthGiven) |
||||
|
model->HICUMcth = 0.0; |
||||
|
|
||||
|
if((model->HICUMrthGiven) && (model->HICUMcth < 1e-12)) |
||||
|
model->HICUMcth = 1e-12; |
||||
|
|
||||
|
//Compatibility with V2.1 |
||||
|
if(!model->HICUMflcompGiven) |
||||
|
model->HICUMflcomp = 0.0; |
||||
|
|
||||
|
if(!model->HICUMvbeMaxGiven) |
||||
|
model->HICUMvbeMax = 1e99; |
||||
|
|
||||
|
if(!model->HICUMvbcMaxGiven) |
||||
|
model->HICUMvbcMax = 1e99; |
||||
|
|
||||
|
if(!model->HICUMvceMaxGiven) |
||||
|
model->HICUMvceMax = 1e99; |
||||
|
|
||||
|
int selfheat = (((model->HICUMflsh == 1) || (model->HICUMflsh == 2)) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0)); |
||||
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0)); |
||||
|
|
||||
|
/* loop through all the instances of the model */ |
||||
|
for (here = HICUMinstances(model); here != NULL ; |
||||
|
here=HICUMnextInstance(here)) { |
||||
|
CKTnode *tmpNode; |
||||
|
IFuid tmpName; |
||||
|
|
||||
|
if(!here->HICUMareaGiven) { |
||||
|
here->HICUMarea = 1.0; |
||||
|
} |
||||
|
if(!here->HICUMmGiven) { |
||||
|
here->HICUMm = 1.0; |
||||
|
} |
||||
|
if(!here->HICUMdtempGiven) { |
||||
|
here->HICUMdtemp = 0.0; |
||||
|
} |
||||
|
|
||||
|
// Warning: |
||||
|
// The scaling with HICUMm and HICUMarea is done here from model to here variables in order to save memory. |
||||
|
// Classical spice scaling with "area" is implemented, but it is not recommended to be used. If you want |
||||
|
// scaling, more sophisticated expressions should be used. Those can be found in modern PDKs or should be |
||||
|
// provided by modeling engineers. |
||||
|
// For discrete devices, the multiplication factor "m" should give reasonable results. |
||||
|
// |
||||
|
// The HICUMm device multiplicaton factor can be exected to give good results. |
||||
|
// The following variables need scaling in HICUM: |
||||
|
// IT : qp0 ~ (area m)**2 qp0 ~ area m icbar ~ area m |
||||
|
// BE junction: cjei0 ~ area m cjep0 ~ m |
||||
|
// ibeis ~ area m ibeps ~ m |
||||
|
// cbepar ~ m -> area scaling not reasonable |
||||
|
// BC junction: cjci0 ~ area m cjcx0 ~ m |
||||
|
// ibcis ~ area m ibcxs ~ m |
||||
|
// ireis ~ area m ireps ~ m |
||||
|
// cbcpar ~ m -> area scaling not reasonable |
||||
|
// qavl ~ area m |
||||
|
// re ~1/(area*m) |
||||
|
// rci0 ~1/(area*m) |
||||
|
// rbx ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase |
||||
|
// rcx ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase |
||||
|
// rbi0 ~1/(area*m) -> assume that scaling with "area" is due to lE0 increase |
||||
|
// rth ~1/(area*m) -> bad assumption, but more transistor geometry needs to be known for accurate scaling |
||||
|
// cth ~ area*m -> bad assumption, but more transistor geometry needs to be known for accurate scaling |
||||
|
// Substrate related parameters not scaled on purpose. This is very geometry dependent? |
||||
|
|
||||
|
double area_times_m = here->HICUMm*here->HICUMarea; |
||||
|
//IT |
||||
|
here->HICUMqp0_scaled = model->HICUMqp0 * area_times_m; |
||||
|
here->HICUMc10_scaled = model->HICUMc10 * area_times_m*area_times_m; |
||||
|
here->HICUMicbar_scaled = model->HICUMicbar * area_times_m; |
||||
|
here->HICUMrth_scaled = model->HICUMrth / area_times_m; //very poor assumption |
||||
|
here->HICUMcth_scaled = model->HICUMcth * area_times_m; //very poor assumption |
||||
|
//BE junction |
||||
|
here->HICUMcjei0_scaled = model->HICUMcjei0 * area_times_m; |
||||
|
here->HICUMibeis_scaled = model->HICUMibeis * area_times_m; |
||||
|
here->HICUMireis_scaled = model->HICUMireis * area_times_m; |
||||
|
here->HICUMibeps_scaled = model->HICUMibeps * here->HICUMm; |
||||
|
here->HICUMireps_scaled = model->HICUMireps * here->HICUMm; |
||||
|
here->HICUMcjep0_scaled = model->HICUMcjep0 * here->HICUMm; |
||||
|
here->HICUMcbepar_scaled = model->HICUMcbepar * here->HICUMm; |
||||
|
here->HICUMibets_scaled = model->HICUMibets * area_times_m; |
||||
|
//BC junction |
||||
|
here->HICUMibcis_scaled = model->HICUMibcis * area_times_m; |
||||
|
here->HICUMcjci0_scaled = model->HICUMcjci0 * area_times_m; |
||||
|
here->HICUMcjcx0_scaled = model->HICUMcjcx0 * here->HICUMm; |
||||
|
here->HICUMcbcpar_scaled = model->HICUMcbcpar * here->HICUMm; |
||||
|
here->HICUMibcxs_scaled = model->HICUMibcxs * here->HICUMm; |
||||
|
here->HICUMqavl_scaled = model->HICUMqavl * area_times_m; |
||||
|
//resistances |
||||
|
here->HICUMre_scaled = model->HICUMre / area_times_m; |
||||
|
here->HICUMrci0_scaled = model->HICUMrci0 / area_times_m; |
||||
|
here->HICUMrbx_scaled = model->HICUMrbx / area_times_m; |
||||
|
here->HICUMrcx_scaled = model->HICUMrcx / area_times_m; |
||||
|
here->HICUMrbi0_scaled = model->HICUMrbi0 / area_times_m; |
||||
|
//noise |
||||
|
here->HICUMkf_scaled = model->HICUMkf * pow(here->HICUMm, (1-model->HICUMaf)); |
||||
|
here->HICUMkfre_scaled = model->HICUMkfre * pow(here->HICUMm, (1-model->HICUMafre)); |
||||
|
|
||||
|
here->HICUMstate = *states; |
||||
|
*states += HICUMnumStates; |
||||
|
|
||||
|
if(model->HICUMrcx == 0) { |
||||
|
here->HICUMcollCINode = here->HICUMcollNode; |
||||
|
} else if(here->HICUMcollCINode == 0) { |
||||
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname,"collCI"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMcollCINode = tmp->number; |
||||
|
if (ckt->CKTcopyNodesets) { |
||||
|
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { |
||||
|
if (tmpNode->nsGiven) { |
||||
|
tmp->nodeset=tmpNode->nodeset; |
||||
|
tmp->nsGiven=tmpNode->nsGiven; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if(model->HICUMrbx == 0) { |
||||
|
here->HICUMbaseBPNode = here->HICUMbaseNode; |
||||
|
} else if(here->HICUMbaseBPNode == 0){ |
||||
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "baseBP"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMbaseBPNode = tmp->number; |
||||
|
if (ckt->CKTcopyNodesets) { |
||||
|
if (CKTinst2Node(ckt,here,2,&tmpNode,&tmpName)==OK) { |
||||
|
if (tmpNode->nsGiven) { |
||||
|
tmp->nodeset=tmpNode->nodeset; |
||||
|
tmp->nsGiven=tmpNode->nsGiven; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if(model->HICUMre == 0) { |
||||
|
here->HICUMemitEINode = here->HICUMemitNode; |
||||
|
} else if(here->HICUMemitEINode == 0) { |
||||
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "emitEI"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMemitEINode = tmp->number; |
||||
|
if (ckt->CKTcopyNodesets) { |
||||
|
if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { |
||||
|
if (tmpNode->nsGiven) { |
||||
|
tmp->nodeset=tmpNode->nodeset; |
||||
|
tmp->nsGiven=tmpNode->nsGiven; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if(model->HICUMrsu == 0) { |
||||
|
here->HICUMsubsSINode = here->HICUMsubsNode; |
||||
|
} else if(here->HICUMsubsSINode == 0) { |
||||
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname, "subsSI"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMsubsSINode = tmp->number; |
||||
|
if (ckt->CKTcopyNodesets) { |
||||
|
if (CKTinst2Node(ckt,here,4,&tmpNode,&tmpName)==OK) { |
||||
|
if (tmpNode->nsGiven) { |
||||
|
tmp->nodeset=tmpNode->nodeset; |
||||
|
tmp->nsGiven=tmpNode->nsGiven; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if(model->HICUMrbi0 == 0) { |
||||
|
here->HICUMbaseBINode = here->HICUMbaseBPNode; |
||||
|
} else if(here->HICUMbaseBINode == 0) { |
||||
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "baseBI"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMbaseBINode = tmp->number; |
||||
|
if (ckt->CKTcopyNodesets) { |
||||
|
if (CKTinst2Node(ckt,here,5,&tmpNode,&tmpName)==OK) { |
||||
|
if (tmpNode->nsGiven) { |
||||
|
tmp->nodeset=tmpNode->nodeset; |
||||
|
tmp->nsGiven=tmpNode->nsGiven; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (selfheat) { |
||||
|
if (here->HICUMtempNode == 0) { // no external node for temperature |
||||
|
error = CKTmkVolt(ckt,&tmp,here->HICUMname,"dT"); // create internal node |
||||
|
if (error) return(error); |
||||
|
here->HICUMtempNode = tmp->number; |
||||
|
} |
||||
|
} else { |
||||
|
if (here->HICUMtempNode > 0) { // external temp node is given, but no she parameter |
||||
|
here->HICUMtempNode = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (nqs) { |
||||
|
if(here->HICUMxfNode == 0) { |
||||
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMxfNode = tmp->number; |
||||
|
} |
||||
|
if(here->HICUMxf1Node == 0) { |
||||
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf1"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMxf1Node = tmp->number; |
||||
|
} |
||||
|
if(here->HICUMxf2Node == 0) { |
||||
|
error = CKTmkVolt(ckt, &tmp, here->HICUMname, "xf2"); |
||||
|
if(error) return(error); |
||||
|
here->HICUMxf2Node = tmp->number; |
||||
|
} |
||||
|
} else { |
||||
|
here->HICUMxfNode = 0; |
||||
|
here->HICUMxf1Node = 0; |
||||
|
here->HICUMxf2Node = 0; |
||||
|
} |
||||
|
|
||||
|
/* macro to make elements with built in test for out of memory */ |
||||
|
#define TSTALLOC(ptr,first,second) \ |
||||
|
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\ |
||||
|
return(E_NOMEM);\ |
||||
|
} } while(0) |
||||
|
TSTALLOC(HICUMcollCollPtr,HICUMcollNode,HICUMcollNode); |
||||
|
TSTALLOC(HICUMbaseBasePtr,HICUMbaseNode,HICUMbaseNode); |
||||
|
TSTALLOC(HICUMemitEmitPtr,HICUMemitNode,HICUMemitNode); |
||||
|
TSTALLOC(HICUMsubsSubsPtr,HICUMsubsNode,HICUMsubsNode); |
||||
|
|
||||
|
TSTALLOC(HICUMcollCICollCIPtr,HICUMcollCINode,HICUMcollCINode); |
||||
|
TSTALLOC(HICUMbaseBIBaseBIPtr,HICUMbaseBINode,HICUMbaseBINode); |
||||
|
TSTALLOC(HICUMemitEIEmitEIPtr,HICUMemitEINode,HICUMemitEINode); |
||||
|
TSTALLOC(HICUMbaseBPBaseBPPtr,HICUMbaseBPNode,HICUMbaseBPNode); |
||||
|
TSTALLOC(HICUMsubsSISubsSIPtr,HICUMsubsSINode,HICUMsubsSINode); |
||||
|
|
||||
|
TSTALLOC(HICUMbaseEmitPtr,HICUMbaseNode,HICUMemitNode); //b-e |
||||
|
TSTALLOC(HICUMemitBasePtr,HICUMemitNode,HICUMbaseNode); //e-b |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBaseBPPtr,HICUMbaseNode,HICUMbaseBPNode); //b-bp |
||||
|
TSTALLOC(HICUMbaseBPBasePtr,HICUMbaseBPNode,HICUMbaseNode); //bp-b |
||||
|
TSTALLOC(HICUMemitEmitEIPtr,HICUMemitNode,HICUMemitEINode); //e-ei |
||||
|
TSTALLOC(HICUMemitEIEmitPtr,HICUMemitEINode,HICUMemitNode); //ei-e |
||||
|
|
||||
|
TSTALLOC(HICUMsubsSubsSIPtr,HICUMsubsNode,HICUMsubsSINode); //s-si |
||||
|
TSTALLOC(HICUMsubsSISubsPtr,HICUMsubsSINode,HICUMsubsNode); //si-s |
||||
|
|
||||
|
TSTALLOC(HICUMcollCIBasePtr,HICUMcollCINode,HICUMbaseNode); //b-ci |
||||
|
TSTALLOC(HICUMbaseCollCIPtr,HICUMbaseNode,HICUMcollCINode); //ci-b |
||||
|
|
||||
|
TSTALLOC(HICUMcollCIEmitEIPtr,HICUMcollCINode,HICUMemitEINode); //ci-ei |
||||
|
TSTALLOC(HICUMemitEICollCIPtr,HICUMemitEINode,HICUMcollCINode); //ei-ci |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPBaseBIPtr,HICUMbaseBPNode,HICUMbaseBINode); //bp-bi |
||||
|
TSTALLOC(HICUMbaseBIBaseBPPtr,HICUMbaseBINode,HICUMbaseBPNode); //bi-bp |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPEmitEIPtr,HICUMbaseBPNode,HICUMemitEINode); //bp-ei |
||||
|
TSTALLOC(HICUMemitEIBaseBPPtr,HICUMemitEINode,HICUMbaseBPNode); //ei-bp |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPEmitPtr,HICUMbaseBPNode,HICUMemitNode); //bp-e |
||||
|
TSTALLOC(HICUMemitBaseBPPtr,HICUMemitNode,HICUMbaseBPNode); //e-bp |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPSubsSIPtr,HICUMbaseBPNode,HICUMsubsSINode); //bp-si |
||||
|
TSTALLOC(HICUMsubsSIBaseBPPtr,HICUMsubsSINode,HICUMbaseBPNode); //si-bp |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBIEmitEIPtr,HICUMbaseBINode,HICUMemitEINode); //ei-bi |
||||
|
TSTALLOC(HICUMemitEIBaseBIPtr,HICUMemitEINode,HICUMbaseBINode); //bi-ei |
||||
|
if (nqs) { |
||||
|
TSTALLOC(HICUMbaseBIXfPtr ,HICUMbaseBINode,HICUMxfNode); //bi - xf |
||||
|
TSTALLOC(HICUMemitEIXfPtr ,HICUMemitEINode,HICUMxfNode); //ei - xf |
||||
|
} |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBICollCIPtr,HICUMbaseBINode,HICUMcollCINode); //ci-bi |
||||
|
TSTALLOC(HICUMcollCIBaseBIPtr,HICUMcollCINode,HICUMbaseBINode); //bi-ci |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPCollCIPtr,HICUMbaseBPNode,HICUMcollCINode); //bp-ci |
||||
|
TSTALLOC(HICUMcollCIBaseBPPtr,HICUMcollCINode,HICUMbaseBPNode); //ci-bp |
||||
|
|
||||
|
TSTALLOC(HICUMsubsSICollCIPtr,HICUMsubsSINode,HICUMcollCINode); //si-ci |
||||
|
TSTALLOC(HICUMcollCISubsSIPtr,HICUMcollCINode,HICUMsubsSINode); //ci-si |
||||
|
|
||||
|
TSTALLOC(HICUMcollCICollPtr,HICUMcollCINode,HICUMcollNode); //ci-c |
||||
|
TSTALLOC(HICUMcollCollCIPtr,HICUMcollNode,HICUMcollCINode); //c-ci |
||||
|
|
||||
|
TSTALLOC(HICUMsubsCollPtr,HICUMsubsNode,HICUMcollNode); //s-c |
||||
|
TSTALLOC(HICUMcollSubsPtr,HICUMcollNode,HICUMsubsNode); //c-s |
||||
|
|
||||
|
if (nqs) { |
||||
|
TSTALLOC(HICUMxf1Xf1Ptr ,HICUMxf1Node ,HICUMxf1Node); |
||||
|
TSTALLOC(HICUMxf1BaseBIPtr,HICUMxf1Node ,HICUMbaseBINode); |
||||
|
TSTALLOC(HICUMxf1EmitEIPtr,HICUMxf1Node ,HICUMemitEINode); |
||||
|
TSTALLOC(HICUMxf1CollCIPtr,HICUMxf1Node ,HICUMcollCINode); |
||||
|
TSTALLOC(HICUMxf1Xf2Ptr ,HICUMxf1Node ,HICUMxf2Node); |
||||
|
|
||||
|
TSTALLOC(HICUMxf2Xf1Ptr ,HICUMxf2Node ,HICUMxf1Node); |
||||
|
TSTALLOC(HICUMxf2BaseBIPtr,HICUMxf2Node ,HICUMbaseBINode); |
||||
|
TSTALLOC(HICUMxf2EmitEIPtr,HICUMxf2Node ,HICUMemitEINode); |
||||
|
TSTALLOC(HICUMxf2CollCIPtr,HICUMxf2Node ,HICUMcollCINode); |
||||
|
TSTALLOC(HICUMxf2Xf2Ptr ,HICUMxf2Node ,HICUMxf2Node); |
||||
|
TSTALLOC(HICUMemitEIXf2Ptr,HICUMemitEINode,HICUMxf2Node); |
||||
|
TSTALLOC(HICUMcollCIXf2Ptr,HICUMcollCINode,HICUMxf2Node); |
||||
|
|
||||
|
TSTALLOC(HICUMxfXfPtr ,HICUMxfNode,HICUMxfNode); |
||||
|
TSTALLOC(HICUMxfEmitEIPtr ,HICUMxfNode,HICUMemitEINode); |
||||
|
TSTALLOC(HICUMxfCollCIPtr ,HICUMxfNode,HICUMcollCINode); |
||||
|
TSTALLOC(HICUMxfBaseBIPtr ,HICUMxfNode,HICUMbaseBINode); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
TSTALLOC(HICUMbaseBPSubsSIPtr ,HICUMbaseBPNode,HICUMsubsSINode); |
||||
|
TSTALLOC(HICUMsubsSIBaseBPPtr ,HICUMsubsSINode,HICUMbaseBPNode); |
||||
|
|
||||
|
if (selfheat) { |
||||
|
TSTALLOC(HICUMcollTempPtr, HICUMcollNode, HICUMtempNode); |
||||
|
TSTALLOC(HICUMbaseTempPtr,HICUMbaseNode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMemitTempPtr,HICUMemitNode,HICUMtempNode); |
||||
|
|
||||
|
TSTALLOC(HICUMcollCItempPtr,HICUMcollCINode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMbaseBItempPtr,HICUMbaseBINode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMbaseBPtempPtr,HICUMbaseBPNode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMemitEItempPtr,HICUMemitEINode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMsubsSItempPtr,HICUMsubsSINode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMsubsTempPtr ,HICUMsubsNode ,HICUMtempNode); |
||||
|
TSTALLOC(HICUMcollTempPtr ,HICUMcollNode ,HICUMtempNode); |
||||
|
|
||||
|
TSTALLOC(HICUMtempCollPtr,HICUMtempNode,HICUMcollNode); |
||||
|
TSTALLOC(HICUMtempBasePtr,HICUMtempNode,HICUMbaseNode); |
||||
|
TSTALLOC(HICUMtempEmitPtr,HICUMtempNode,HICUMemitNode); |
||||
|
|
||||
|
TSTALLOC(HICUMtempCollCIPtr,HICUMtempNode,HICUMcollCINode); |
||||
|
TSTALLOC(HICUMtempBaseBIPtr,HICUMtempNode,HICUMbaseBINode); |
||||
|
TSTALLOC(HICUMtempBaseBPPtr,HICUMtempNode,HICUMbaseBPNode); |
||||
|
TSTALLOC(HICUMtempEmitEIPtr,HICUMtempNode,HICUMemitEINode); |
||||
|
TSTALLOC(HICUMtempSubsSIPtr,HICUMtempNode,HICUMsubsSINode); |
||||
|
|
||||
|
TSTALLOC(HICUMtempTempPtr,HICUMtempNode,HICUMtempNode); |
||||
|
|
||||
|
if (nqs) { |
||||
|
TSTALLOC(HICUMxfTempPtr ,HICUMxfNode,HICUMtempNode); |
||||
|
TSTALLOC(HICUMxf2TempPtr ,HICUMxf2Node ,HICUMtempNode); |
||||
|
TSTALLOC(HICUMxf1TempPtr ,HICUMxf1Node ,HICUMtempNode); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
HICUMunsetup( |
||||
|
GENmodel *inModel, |
||||
|
CKTcircuit *ckt) |
||||
|
{ |
||||
|
HICUMmodel *model; |
||||
|
HICUMinstance *here; |
||||
|
|
||||
|
for (model = (HICUMmodel *)inModel; model != NULL; |
||||
|
model = HICUMnextModel(model)) |
||||
|
{ |
||||
|
int selfheat = (((model->HICUMflsh == 1) || (model->HICUMflsh == 2)) && (model->HICUMrthGiven) && (model->HICUMrth > 0.0)); |
||||
|
int nqs = ( (model->HICUMflnqs != 0 || model->HICUMflcomp < 2.3) && (model->HICUMalit > 0 || model->HICUMalqf > 0)); |
||||
|
|
||||
|
for (here = HICUMinstances(model); here != NULL; |
||||
|
here=HICUMnextInstance(here)) |
||||
|
{ |
||||
|
if (here->HICUMcollCINode > 0 |
||||
|
&& here->HICUMcollCINode != here->HICUMcollNode) |
||||
|
CKTdltNNum(ckt, here->HICUMcollCINode); |
||||
|
here->HICUMcollCINode = 0; |
||||
|
|
||||
|
if (here->HICUMbaseBINode > 0 |
||||
|
&& here->HICUMbaseBPNode != here->HICUMbaseBINode) |
||||
|
CKTdltNNum(ckt, here->HICUMbaseBINode); |
||||
|
here->HICUMbaseBINode = 0; |
||||
|
|
||||
|
if (here->HICUMbaseBPNode > 0 |
||||
|
&& here->HICUMbaseBPNode != here->HICUMbaseNode) |
||||
|
CKTdltNNum(ckt, here->HICUMbaseBPNode); |
||||
|
here->HICUMbaseBPNode = 0; |
||||
|
|
||||
|
if (here->HICUMemitEINode > 0 |
||||
|
&& here->HICUMemitEINode != here->HICUMemitNode) |
||||
|
CKTdltNNum(ckt, here->HICUMemitEINode); |
||||
|
here->HICUMemitEINode = 0; |
||||
|
|
||||
|
if (here->HICUMsubsSINode > 0 |
||||
|
&& here->HICUMsubsSINode != here->HICUMsubsNode) |
||||
|
CKTdltNNum(ckt, here->HICUMsubsSINode); |
||||
|
here->HICUMsubsSINode = 0; |
||||
|
|
||||
|
if (selfheat) { |
||||
|
if (here->HICUMtempNode > 6) { // it is an internal node |
||||
|
CKTdltNNum(ckt, here->HICUMtempNode); |
||||
|
here->HICUMtempNode = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (nqs) { |
||||
|
|
||||
|
if(here->HICUMxfNode > 0) |
||||
|
CKTdltNNum(ckt, here->HICUMxfNode); |
||||
|
here->HICUMxfNode = 0; |
||||
|
|
||||
|
if(here->HICUMxf1Node > 0) |
||||
|
CKTdltNNum(ckt, here->HICUMxf1Node); |
||||
|
here->HICUMxf1Node = 0; |
||||
|
|
||||
|
if(here->HICUMxf2Node > 0) |
||||
|
CKTdltNNum(ckt, here->HICUMxf2Node); |
||||
|
here->HICUMxf2Node = 0; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
return OK; |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/trandefs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
#include "ngspice/cpdefs.h" |
||||
|
|
||||
|
|
||||
|
int |
||||
|
HICUMsoaCheck(CKTcircuit *ckt, GENmodel *inModel) |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel *) inModel; |
||||
|
HICUMinstance *here; |
||||
|
double vbe, vbc, vce; /* actual bjt voltages */ |
||||
|
int maxwarns; |
||||
|
static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0; |
||||
|
|
||||
|
if (!ckt) { |
||||
|
warns_vbe = 0; |
||||
|
warns_vbc = 0; |
||||
|
warns_vce = 0; |
||||
|
return OK; |
||||
|
} |
||||
|
|
||||
|
maxwarns = ckt->CKTsoaMaxWarns; |
||||
|
|
||||
|
for (; model; model = HICUMnextModel(model)) { |
||||
|
|
||||
|
for (here = HICUMinstances(model); here; here=HICUMnextInstance(here)) { |
||||
|
|
||||
|
vbe = fabs(ckt->CKTrhsOld [here->HICUMbaseNode] - |
||||
|
ckt->CKTrhsOld [here->HICUMemitNode]); |
||||
|
vbc = fabs(ckt->CKTrhsOld [here->HICUMbaseNode] - |
||||
|
ckt->CKTrhsOld [here->HICUMcollNode]); |
||||
|
vce = fabs(ckt->CKTrhsOld [here->HICUMcollNode] - |
||||
|
ckt->CKTrhsOld [here->HICUMemitNode]); |
||||
|
|
||||
|
if (vbe > model->HICUMvbeMax) |
||||
|
if (warns_vbe < maxwarns) { |
||||
|
soa_printf(ckt, (GENinstance*) here, |
||||
|
"|Vbe|=%g has exceeded Vbe_max=%g\n", |
||||
|
vbe, model->HICUMvbeMax); |
||||
|
warns_vbe++; |
||||
|
} |
||||
|
|
||||
|
if (vbc > model->HICUMvbcMax) |
||||
|
if (warns_vbc < maxwarns) { |
||||
|
soa_printf(ckt, (GENinstance*) here, |
||||
|
"|Vbc|=%g has exceeded Vbc_max=%g\n", |
||||
|
vbc, model->HICUMvbcMax); |
||||
|
warns_vbc++; |
||||
|
} |
||||
|
|
||||
|
if (vce > model->HICUMvceMax) |
||||
|
if (warns_vce < maxwarns) { |
||||
|
soa_printf(ckt, (GENinstance*) here, |
||||
|
"|Vce|=%g has exceeded Vce_max=%g\n", |
||||
|
vce, model->HICUMvceMax); |
||||
|
warns_vce++; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return OK; |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
/********** |
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
/* |
||||
|
* This routine performs truncation error calculations for |
||||
|
* HICUMs in the circuit. |
||||
|
*/ |
||||
|
|
||||
|
#include "ngspice/ngspice.h" |
||||
|
#include "ngspice/cktdefs.h" |
||||
|
#include "hicum2defs.h" |
||||
|
#include "ngspice/sperror.h" |
||||
|
#include "ngspice/suffix.h" |
||||
|
|
||||
|
|
||||
|
int |
||||
|
HICUMtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel*)inModel; |
||||
|
HICUMinstance *here; |
||||
|
|
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
for(here=HICUMinstances(model);here!=NULL; |
||||
|
here = HICUMnextInstance(here)){ |
||||
|
|
||||
|
CKTterr(here->HICUMqrbi, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjei, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqf, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjci, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqr, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjep, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjcx0_i, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjcx0_ii, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqdsu, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqjs, ckt, timeStep); |
||||
|
CKTterr(here->HICUMqscp, ckt, timeStep); |
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
3350
src/spicelib/devices/hicum2/hicumL2.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,23 @@ |
|||||
|
/**********
|
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
#ifndef hicumL2_H
|
||||
|
#define hicumL2_H
|
||||
|
#include "hicum2defs.h"
|
||||
|
|
||||
|
#ifdef __cplusplus
|
||||
|
extern "C" { |
||||
|
#endif
|
||||
|
void hicum_diode(double T, double IS, double UM1, double U, double *Iz, double *Gz, double *Tz); |
||||
|
void hicum_qjmodf(double T, double c_0, double u_d, double z, double a_j, double U_cap, double *C, double *C_dU, double *C_dvt, double *Qz, double *Qz_dU, double *Qz_dvt); |
||||
|
static double HICUMlimitlog( double deltemp, double deltemp_old, double LIM_TOL, int *check); |
||||
|
int hicum_thermal_update(HICUMmodel *, HICUMinstance *, double * Temp, double * Tdev_Vrth); |
||||
|
int HICUMload(GENmodel *inModel, CKTcircuit *ckt); |
||||
|
int HICUMtemp(GENmodel *inModel, CKTcircuit *ckt); |
||||
|
#ifdef __cplusplus
|
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
#endif /* hicumL2_H */
|
||||
@ -0,0 +1,521 @@ |
|||||
|
/**********
|
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
|
||||
|
#include "cmath"
|
||||
|
#ifndef M_PI
|
||||
|
#define M_PI 3.1415926535897932384626433832795
|
||||
|
#endif
|
||||
|
#include <duals/dual>
|
||||
|
#include "hicumL2.hpp"
|
||||
|
#include <functional>
|
||||
|
|
||||
|
//ngspice header files written in C
|
||||
|
#ifdef __cplusplus
|
||||
|
extern "C" |
||||
|
{ |
||||
|
#endif
|
||||
|
#include "ngspice/ngspice.h"
|
||||
|
#include "ngspice/cktdefs.h"
|
||||
|
#include "ngspice/smpdefs.h"
|
||||
|
#include "hicum2defs.h"
|
||||
|
#include "ngspice/const.h"
|
||||
|
#include "ngspice/sperror.h"
|
||||
|
#include "ngspice/ifsim.h"
|
||||
|
#include "ngspice/suffix.h"
|
||||
|
#ifdef __cplusplus
|
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
using namespace duals::literals; |
||||
|
|
||||
|
#define TMAX 326.85
|
||||
|
#define TMIN -100.0
|
||||
|
#define LN_EXP_LIMIT 11.0
|
||||
|
|
||||
|
duals::duald clip_temperature(duals::duald T){ |
||||
|
// smooth clipping function for device temperature, if self heating increases temperature beyond
|
||||
|
// T0+TMAX or below T0-TMIN
|
||||
|
duals::duald Tdev; |
||||
|
Tdev = T; |
||||
|
if (T<(TMIN+CONSTCtoK+1.0)){ |
||||
|
Tdev = TMIN+CONSTCtoK+exp(T-TMIN+CONSTCtoK-1.0); |
||||
|
} else if (T>(TMAX+CONSTCtoK-1.0)) { |
||||
|
Tdev = TMAX+CONSTCtoK-exp(TMAX+CONSTCtoK-T-1.0); |
||||
|
}; |
||||
|
return Tdev; |
||||
|
}; |
||||
|
|
||||
|
void TMPHICJ(double , double , double , double , double , |
||||
|
double , double , double , double , double , double , |
||||
|
double *, double *, double *); |
||||
|
|
||||
|
// TEMPERATURE UPDATE OF JUNCTION CAPACITANCE RELATED PARAMETERS
|
||||
|
// INPUT:
|
||||
|
// mostly model parameters
|
||||
|
// x : zero bias junction capacitance
|
||||
|
// y : junction built-in potential
|
||||
|
// z : grading co-efficient
|
||||
|
// w : ratio of maximum to zero-bias value of capacitance or punch-through voltage
|
||||
|
// is_al : condition factor to check what "w" stands for
|
||||
|
// vgeff : band-gap voltage
|
||||
|
// IMPLICIT INPUT:
|
||||
|
// vt : thermal voltage
|
||||
|
// vt0,qtt0,ln_qtt0,mg : other model variables
|
||||
|
// OUTPUT:
|
||||
|
// c_j_t : temperature update of "c_j"
|
||||
|
// vd_t : temperature update of "vd0"
|
||||
|
// w_t : temperature update of "w"
|
||||
|
void TMPHICJ(duals::duald vt, double vt0, duals::duald qtt0, duals::duald ln_qtt0, double mg, |
||||
|
double c_j, double vd0, double z, double w, double is_al, double vgeff, |
||||
|
duals::duald *c_j_t, duals::duald *vd_t, duals::duald *w_t) |
||||
|
{ |
||||
|
duals::duald vdj0,vdjt,vdt; |
||||
|
|
||||
|
if (c_j > 0.0) { |
||||
|
vdj0 = 2*vt0*log(exp(vd0*0.5/vt0)-exp(-0.5*vd0/vt0)); |
||||
|
vdjt = vdj0*qtt0+vgeff*(1-qtt0)-mg*vt*ln_qtt0; |
||||
|
vdt = vdjt+2*vt*log(0.5*(1+sqrt(1+4*exp(-vdjt/vt)))); |
||||
|
*vd_t = vdt; |
||||
|
*c_j_t = c_j*exp(z*log(vd0/(*vd_t))); |
||||
|
if (is_al == 1) { |
||||
|
*w_t = w*(*vd_t)/vd0; |
||||
|
} else { |
||||
|
*w_t = w; |
||||
|
} |
||||
|
} else { |
||||
|
*c_j_t = c_j; |
||||
|
*vd_t = vd0; |
||||
|
*w_t = w; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void hicum_TMPHICJ(duals::duald vt, double vt0, duals::duald qtt0, duals::duald ln_qtt0, double mg, |
||||
|
double c_j, double vd0, double z, double w, double is_al, double vgeff, |
||||
|
double *c_j_t, double *vd_t, double *w_t, |
||||
|
double *c_j_t_dT, double *vd_t_dT, double *w_t_dT) |
||||
|
{ |
||||
|
duals::duald c_j_t_result = 0; |
||||
|
duals::duald vd_t_result = 0; |
||||
|
duals::duald w_t_result = 0; |
||||
|
TMPHICJ(vt, vt0, qtt0, ln_qtt0, mg, c_j, vd0, z, w, is_al, vgeff, &c_j_t_result, &vd_t_result, &w_t_result); |
||||
|
*c_j_t = c_j_t_result.rpart(); |
||||
|
*c_j_t_dT = c_j_t_result.dpart(); |
||||
|
*vd_t = vd_t_result.rpart(); |
||||
|
*vd_t_dT = vd_t_result.dpart(); |
||||
|
*w_t = w_t_result.rpart(); |
||||
|
*w_t_dT = w_t_result.dpart(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int |
||||
|
HICUMtemp(GENmodel *inModel, CKTcircuit *ckt) |
||||
|
/* Pre-compute many useful parameters
|
||||
|
*/ |
||||
|
{ |
||||
|
int iret; |
||||
|
HICUMmodel *model = (HICUMmodel *)inModel; |
||||
|
HICUMinstance *here; |
||||
|
|
||||
|
/* loop through all the bipolar models */ |
||||
|
for( ; model != NULL; model = HICUMnextModel(model)) { |
||||
|
|
||||
|
/* loop through all the instances of the model */ |
||||
|
for (here = HICUMinstances(model); here != NULL ; |
||||
|
here=HICUMnextInstance(here)) { |
||||
|
|
||||
|
if(!here->HICUMtempGiven) here->HICUMtemp = ckt->CKTtemp; |
||||
|
|
||||
|
if(here->HICUMdtempGiven) here->HICUMtemp = here->HICUMtemp + here->HICUMdtemp; |
||||
|
|
||||
|
iret = hicum_thermal_update(model, here, &here -> HICUMtemp, &here->HICUMtemp_Vrth); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
return(OK); |
||||
|
} |
||||
|
|
||||
|
int hicum_thermal_update(HICUMmodel *inModel, HICUMinstance *inInstance, double * HICUMTemp, double * Tdev_Vrth) |
||||
|
{ |
||||
|
HICUMmodel *model = (HICUMmodel *)inModel; |
||||
|
HICUMinstance *here = (HICUMinstance *)inInstance; |
||||
|
|
||||
|
double mg,k10,k20,avs,vgb_t0,vge_t0,vgbe_t0,vgbe0,vgbc0,vgsc0; |
||||
|
double zetabci,zetabcxt,zetasct; |
||||
|
duals::duald temp, dT, vt, qtt0, ln_qtt0; |
||||
|
duals::duald k1,k2,dvg0,vge_t,vgb_t,vgbe_t,cratio_t,a; |
||||
|
double cratio_t_real, cratio_t_dual; |
||||
|
double Tnom, zetatef, cjcx01, cjcx02, C_1; |
||||
|
duals::duald cjei0_t, vdei_t, cjep0_t, vdep_t; |
||||
|
|
||||
|
Tnom = model->HICUMtnom; |
||||
|
k10 = model->HICUMf1vg*Tnom*log(Tnom); |
||||
|
k20 = model->HICUMf2vg*Tnom; |
||||
|
avs = model->HICUMalvs*Tnom; |
||||
|
vgb_t0 = model->HICUMvgb+k10+k20; |
||||
|
vge_t0 = model->HICUMvge+k10+k20; |
||||
|
vgbe_t0 = (vgb_t0+vge_t0)/2; |
||||
|
|
||||
|
vgbe0 = (model->HICUMvgb+model->HICUMvge)/2; |
||||
|
vgbc0 = (model->HICUMvgb+model->HICUMvgc)/2; |
||||
|
vgsc0 = (model->HICUMvgs+model->HICUMvgc)/2; |
||||
|
|
||||
|
mg = 3-model->HICUMf1vg/CONSTKoverQ; |
||||
|
zetabci = mg+1-model->HICUMzetaci; |
||||
|
zetabcxt= mg+1-model->HICUMzetacx; |
||||
|
zetasct = mg-1.5; |
||||
|
|
||||
|
|
||||
|
// Smooth ngspice T clipping
|
||||
|
temp = clip_temperature( *(HICUMTemp)+1_e ); |
||||
|
*(HICUMTemp) = temp.rpart(); |
||||
|
*(Tdev_Vrth) = temp.dpart(); |
||||
|
|
||||
|
// original HICUM clipping for Tdev => left here for reference
|
||||
|
// *(Tdev_Vrth) = 1.0;
|
||||
|
// if(*(HICUMTemp) < TMIN + CONSTCtoK) {
|
||||
|
// *(HICUMTemp) = TMIN + CONSTCtoK;
|
||||
|
// *(Tdev_Vrth) = 0.0;
|
||||
|
// } else {
|
||||
|
// if (*(HICUMTemp) > TMAX + CONSTCtoK) {
|
||||
|
// *(HICUMTemp) = TMAX + CONSTCtoK;
|
||||
|
// *(Tdev_Vrth) = 0.0;
|
||||
|
// }
|
||||
|
//}
|
||||
|
|
||||
|
//This routine calculates the derivatives with respect to Vrth. Since at some point
|
||||
|
// Tdev becomes constant (see above), we need to account for this like below.
|
||||
|
//temp = *(HICUMTemp)+1_e* *(Tdev_Vrth); // dual number device temperature
|
||||
|
|
||||
|
vt = temp*CONSTKoverQ; // dual valued temperature voltage
|
||||
|
|
||||
|
here->HICUMvt0 = Tnom * CONSTKoverQ; |
||||
|
here->HICUMvt.rpart = vt.rpart(); |
||||
|
here->HICUMvt.dpart = vt.dpart(); |
||||
|
dT = temp-Tnom; |
||||
|
qtt0 = temp/Tnom; |
||||
|
ln_qtt0 = log(qtt0); |
||||
|
|
||||
|
k1 = model->HICUMf1vg*temp*log(temp); |
||||
|
k2 = model->HICUMf2vg*temp; |
||||
|
vgb_t = model->HICUMvgb+k1+k2; |
||||
|
vge_t = model->HICUMvge+k1+k2; |
||||
|
vgbe_t = (vgb_t+vge_t)/2; |
||||
|
|
||||
|
here->HICUMtVcrit = here->HICUMvt.rpart * |
||||
|
log(here->HICUMvt.rpart / (CONSTroot2*here->HICUMibeis_scaled)); |
||||
|
|
||||
|
//Internal b-e junction capacitance
|
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
here->HICUMcjei0_scaled, model->HICUMvdei, model->HICUMzei, model->HICUMajei, 1, vgbe0, |
||||
|
&here->HICUMcjei0_t.rpart, &here->HICUMvdei_t.rpart, &here->HICUMajei_t.rpart, |
||||
|
&here->HICUMcjei0_t.dpart, &here->HICUMvdei_t.dpart, &here->HICUMajei_t.dpart); |
||||
|
cjei0_t.rpart(here->HICUMcjei0_t.rpart); |
||||
|
cjei0_t.dpart(here->HICUMcjei0_t.dpart); |
||||
|
vdei_t.rpart(here->HICUMvdei_t.rpart); |
||||
|
vdei_t.dpart(here->HICUMvdei_t.dpart); |
||||
|
|
||||
|
if (model->HICUMflcomp < 2.3) { |
||||
|
duals::duald V_gT, r_VgVT, k; |
||||
|
V_gT = 3.0*vt*ln_qtt0 + model->HICUMvgb*(qtt0-1.0); |
||||
|
r_VgVT = V_gT/vt; |
||||
|
//Internal b-e diode saturation currents
|
||||
|
a = model->HICUMmcf*r_VgVT/model->HICUMmbei - model->HICUMalb*dT; |
||||
|
a = here->HICUMibeis_scaled*exp(a); |
||||
|
here->HICUMibeis_t.rpart = a.rpart(); |
||||
|
here->HICUMibeis_t.dpart = a.dpart(); |
||||
|
|
||||
|
a = model->HICUMmcf*r_VgVT/model->HICUMmrei - model->HICUMalb*dT; |
||||
|
a = here->HICUMireis_scaled*exp(a); |
||||
|
here->HICUMireis_t.rpart = a.rpart(); |
||||
|
here->HICUMireis_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Peripheral b-e diode saturation currents
|
||||
|
a = model->HICUMmcf*r_VgVT/model->HICUMmbep - model->HICUMalb*dT; |
||||
|
a = here->HICUMibeps_scaled*exp(a); |
||||
|
here->HICUMibeps_t.rpart = a.rpart(); |
||||
|
here->HICUMibeps_t.dpart = a.dpart(); |
||||
|
|
||||
|
a = model->HICUMmcf*r_VgVT/model->HICUMmrep - model->HICUMalb*dT; |
||||
|
a = here->HICUMireps_scaled*exp(a); |
||||
|
here->HICUMireps_t.rpart = a.rpart(); |
||||
|
here->HICUMireps_t.dpart = a.dpart(); |
||||
|
//Internal b-c diode saturation current
|
||||
|
a = r_VgVT/model->HICUMmbci; |
||||
|
a = here->HICUMibcis_scaled*exp(a); |
||||
|
here->HICUMibcis_t.rpart = a.rpart(); |
||||
|
here->HICUMibcis_t.dpart = a.dpart(); |
||||
|
//External b-c diode saturation currents
|
||||
|
a = r_VgVT/model->HICUMmbcx; |
||||
|
a = here->HICUMibcxs_scaled*exp(a); |
||||
|
here->HICUMibcxs_t.rpart = a.rpart(); |
||||
|
here->HICUMibcxs_t.dpart = a.dpart(); |
||||
|
//Saturation transfer current for substrate transistor
|
||||
|
a = r_VgVT/model->HICUMmsf; |
||||
|
a = model->HICUMitss*exp(a); |
||||
|
here->HICUMitss_t.rpart = a.rpart(); |
||||
|
here->HICUMitss_t.rpart = a.dpart(); |
||||
|
//Saturation current for c-s diode
|
||||
|
a = r_VgVT/model->HICUMmsc; |
||||
|
a = model->HICUMiscs*exp(a); |
||||
|
here->HICUMiscs_t.rpart = a.rpart(); |
||||
|
here->HICUMiscs_t.dpart = a.dpart(); |
||||
|
//Zero bias hole charge
|
||||
|
a = vdei_t/model->HICUMvdei; |
||||
|
a = here->HICUMqp0_scaled*(1.0+0.5*model->HICUMzei*(1.0-a)); |
||||
|
here->HICUMqp0_t.rpart = a.rpart(); |
||||
|
here->HICUMqp0_t.dpart = a.dpart(); |
||||
|
//Voltage separating ohmic and saturation velocity regime
|
||||
|
a = model->HICUMvlim*(1.0-model->HICUMalvs*dT)*exp(model->HICUMzetaci*ln_qtt0); |
||||
|
k = (a-vt)/vt; |
||||
|
if (k.rpart() < LN_EXP_LIMIT) { |
||||
|
a = vt + vt*log(1.0+exp(k)); |
||||
|
} |
||||
|
here->HICUMvlim_t.rpart = a.rpart(); |
||||
|
here->HICUMvlim_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Neutral emitter storage time
|
||||
|
a = 1.0+model->HICUMalb*dT; |
||||
|
k = 0.5*(a+sqrt(a*a+0.01)); |
||||
|
a = model->HICUMtef0*qtt0/k; |
||||
|
here->HICUMtef0_t.rpart = a.rpart(); |
||||
|
here->HICUMtef0_t.dpart = a.dpart(); |
||||
|
} else { |
||||
|
//Internal b-e diode saturation currents
|
||||
|
a = here->HICUMibeis_scaled*exp(model->HICUMzetabet*ln_qtt0+model->HICUMvge/vt*(qtt0-1)); |
||||
|
here->HICUMibeis_t.rpart = a.rpart(); |
||||
|
here->HICUMibeis_t.dpart = a.dpart(); |
||||
|
if (model->HICUMflcomp>=2.3) { |
||||
|
a = here->HICUMireis_scaled*exp(mg/model->HICUMmrei*ln_qtt0+vgbe0/(model->HICUMmrei*vt)*(qtt0-1)); |
||||
|
} else { |
||||
|
a = here->HICUMireis_scaled*exp(0.5*mg*ln_qtt0+0.5*vgbe0/vt*(qtt0-1)); |
||||
|
} |
||||
|
here->HICUMireis_t.rpart = a.rpart(); |
||||
|
here->HICUMireis_t.dpart = a.dpart(); |
||||
|
//Peripheral b-e diode saturation currents
|
||||
|
a = here->HICUMibeps_scaled*exp(model->HICUMzetabet*ln_qtt0+model->HICUMvge/vt*(qtt0-1)); |
||||
|
here->HICUMibeps_t.rpart = a.rpart(); |
||||
|
here->HICUMibeps_t.dpart = a.dpart(); |
||||
|
if (model->HICUMflcomp>=2.3) { |
||||
|
a = here->HICUMireps_scaled*exp(mg/model->HICUMmrep*ln_qtt0+vgbe0/(model->HICUMmrep*vt)*(qtt0-1)); |
||||
|
} else { |
||||
|
a = here->HICUMireps_scaled*exp(0.5*mg*qtt0+0.5*vgbe0/vt*(qtt0-1)); |
||||
|
} |
||||
|
here->HICUMireps_t.rpart = a.rpart(); |
||||
|
here->HICUMireps_t.dpart = a.dpart(); |
||||
|
//Internal b-c diode saturation currents
|
||||
|
a = here->HICUMibcis_scaled*exp(zetabci*ln_qtt0+model->HICUMvgc/vt*(qtt0-1)); |
||||
|
here->HICUMibcis_t.rpart = a.rpart(); |
||||
|
here->HICUMibcis_t.dpart = a.dpart(); |
||||
|
//External b-c diode saturation currents
|
||||
|
a = here->HICUMibcxs_scaled*exp(zetabcxt*ln_qtt0+model->HICUMvgc/vt*(qtt0-1)); |
||||
|
here->HICUMibcxs_t.rpart = a.rpart(); |
||||
|
here->HICUMibcxs_t.dpart = a.dpart(); |
||||
|
//Saturation transfer current for substrate transistor
|
||||
|
a = model->HICUMitss*exp(zetasct*ln_qtt0+model->HICUMvgc/vt*(qtt0-1)); |
||||
|
here->HICUMitss_t.rpart = a.rpart(); |
||||
|
here->HICUMitss_t.dpart = a.dpart(); |
||||
|
//Saturation current for c-s diode
|
||||
|
a = model->HICUMiscs*exp(zetasct*ln_qtt0+model->HICUMvgs/vt*(qtt0-1)); |
||||
|
here->HICUMiscs_t.rpart = a.rpart(); |
||||
|
here->HICUMiscs_t.dpart = a.dpart(); |
||||
|
//Zero bias hole charge
|
||||
|
a = exp(model->HICUMzei*log(vdei_t/model->HICUMvdei)); |
||||
|
a = here->HICUMqp0_scaled*(2.0-a); |
||||
|
here->HICUMqp0_t.rpart = a.rpart(); |
||||
|
here->HICUMqp0_t.dpart = a.dpart(); |
||||
|
//Voltage separating ohmic and saturation velocity regime
|
||||
|
a = model->HICUMvlim*exp((model->HICUMzetaci-avs)*ln_qtt0); |
||||
|
here->HICUMvlim_t.rpart = a.rpart(); |
||||
|
here->HICUMvlim_t.dpart = a.dpart(); |
||||
|
//Neutral emitter storage time
|
||||
|
if (model->HICUMflcomp >= 2.3) { |
||||
|
a = model->HICUMtef0; |
||||
|
} else { |
||||
|
zetatef = model->HICUMzetabet-model->HICUMzetact-0.5; |
||||
|
dvg0 = model->HICUMvgb-model->HICUMvge; |
||||
|
a = model->HICUMtef0*exp(zetatef*ln_qtt0-dvg0/vt*(qtt0-1)); |
||||
|
} |
||||
|
here->HICUMtef0_t.rpart = a.rpart(); |
||||
|
here->HICUMtef0_t.dpart = a.dpart(); |
||||
|
} |
||||
|
|
||||
|
//GICCR prefactor
|
||||
|
a = here->HICUMc10_scaled*exp(model->HICUMzetact*ln_qtt0+model->HICUMvgb/vt*(qtt0-1)); |
||||
|
here->HICUMc10_t.rpart = a.rpart(); |
||||
|
here->HICUMc10_t.dpart = a.dpart(); |
||||
|
|
||||
|
// Low-field internal collector resistance
|
||||
|
a = here->HICUMrci0_scaled*exp(model->HICUMzetaci*ln_qtt0); |
||||
|
here->HICUMrci0_t.rpart = a.rpart(); |
||||
|
here->HICUMrci0_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Internal c-e saturation voltage
|
||||
|
a = model->HICUMvces*(1+model->HICUMalces*dT); |
||||
|
here->HICUMvces_t.rpart = a.rpart(); |
||||
|
here->HICUMvces_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Internal b-c junction capacitance
|
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
here->HICUMcjci0_scaled, model->HICUMvdci, model->HICUMzci, model->HICUMvptci, 0, vgbc0, |
||||
|
&here->HICUMcjci0_t.rpart, &here->HICUMvdci_t.rpart, &here->HICUMvptci_t.rpart, |
||||
|
&here->HICUMcjci0_t.dpart, &here->HICUMvdci_t.dpart, &here->HICUMvptci_t.dpart); |
||||
|
|
||||
|
//Low-current forward transit time
|
||||
|
a = model->HICUMt0*(1+model->HICUMalt0*dT+model->HICUMkt0*dT*dT); |
||||
|
here->HICUMt0_t.rpart = a.rpart(); |
||||
|
here->HICUMt0_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Saturation time constant at high current densities
|
||||
|
a = model->HICUMthcs*exp((model->HICUMzetaci-1)*ln_qtt0); |
||||
|
here->HICUMthcs_t.rpart = a.rpart(); |
||||
|
here->HICUMthcs_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Avalanche current factors
|
||||
|
a = model->HICUMfavl*exp(model->HICUMalfav*dT); |
||||
|
here->HICUMfavl_t.rpart = a.rpart(); |
||||
|
here->HICUMfavl_t.dpart = a.dpart(); |
||||
|
a = here->HICUMqavl_scaled*exp(model->HICUMalqav*dT); |
||||
|
here->HICUMqavl_t.rpart = a.rpart(); |
||||
|
here->HICUMqavl_t.dpart = a.dpart(); |
||||
|
a = model->HICUMkavl*exp(model->HICUMalkav*dT); |
||||
|
here->HICUMkavl_t.rpart = a.rpart(); |
||||
|
here->HICUMkavl_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Zero bias internal base resistance
|
||||
|
a = here->HICUMrbi0_scaled*exp(model->HICUMzetarbi*ln_qtt0); |
||||
|
here->HICUMrbi0_t.rpart = a.rpart(); |
||||
|
here->HICUMrbi0_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Peripheral b-e junction capacitance
|
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
here->HICUMcjep0_scaled, model->HICUMvdep, model->HICUMzep, model->HICUMajep, 1, vgbe0, |
||||
|
&here->HICUMcjep0_t.rpart, &here->HICUMvdep_t.rpart, &here->HICUMajep_t.rpart, |
||||
|
&here->HICUMcjep0_t.dpart, &here->HICUMvdep_t.dpart, &here->HICUMajep_t.dpart); |
||||
|
cjep0_t.rpart(here->HICUMcjep0_t.rpart); |
||||
|
cjep0_t.dpart(here->HICUMcjep0_t.dpart); |
||||
|
vdep_t.rpart(here->HICUMvdep_t.rpart); |
||||
|
vdep_t.dpart(here->HICUMvdep_t.dpart); |
||||
|
|
||||
|
//Tunneling current factors
|
||||
|
if (here->HICUMibets_scaled > 0) { // HICTUN_T
|
||||
|
duals::duald a_eg,ab,aa; |
||||
|
ab = 1.0; |
||||
|
aa = 1.0; |
||||
|
a_eg = vgbe_t0/vgbe_t; |
||||
|
if(model->HICUMtunode==1 && here->HICUMcjep0_scaled > 0.0 && model->HICUMvdep >0.0) { |
||||
|
ab = (cjep0_t/here->HICUMcjep0_scaled)*sqrt(a_eg)*vdep_t*vdep_t/(model->HICUMvdep*model->HICUMvdep); |
||||
|
aa = (model->HICUMvdep/vdep_t)*(here->HICUMcjep0_scaled/cjep0_t)*pow(a_eg,-1.5); |
||||
|
} else if (model->HICUMtunode==0 && here->HICUMcjei0_scaled > 0.0 && model->HICUMvdei >0.0) { |
||||
|
ab = (cjei0_t/here->HICUMcjei0_scaled)*sqrt(a_eg)*vdei_t*vdei_t/(model->HICUMvdei*model->HICUMvdei); |
||||
|
aa = (model->HICUMvdei/vdei_t)*(here->HICUMcjei0_scaled/cjei0_t)*pow(a_eg,-1.5); |
||||
|
} |
||||
|
a = here->HICUMibets_scaled*ab; |
||||
|
here->HICUMibets_t.rpart = a.rpart(); |
||||
|
here->HICUMibets_t.dpart = a.dpart(); |
||||
|
a = model->HICUMabet*aa; |
||||
|
here->HICUMabet_t.rpart = a.rpart(); |
||||
|
here->HICUMabet_t.dpart = a.dpart(); |
||||
|
} else { |
||||
|
here->HICUMibets_t.rpart = 0; |
||||
|
here->HICUMibets_t.dpart = 0; |
||||
|
here->HICUMabet_t.rpart = 1; |
||||
|
here->HICUMabet_t.dpart = 0; |
||||
|
} |
||||
|
|
||||
|
//Depletion capacitance splitting at b-c junction
|
||||
|
//Capacitances at peripheral and external base node
|
||||
|
C_1 = (1.0-model->HICUMfbcpar)*(here->HICUMcjcx0_scaled+here->HICUMcbcpar_scaled); |
||||
|
if (C_1 >= here->HICUMcbcpar_scaled) { |
||||
|
cjcx01 = C_1-here->HICUMcbcpar_scaled; |
||||
|
cjcx02 = here->HICUMcjcx0_scaled-cjcx01; |
||||
|
} else { |
||||
|
cjcx01 = 0.0; |
||||
|
cjcx02 = here->HICUMcjcx0_scaled; |
||||
|
} |
||||
|
|
||||
|
//Temperature mapping for tunneling current is done inside HICTUN
|
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
1.0, model->HICUMvdcx, model->HICUMzcx, model->HICUMvptcx, 0, vgbc0, |
||||
|
&cratio_t_real, &here->HICUMvdcx_t.rpart, &here->HICUMvptcx_t.rpart, |
||||
|
&cratio_t_dual, &here->HICUMvdcx_t.dpart, &here->HICUMvptcx_t.dpart); |
||||
|
cratio_t.rpart(cratio_t_real); |
||||
|
cratio_t.dpart(cratio_t_dual); |
||||
|
a = cratio_t*cjcx01; |
||||
|
here->HICUMcjcx01_t.rpart = a.rpart(); |
||||
|
here->HICUMcjcx01_t.dpart = a.dpart(); |
||||
|
a = cratio_t*cjcx02; |
||||
|
here->HICUMcjcx02_t.rpart = a.rpart(); |
||||
|
here->HICUMcjcx02_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Constant external series resistances
|
||||
|
a = here->HICUMrcx_scaled*exp(model->HICUMzetarcx*ln_qtt0); |
||||
|
here->HICUMrcx_t.rpart = a.rpart(); |
||||
|
here->HICUMrcx_t.dpart = a.dpart(); |
||||
|
a = here->HICUMrbx_scaled*exp(model->HICUMzetarbx*ln_qtt0); |
||||
|
here->HICUMrbx_t.rpart = a.rpart(); |
||||
|
here->HICUMrbx_t.dpart = a.dpart(); |
||||
|
a = here->HICUMre_scaled*exp(model->HICUMzetare*ln_qtt0); |
||||
|
here->HICUMre_t.rpart = a.rpart(); |
||||
|
here->HICUMre_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Forward transit time in substrate transistor
|
||||
|
a = model->HICUMtsf*exp((model->HICUMzetacx-1.0)*ln_qtt0); |
||||
|
here->HICUMtsf_t.rpart = a.rpart(); |
||||
|
here->HICUMtsf_t.dpart = a.dpart(); |
||||
|
|
||||
|
//Capacitance for c-s junction
|
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
model->HICUMcjs0, model->HICUMvds, model->HICUMzs, model->HICUMvpts, 0, vgsc0, |
||||
|
&here->HICUMcjs0_t.rpart, &here->HICUMvds_t.rpart, &here->HICUMvpts_t.rpart, |
||||
|
&here->HICUMcjs0_t.dpart, &here->HICUMvds_t.dpart, &here->HICUMvpts_t.dpart); |
||||
|
/*Peripheral s-c capacitance
|
||||
|
* Note, thermal update only required for model->HICUMvds > 0 |
||||
|
* Save computional effort otherwise |
||||
|
*/ |
||||
|
if (model->HICUMvdsp > 0) { |
||||
|
hicum_TMPHICJ(vt, here->HICUMvt0, qtt0, ln_qtt0, mg, |
||||
|
model->HICUMcscp0, model->HICUMvdsp, model->HICUMzsp, model->HICUMvptsp, 0, vgsc0, |
||||
|
&here->HICUMcscp0_t.rpart, &here->HICUMvdsp_t.rpart, &here->HICUMvptsp_t.rpart, |
||||
|
&here->HICUMcscp0_t.dpart, &here->HICUMvdsp_t.dpart, &here->HICUMvptsp_t.dpart); |
||||
|
} else { |
||||
|
// Avoid uninitialized variables
|
||||
|
here->HICUMcscp0_t.rpart = model->HICUMcscp0; |
||||
|
here->HICUMcscp0_t.dpart = 0; |
||||
|
here->HICUMvdsp_t.rpart = model->HICUMvdsp; |
||||
|
here->HICUMvdsp_t.dpart = 0; |
||||
|
here->HICUMvptsp_t.rpart = model->HICUMvptsp; |
||||
|
here->HICUMvptsp_t.dpart = 0; |
||||
|
} |
||||
|
|
||||
|
a = model->HICUMahjei*exp(model->HICUMzetahjei*ln_qtt0); |
||||
|
here->HICUMahjei_t.rpart = a.rpart(); |
||||
|
here->HICUMahjei_t.dpart = a.dpart(); |
||||
|
a = model->HICUMhjei*exp(model->HICUMdvgbe/vt*(exp(model->HICUMzetavgbe*log(qtt0))-1)); |
||||
|
here->HICUMhjei0_t.rpart = a.rpart(); |
||||
|
here->HICUMhjei0_t.dpart = a.dpart(); |
||||
|
a = model->HICUMhf0*exp(model->HICUMdvgbe/vt*(qtt0-1)); |
||||
|
here->HICUMhf0_t.rpart = a.rpart(); |
||||
|
here->HICUMhf0_t.dpart = a.dpart(); |
||||
|
if (model->HICUMflcomp >= 2.3) { |
||||
|
a = model->HICUMhfe*exp((model->HICUMvgb-model->HICUMvge)/vt*(qtt0-1)); |
||||
|
here->HICUMhfe_t.rpart = a.rpart(); |
||||
|
here->HICUMhfe_t.dpart = a.dpart(); |
||||
|
a = model->HICUMhfc*exp((model->HICUMvgb-model->HICUMvgc)/vt*(qtt0-1)); |
||||
|
here->HICUMhfc_t.rpart = a.rpart(); |
||||
|
here->HICUMhfc_t.dpart = a.dpart(); |
||||
|
} else { |
||||
|
here->HICUMhfe_t.rpart = model->HICUMhfe; |
||||
|
here->HICUMhfe_t.dpart = 0; |
||||
|
here->HICUMhfc_t.rpart = model->HICUMhfc; |
||||
|
here->HICUMhfc_t.dpart = 0; |
||||
|
} |
||||
|
|
||||
|
a = here->HICUMrth_scaled*exp(model->HICUMzetarth*ln_qtt0)*(1+model->HICUMalrth*dT); |
||||
|
here->HICUMrth_t.rpart = a.rpart(); |
||||
|
here->HICUMrth_t.dpart = a.dpart(); |
||||
|
|
||||
|
return(0); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
/**********
|
||||
|
License : 3-clause BSD |
||||
|
Spice3 Implementation: 2019-2020 Dietmar Warning, Markus Müller, Mario Krattenmacher |
||||
|
Model Author : 1990 Michael Schröter TU Dresden |
||||
|
**********/ |
||||
|
#ifndef hicumL2_temp
|
||||
|
#define hicumL2_temp
|
||||
|
#include "hicum2defs.h"
|
||||
|
|
||||
|
#ifdef __cplusplus
|
||||
|
extern "C" { |
||||
|
#endif
|
||||
|
#ifdef __cplusplus
|
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
#endif /* hicumL2_temp */
|
||||
@ -0,0 +1,686 @@ |
|||||
|
|
||||
|
# |
||||
|
# ads DC, AC and noise test routines |
||||
|
# |
||||
|
|
||||
|
# |
||||
|
# Rel Date Who Comments |
||||
|
# ==== ========== ============= ======== |
||||
|
# 1.3 06/21/07 Colin McAndrew Verilog-A model support added |
||||
|
# 1.2 06/30/06 Colin McAndrew Floating node support added |
||||
|
# Noise simulation added |
||||
|
# 1.0 04/13/06 Rick Poore/ Initial version |
||||
|
# Colin McAndrew |
||||
|
# |
||||
|
|
||||
|
package simulate; |
||||
|
$simulatorCommand="hpeesofsim_local"; |
||||
|
$netlistFile="adsCkt"; |
||||
|
$mFactorVerilogaName="m"; # for LRM2.1 |
||||
|
#$mFactorVerilogaName="_M"; # for LRM2.2 |
||||
|
use strict; |
||||
|
|
||||
|
sub version { |
||||
|
my($version,@Field); |
||||
|
if (!open(SIMULATE,"$simulate::simulatorCommand -version 2>/dev/null|")) { |
||||
|
die("ERROR: cannot run $main::simulatorName, stopped"); |
||||
|
} |
||||
|
$version="unknown"; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
if (/HPEESOFSIM/i) { |
||||
|
@Field=split; |
||||
|
$version=$Field[2]; |
||||
|
} |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
if (! $main::debug) { |
||||
|
unlink($simulate::netlistFile); |
||||
|
} |
||||
|
return($version); |
||||
|
} |
||||
|
|
||||
|
sub runNoiseTest { |
||||
|
my($variant,$outputFile)=@_; |
||||
|
my($i,@Field,$arg,$name,$value,$type,$pin,$noisePin); |
||||
|
my(@BiasList,$realVal,$imagVal); |
||||
|
my($start,$stop,$step,$sign,$inResults,%Index,$iVariables); |
||||
|
my(@X,@Noise,$temperature,$biasVoltage,$sweepVoltage); |
||||
|
my(@realAdsResults,@imagAdsResults); |
||||
|
|
||||
|
# |
||||
|
# Make up the netlist, using a subckt to encapsulate the |
||||
|
# instance. This simplifies handling of the variants as |
||||
|
# the actual instance is driven by voltage-controlled |
||||
|
# voltage sources from the subckt pins, and the currents |
||||
|
# are fed back to the subckt pins using current-controlled |
||||
|
# current sources. Pin swapping, polarity reversal, and |
||||
|
# m-factor scaling can all be handled by simple modifications |
||||
|
# of this subckt. |
||||
|
# |
||||
|
|
||||
|
@X=();@Noise=(); |
||||
|
$noisePin=$main::Outputs[0]; |
||||
|
($start,$stop,$step)=split(/\s+/,$main::biasSweepSpec); |
||||
|
foreach $temperature (@main::Temperature) { |
||||
|
foreach $biasVoltage (split(/\s+/,$main::biasListSpec)) { |
||||
|
if ($main::fMin == $main::fMax) { |
||||
|
push(@X,@main::BiasSweepList); |
||||
|
} |
||||
|
if (!open(OF,">$simulate::netlistFile")) { |
||||
|
die("ERROR: cannot open file $simulate::netlistFile, stopped"); |
||||
|
} |
||||
|
print OF "; Noise simulation for $main::simulatorName"; |
||||
|
print OF "Options UseNutmegFormat=yes ASCII_Rawfile=yes"; |
||||
|
print OF "Options Temp=$temperature"; |
||||
|
print OF "Vsweep = 0 V"; |
||||
|
&generateCommonNetlistInfo($variant); |
||||
|
foreach $pin (@main::Pin) { |
||||
|
if ($main::isFloatingPin{$pin}) { |
||||
|
print OF "I_Source:i_$pin $pin 0 Idc=0"; |
||||
|
} elsif ($pin eq $main::biasListPin) { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=$biasVoltage"; |
||||
|
} elsif ($pin eq $main::biasSweepPin) { |
||||
|
if ($stop < $start) { # flip polarity as ADS always does lo->hi sweep |
||||
|
print OF "V_Source:v_$pin 0 $pin Vdc=Vsweep"; |
||||
|
} else { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=Vsweep"; |
||||
|
} |
||||
|
} else { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=$main::BiasFor{$pin}"; |
||||
|
} |
||||
|
} |
||||
|
print OF "mysub:x_$noisePin ".join(" ",@main::Pin); |
||||
|
print OF "SDD:fn_$noisePin 0 n_$noisePin I[1,0]=_c1 C[1]=\"v_$noisePin\""; |
||||
|
print OF "R:r_$noisePin n_$noisePin 0 R=1 Noise=no"; |
||||
|
print OF "OutputPlan:noiseOutput Type=\"Output\""; |
||||
|
if ($main::fType eq "lin") { |
||||
|
print OF "SweepPlan:noisePlan Start=$main::fMin Stop=$main::fMax Lin=$main::fSteps"; |
||||
|
} elsif ($main::fType eq "dec") { |
||||
|
print OF "SweepPlan:noisePlan Start=$main::fMin Stop=$main::fMax Dec=$main::fSteps"; |
||||
|
} else { # octal sweep |
||||
|
print OF "SweepPlan:noisePlan Start=$main::fMin Stop=$main::fMax Dec=".(int($main::fSteps*log(10)/log(2))); |
||||
|
} |
||||
|
if ($stop < $start) { |
||||
|
$sign=-1; |
||||
|
print OF "SweepPlan:dcPlan Start=".(-1)*$start." Stop=".(-1)*$stop." Step=".(-1)*$step; |
||||
|
} else { |
||||
|
$sign=1; |
||||
|
print OF "SweepPlan:dcPlan Start=$start Stop=$stop Step=$step"; |
||||
|
} |
||||
|
print OF "AC:AC1 CalcNoise=yes OutputPlan=\"noiseOutput\" SweepVar=\"freq\" \\"; |
||||
|
print OF "SweepPlan=\"noisePlan\" NoiseNode=\"n_$noisePin\""; |
||||
|
print OF "ParamSweep:Vsweep SimInstanceName=\"AC1\" SweepVar=\"Vsweep\" SweepPlan=\"dcPlan\""; |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Run simulations and get the results |
||||
|
# |
||||
|
|
||||
|
if (!open(SIMULATE,"$simulate::simulatorCommand $simulate::netlistFile 2>/dev/null |")) { |
||||
|
die("ERROR: cannot run $main::simulatorName, stopped"); |
||||
|
} |
||||
|
$inResults=0; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp; |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
if (!open(SIMULATE,"spectra.raw")) { |
||||
|
die("ERROR: cannot open ADS spectra.raw file, stopped"); |
||||
|
} |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
next if (/^$/); |
||||
|
if (/Plotname:\s*AC/) { |
||||
|
$inResults=0;next; |
||||
|
} |
||||
|
if (/Plotname:\s*CT/) { |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
last if (/^$/); |
||||
|
} |
||||
|
next; |
||||
|
} |
||||
|
if (s/^Variables:\s*//) { |
||||
|
$iVariables=0; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
if (/^Values:/) { |
||||
|
$inResults=1;last; |
||||
|
} |
||||
|
++$iVariables; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
} |
||||
|
@realAdsResults=();@imagAdsResults=(); |
||||
|
next; |
||||
|
} |
||||
|
next if (!$inResults); |
||||
|
s/,/ /; |
||||
|
@Field=split; |
||||
|
shift(@Field) if ($#Field == 2); |
||||
|
push(@realAdsResults,$Field[0]); |
||||
|
push(@imagAdsResults,$Field[1]); |
||||
|
if ($#realAdsResults == $iVariables) { |
||||
|
if ($main::fMin != $main::fMax) { |
||||
|
push(@X,1*$realAdsResults[$Index{"freq"}]); |
||||
|
} |
||||
|
push(@Noise,$realAdsResults[$Index{"n_$noisePin.noise"}]**2); |
||||
|
@realAdsResults=();@imagAdsResults=(); |
||||
|
} |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# |
||||
|
# Write the results to a file |
||||
|
# |
||||
|
|
||||
|
if (!open(OF,">$outputFile")) { |
||||
|
die("ERROR: cannot open file $outputFile, stopped"); |
||||
|
} |
||||
|
if ($main::fMin == $main::fMax) { |
||||
|
printf OF ("V($main::biasSweepPin)"); |
||||
|
} else { |
||||
|
printf OF ("Freq"); |
||||
|
} |
||||
|
foreach (@main::Outputs) { |
||||
|
printf OF (" N($_)"); |
||||
|
} |
||||
|
printf OF ("\n"); |
||||
|
for ($i=0;$i<=$#X;++$i) { |
||||
|
if (defined($Noise[$i])) {printf OF ("$X[$i] $Noise[$i]\n")} |
||||
|
} |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Clean up, unless the debug flag was specified |
||||
|
# |
||||
|
|
||||
|
if (! $main::debug) { |
||||
|
unlink($simulate::netlistFile); |
||||
|
unlink("$simulate::netlistFile.ds"); |
||||
|
unlink(".spiceinit"); |
||||
|
unlink("spectra.raw"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
sub runAcTest { |
||||
|
my($variant,$outputFile)=@_; |
||||
|
my($i,@Field,$arg,$name,$value,$type,$pin,$mPin,$fPin,%NextPin); |
||||
|
my(@BiasList,$acStim,$realVal,$imagVal); |
||||
|
my($start,$stop,$step,$sign,$inResults,%Index,$iVariables); |
||||
|
my(@X,$omega,%g,%c,$temperature,$biasVoltage,$sweepVoltage,$twoPi); |
||||
|
my(@realAdsResults,@imagAdsResults,$outputLine); |
||||
|
$twoPi=8.0*atan2(1.0,1.0); |
||||
|
|
||||
|
# |
||||
|
# Make up the netlist, using a subckt to encapsulate the |
||||
|
# instance. This simplifies handling of the variants as |
||||
|
# the actual instance is driven by voltage-controlled |
||||
|
# voltage sources from the subckt pins, and the currents |
||||
|
# are fed back to the subckt pins using current-controlled |
||||
|
# current sources. Pin swapping, polarity reversal, and |
||||
|
# m-factor scaling can all be handled by simple modifications |
||||
|
# of this subckt. |
||||
|
# |
||||
|
|
||||
|
foreach $mPin (@main::Pin) { |
||||
|
foreach $fPin (@main::Pin) { |
||||
|
@{$g{$mPin,$fPin}}=(); |
||||
|
@{$c{$mPin,$fPin}}=(); |
||||
|
} |
||||
|
} |
||||
|
@X=(); |
||||
|
($start,$stop,$step)=split(/\s+/,$main::biasSweepSpec); |
||||
|
foreach $temperature (@main::Temperature) { |
||||
|
foreach $biasVoltage (split(/\s+/,$main::biasListSpec)) { |
||||
|
if ($main::fMin == $main::fMax) { |
||||
|
push(@X,@main::BiasSweepList); |
||||
|
} |
||||
|
if (!open(OF,">$simulate::netlistFile")) { |
||||
|
die("ERROR: cannot open file $simulate::netlistFile, stopped"); |
||||
|
} |
||||
|
print OF "; AC simulation for $main::simulatorName"; |
||||
|
print OF "Options UseNutmegFormat=yes ASCII_Rawfile=yes"; |
||||
|
print OF "Options Temp=$temperature"; |
||||
|
print OF "Vsweep = 0 V"; |
||||
|
&generateCommonNetlistInfo($variant); |
||||
|
foreach $fPin (@main::Pin) { |
||||
|
foreach $mPin (@main::Pin) { |
||||
|
if ($mPin eq $fPin) { |
||||
|
$acStim=" Vac=1"; |
||||
|
} else { |
||||
|
$acStim=""; |
||||
|
} |
||||
|
if ($main::isFloatingPin{$mPin}) { |
||||
|
print OF "I_Source:i_${mPin}_$fPin ${mPin}_$fPin 0 Idc=0"; |
||||
|
} elsif ($mPin eq $main::biasListPin) { |
||||
|
print OF "V_Source:v_${mPin}_$fPin ${mPin}_$fPin 0 Vdc=$biasVoltage$acStim"; |
||||
|
} elsif ($mPin eq $main::biasSweepPin) { |
||||
|
if ($stop < $start) { # flip polarity as ADS always does lo->hi sweep |
||||
|
$acStim=~s/1/-1/; |
||||
|
print OF "V_Source:v_${mPin}_$fPin 0 ${mPin}_$fPin Vdc=Vsweep$acStim"; |
||||
|
} else { |
||||
|
print OF "V_Source:v_${mPin}_$fPin ${mPin}_$fPin 0 Vdc=Vsweep$acStim"; |
||||
|
} |
||||
|
} else { |
||||
|
print OF "V_Source:v_${mPin}_$fPin ${mPin}_$fPin 0 Vdc=$main::BiasFor{$mPin}$acStim"; |
||||
|
} |
||||
|
} |
||||
|
print OF "mysub:x_$fPin ".join("_$fPin ",@main::Pin)."_$fPin "; |
||||
|
} |
||||
|
if ($main::fType eq "lin") { |
||||
|
print OF "SweepPlan:acPlan Start=$main::fMin Stop=$main::fMax Lin=$main::fSteps"; |
||||
|
} elsif ($main::fType eq "dec") { |
||||
|
print OF "SweepPlan:acPlan Start=$main::fMin Stop=$main::fMax Dec=$main::fSteps"; |
||||
|
} else { # octal sweep |
||||
|
print OF "SweepPlan:acPlan Start=$main::fMin Stop=$main::fMax Dec=".(int($main::fSteps*log(10)/log(2))); |
||||
|
} |
||||
|
if ($stop < $start) { |
||||
|
$sign=-1; |
||||
|
print OF "SweepPlan:dcPlan Start=".(-1)*$start." Stop=".(-1)*$stop." Step=".(-1)*$step; |
||||
|
} else { |
||||
|
$sign=1; |
||||
|
print OF "SweepPlan:dcPlan Start=$start Stop=$stop Step=$step"; |
||||
|
} |
||||
|
print OF "OutputPlan:acOutput Type=\"Output\" UseNodeNestLevel=yes NodeNestLevel=2 UseEquationNestLevel=yes EquationNestLevel=2"; |
||||
|
print OF "AC:AC1 OutputPlan=\"acOutput\" SweepVar=\"freq\" SweepPlan=\"acPlan\""; |
||||
|
print OF "ParamSweep:Vsweep SimInstanceName=\"AC1\" SweepVar=\"Vsweep\" SweepPlan=\"dcPlan\""; |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Run simulations and get the results |
||||
|
# |
||||
|
|
||||
|
if (!open(SIMULATE,"$simulate::simulatorCommand $simulate::netlistFile 2>/dev/null |")) { |
||||
|
die("ERROR: cannot run $main::simulatorName, stopped"); |
||||
|
} |
||||
|
$inResults=0; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp; |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
if (!open(SIMULATE,"spectra.raw")) { |
||||
|
die("ERROR: cannot open ADS spectra.raw file, stopped"); |
||||
|
} |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
next if (/^$/); |
||||
|
if (/Plotname:\s*AC/) { |
||||
|
$inResults=0;next; |
||||
|
} |
||||
|
if (/Plotname:\s*CT/) { |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
last if (/^$/); |
||||
|
} |
||||
|
next; |
||||
|
} |
||||
|
if (s/^Variables:\s*//) { |
||||
|
$iVariables=0; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
if (/^Values:/) { |
||||
|
$inResults=1;last; |
||||
|
} |
||||
|
++$iVariables; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
} |
||||
|
@realAdsResults=();@imagAdsResults=(); |
||||
|
next; |
||||
|
} |
||||
|
next if (!$inResults); |
||||
|
s/,/ /; |
||||
|
@Field=split; |
||||
|
shift(@Field) if ($#Field == 2); |
||||
|
push(@realAdsResults,$Field[0]); |
||||
|
push(@imagAdsResults,$Field[1]); |
||||
|
if ($#realAdsResults == $iVariables) { |
||||
|
if ($main::fMin != $main::fMax) { |
||||
|
push(@X,1*$realAdsResults[$Index{"freq"}]); |
||||
|
} |
||||
|
$omega=$twoPi*$realAdsResults[$Index{"freq"}]; |
||||
|
foreach (@main::Outputs) { |
||||
|
($type,$mPin,$fPin)=split(/\s+/,$_); |
||||
|
push(@{$g{$mPin,$fPin}},1*$realAdsResults[$Index{"v_${mPin}_${fPin}.i"}]); |
||||
|
if ($mPin eq $fPin) { |
||||
|
push(@{$c{$mPin,$fPin}},$imagAdsResults[$Index{"v_${mPin}_${fPin}.i"}]/$omega); |
||||
|
} else { |
||||
|
push(@{$c{$mPin,$fPin}},-1*$imagAdsResults[$Index{"v_${mPin}_${fPin}.i"}]/$omega); |
||||
|
} |
||||
|
} |
||||
|
@realAdsResults=();@imagAdsResults=(); |
||||
|
} |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# |
||||
|
# Write the results to a file |
||||
|
# |
||||
|
|
||||
|
if (!open(OF,">$outputFile")) { |
||||
|
die("ERROR: cannot open file $outputFile, stopped"); |
||||
|
} |
||||
|
if ($main::fMin == $main::fMax) { |
||||
|
printf OF ("V($main::biasSweepPin)"); |
||||
|
} else { |
||||
|
printf OF ("Freq"); |
||||
|
} |
||||
|
foreach (@main::Outputs) { |
||||
|
($type,$mPin,$fPin)=split(/\s+/,$_); |
||||
|
printf OF (" $type($mPin,$fPin)"); |
||||
|
} |
||||
|
printf OF ("\n"); |
||||
|
for ($i=0;$i<=$#X;++$i) { |
||||
|
$outputLine="$X[$i]"; |
||||
|
foreach (@main::Outputs) { |
||||
|
($type,$mPin,$fPin)=split(/\s+/,$_); |
||||
|
if ($type eq "g") { |
||||
|
if (defined(${$g{$mPin,$fPin}}[$i])) { |
||||
|
$outputLine.=" ${$g{$mPin,$fPin}}[$i]"; |
||||
|
} else { |
||||
|
undef($outputLine);last; |
||||
|
} |
||||
|
} else { |
||||
|
if (defined(${$c{$mPin,$fPin}}[$i])) { |
||||
|
$outputLine.=" ${$c{$mPin,$fPin}}[$i]"; |
||||
|
} else { |
||||
|
undef($outputLine);last; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
if (defined($outputLine)) {printf OF ("$outputLine\n")} |
||||
|
} |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Clean up, unless the debug flag was specified |
||||
|
# |
||||
|
|
||||
|
if (! $main::debug) { |
||||
|
unlink($simulate::netlistFile); |
||||
|
unlink("$simulate::netlistFile.ds"); |
||||
|
unlink(".spiceinit"); |
||||
|
unlink("spectra.raw"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
sub runDcTest { |
||||
|
my($variant,$outputFile)=@_; |
||||
|
my($i,$arg,$name,$value,$pin); |
||||
|
my($start,$stop,$step); |
||||
|
my(@V,%DC,$temperature,$biasVoltage); |
||||
|
my($inData,$inResults,$iVariables,@Field,%Index,@AdsResults,$sign); |
||||
|
|
||||
|
if (!defined($main::biasSweepPin)) { |
||||
|
die("ERROR: biasSweep must be specified for a DC I(V) test, stopped"); |
||||
|
} |
||||
|
|
||||
|
# |
||||
|
# Make up the netlist, using a subckt to encapsulate the |
||||
|
# instance. This simplifies handling of the variants as |
||||
|
# the actual instance is driven by voltage-controlled |
||||
|
# voltage sources from the subckt pins, and the currents |
||||
|
# are fed back to the subckt pins using current-controlled |
||||
|
# current sources. Pin swapping, polarity reversal, and |
||||
|
# m-factor scaling can all be handled by simple modifications |
||||
|
# of this subckt. |
||||
|
# |
||||
|
|
||||
|
@V=(); |
||||
|
foreach $pin (@main::Outputs) {@{$DC{$pin}}=()} |
||||
|
($start,$stop,$step)=split(/\s+/,$main::biasSweepSpec); |
||||
|
$start-=$step; |
||||
|
foreach $temperature (@main::Temperature) { |
||||
|
foreach $biasVoltage (split(/\s+/,$main::biasListSpec)) { |
||||
|
if (!open(OF,">$simulate::netlistFile")) { |
||||
|
die("ERROR: cannot open file $simulate::netlistFile, stopped"); |
||||
|
} |
||||
|
print OF "; DC simulation for $main::simulatorName"; |
||||
|
print OF "Options UseNutmegFormat=yes ASCII_Rawfile=yes"; |
||||
|
print OF "Options Temp=$temperature"; |
||||
|
&generateCommonNetlistInfo($variant); |
||||
|
foreach $pin (@main::Pin) { |
||||
|
if ($main::isFloatingPin{$pin}) { |
||||
|
print OF "I_Source:i_$pin $pin 0 Idc=0"; |
||||
|
} elsif ($pin eq $main::biasListPin) { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=$biasVoltage"; |
||||
|
} elsif ($pin eq $main::biasSweepPin) { |
||||
|
if ($stop < $start) { # flip polarity as ADS always does lo->hi sweep |
||||
|
print OF "V_Source:v_$pin 0 $pin Vdc=".(-1)*$start; |
||||
|
} else { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=$start"; |
||||
|
} |
||||
|
} else { |
||||
|
print OF "V_Source:v_$pin $pin 0 Vdc=$main::BiasFor{$pin}"; |
||||
|
} |
||||
|
} |
||||
|
print OF "mysub:x1 ".join(" ",@main::Pin); |
||||
|
if ($stop < $start) { |
||||
|
$sign=-1; |
||||
|
print OF "SweepPlan:dcPlan Start=".(-1)*$start." Stop=".(-1)*$stop." Step=".(-1)*$step; |
||||
|
} else { |
||||
|
$sign=1; |
||||
|
print OF "SweepPlan:dcPlan Start=$start Stop=$stop Step=$step"; |
||||
|
} |
||||
|
print OF "DC:DC1 SweepVar=\"v_$main::biasSweepPin.Vdc\" SweepPlan=\"dcPlan\""; |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Run simulations and get the results |
||||
|
# |
||||
|
|
||||
|
if (!open(SIMULATE,"$simulate::simulatorCommand $simulate::netlistFile 2>/dev/null |")) { |
||||
|
die("ERROR: cannot run $main::simulatorName, stopped"); |
||||
|
} |
||||
|
$inResults=0; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp; |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
if (!open(SIMULATE,"spectra.raw")) { |
||||
|
die("ERROR: cannot open ADS spectra.raw file, stopped"); |
||||
|
} |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
if (s/^Variables:\s*//) { |
||||
|
$iVariables=0; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
while (<SIMULATE>) { |
||||
|
chomp;s/^\s+//;s/\s+$//; |
||||
|
if (/^Values:/) { |
||||
|
$inResults=1;last; |
||||
|
} |
||||
|
++$iVariables; |
||||
|
@Field=split; |
||||
|
$Index{$Field[1]}=$Field[0]; |
||||
|
} |
||||
|
@AdsResults=(); |
||||
|
next; |
||||
|
} |
||||
|
next if (!$inResults); |
||||
|
@Field=split; |
||||
|
shift(@Field) if ($#Field == 2); |
||||
|
push(@AdsResults,@Field); |
||||
|
if ($#AdsResults == $iVariables) { |
||||
|
push(@V,$sign*$AdsResults[$Index{"v_$main::biasSweepPin.Vdc"}]); |
||||
|
foreach $pin (@main::Outputs) { |
||||
|
if ($pin eq $main::biasSweepPin) { |
||||
|
push(@{$DC{$pin}},$sign*$AdsResults[$Index{"v_$pin.i"}]); |
||||
|
} elsif ($main::isFloatingPin{$pin}) { |
||||
|
push(@{$DC{$pin}},1*$AdsResults[$Index{"$pin"}]); |
||||
|
} else { |
||||
|
push(@{$DC{$pin}},1*$AdsResults[$Index{"v_$pin.i"}]); |
||||
|
} |
||||
|
} |
||||
|
@AdsResults=(); |
||||
|
} |
||||
|
} |
||||
|
close(SIMULATE); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
# |
||||
|
# Write the results to a file |
||||
|
# |
||||
|
|
||||
|
if (!open(OF,">$outputFile")) { |
||||
|
die("ERROR: cannot open file $outputFile, stopped"); |
||||
|
} |
||||
|
printf OF ("V($main::biasSweepPin)"); |
||||
|
foreach $pin (@main::Outputs) { |
||||
|
if ($main::isFloatingPin{$pin}) { |
||||
|
printf OF (" V($pin)"); |
||||
|
} else { |
||||
|
printf OF (" I($pin)"); |
||||
|
} |
||||
|
} |
||||
|
printf OF ("\n"); |
||||
|
for ($i=0;$i<=$#V;++$i) { |
||||
|
next if (abs($V[$i]-$start) < abs(0.1*$step)); # this is dummy first bias point |
||||
|
printf OF ("$V[$i]"); |
||||
|
foreach $pin (@main::Outputs) {printf OF (" ${$DC{$pin}}[$i]")} |
||||
|
printf OF ("\n"); |
||||
|
} |
||||
|
close(OF); |
||||
|
|
||||
|
# |
||||
|
# Clean up, unless the debug flag was specified |
||||
|
# |
||||
|
|
||||
|
if (! $main::debug) { |
||||
|
unlink($simulate::netlistFile); |
||||
|
unlink("$simulate::netlistFile.ds"); |
||||
|
unlink(".spiceinit"); |
||||
|
unlink("spectra.raw"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
sub generateCommonNetlistInfo { |
||||
|
my($variant)=$_[0]; |
||||
|
my(@Pin_x,$arg,$name,$value,$eFactor,$fFactor,$pin,@Args); |
||||
|
foreach $pin (@main::Pin) {push(@Pin_x,"${pin}_x")} |
||||
|
if ($variant=~/^scale$/) { |
||||
|
die("ERROR: there is no scale or shrink option for ads, stopped"); |
||||
|
} |
||||
|
if ($variant=~/^shrink$/) { |
||||
|
die("ERROR: there is no scale or shrink option for ads, stopped"); |
||||
|
} |
||||
|
if ($variant=~/_P/) { |
||||
|
$eFactor=-1;$fFactor=1; |
||||
|
} else { |
||||
|
$eFactor=1;$fFactor=-1; |
||||
|
} |
||||
|
if ($variant=~/^m$/) { |
||||
|
if ($main::outputNoise) { |
||||
|
$fFactor/=sqrt($main::mFactor); |
||||
|
} else { |
||||
|
$fFactor/=$main::mFactor; |
||||
|
} |
||||
|
} |
||||
|
if (defined($main::verilogaFile)) { |
||||
|
print OF ""; |
||||
|
print OF "#load \"veriloga\", \"$main::verilogaFile\";"; |
||||
|
} |
||||
|
print OF " "; |
||||
|
print OF "define mysub (".join(" ",@Pin_x).")"; |
||||
|
foreach $pin (@main::Pin) { |
||||
|
if ($main::isFloatingPin{$pin}) { # assumed "dt" thermal pin, no scaling sign change |
||||
|
print OF "V_Source:v_$pin ${pin} ${pin}_x Vdc=0"; |
||||
|
} elsif ($variant=~/^Flip/ && defined($main::flipPin{$pin})) { |
||||
|
print OF "#uselib \"ckt\", \"VCVS\""; |
||||
|
print OF "VCVS:e_$pin $main::flipPin{$pin}_x 0 ${pin}_v 0 G=$eFactor"; |
||||
|
print OF "V_Source:v_$pin ${pin}_v ${pin} Vdc=0"; |
||||
|
print OF "SDD:f_$pin $main::flipPin{$pin}_x 0 C[1]=\"v_$pin\" I[1]=_c1*$fFactor"; |
||||
|
} else { |
||||
|
print OF "#uselib \"ckt\", \"VCVS\""; |
||||
|
print OF "VCVS:e_$pin ${pin}_x 0 ${pin}_v 0 G=$eFactor"; |
||||
|
print OF "V_Source:v_$pin ${pin}_v ${pin} Vdc=0"; |
||||
|
print OF "SDD:f_$pin ${pin}_x 0 C[1]=\"v_$pin\" I[1]=_c1*$fFactor"; |
||||
|
} |
||||
|
} |
||||
|
print OF " "; |
||||
|
if (defined($main::verilogaFile)) { |
||||
|
if ($variant=~/_P/) { |
||||
|
@Args=split(/\s+/,$main::pTypeSelectionArguments); |
||||
|
} else { |
||||
|
@Args=split(/\s+/,$main::nTypeSelectionArguments); |
||||
|
} |
||||
|
print OF "$Args[0]:${main::keyLetter}1 ".join(" ",@main::Pin)." \\"; |
||||
|
foreach $arg (@Args[1..$#Args]) { |
||||
|
($name,$value)=split(/=/,$arg); |
||||
|
print OF " ".$name."=$value \\"; |
||||
|
} |
||||
|
foreach $arg (@main::InstanceParameters) { |
||||
|
($name,$value)=split(/=/,$arg); |
||||
|
if ($variant=~/^scale$/) { |
||||
|
if ($main::isLinearScale{$name}) { |
||||
|
$value/=$main::scaleFactor; |
||||
|
} elsif ($main::isAreaScale{$name}) { |
||||
|
$value/=$main::scaleFactor**2; |
||||
|
} |
||||
|
} |
||||
|
if ($variant=~/^shrink$/) { |
||||
|
if ($main::isLinearScale{$name}) { |
||||
|
$value/=(1.0-$main::shrinkPercent*0.01); |
||||
|
} elsif ($main::isAreaScale{$name}) { |
||||
|
$value/=(1.0-$main::shrinkPercent*0.01)**2; |
||||
|
} |
||||
|
} |
||||
|
print OF " ".$name."=$value \\"; |
||||
|
} |
||||
|
if ($variant eq "m") { |
||||
|
print OF " $simulate::mFactorVerilogaName=$main::mFactor \\"; |
||||
|
} |
||||
|
foreach $arg (@main::ModelParameters) { |
||||
|
print OF " ".$arg." \\"; |
||||
|
} |
||||
|
} else { |
||||
|
print OF "mymodel:${main::keyLetter}1 ".join(" ",@main::Pin)." \\"; |
||||
|
foreach $arg (@main::InstanceParameters) { |
||||
|
($name,$value)=split(/=/,$arg); |
||||
|
if ($variant=~/^scale$/) { |
||||
|
if ($main::isLinearScale{$name}) { |
||||
|
$value/=$main::scaleFactor; |
||||
|
} elsif ($main::isAreaScale{$name}) { |
||||
|
$value/=$main::scaleFactor**2; |
||||
|
} |
||||
|
} |
||||
|
if ($variant=~/^shrink$/) { |
||||
|
if ($main::isLinearScale{$name}) { |
||||
|
$value/=(1.0-$main::shrinkPercent*0.01); |
||||
|
} elsif ($main::isAreaScale{$name}) { |
||||
|
$value/=(1.0-$main::shrinkPercent*0.01)**2; |
||||
|
} |
||||
|
} |
||||
|
print OF " ".ucfirst($name)."=$value \\"; |
||||
|
} |
||||
|
if ($variant eq "m") { |
||||
|
print OF " _M=$main::mFactor \\"; |
||||
|
} |
||||
|
print OF " "; |
||||
|
if ($variant=~/_P/) { |
||||
|
print OF "model mymodel $main::pTypeSelectionArguments \\"; |
||||
|
} else { |
||||
|
print OF "model mymodel $main::nTypeSelectionArguments \\"; |
||||
|
} |
||||
|
foreach $arg (@main::ModelParameters) { |
||||
|
print OF " ".ucfirst($arg)." \\"; |
||||
|
} |
||||
|
} |
||||
|
print OF " "; |
||||
|
print OF "end mysub"; |
||||
|
print OF " "; |
||||
|
} |
||||
|
|
||||
|
1; |
||||
@ -0,0 +1,37 @@ |
|||||
|
HICUML2 v2.4.0 Gummel Test |
||||
|
VE Q1_E 0 1.0 |
||||
|
VC Q1_C 0 0.0 |
||||
|
VB Q1_B 0 0.0 |
||||
|
RT Q1_T 0 1M |
||||
|
Q1 Q1_C Q1_B Q1_E Q1_E Q1_T P1 icVB=0.2 icVC=0.2 dt=0.0 |
||||
|
.DC VE -0.2 -1.2 -10m |
||||
|
* .DC VE -0.2 -0.21 -10m |
||||
|
|
||||
|
.print dc abs(i(vc)) abs(i(vb)) |
||||
|
|
||||
|
* @Q1[area] @Q1[icvbe] @Q1[icvce] @Q1[temp] @Q1[m] @Q1[vbe] @Q1[vbc] @Q1[vce] @Q1[vsc] @Q1[ic] @Q1[ib] @Q1[ie] @Q1[iavl] @Q1[is] @Q1[rcx_t] @Q1[re_t] @Q1[rbi] @Q1[rb] @Q1[betadc] @Q1[gmi] @Q1[gms] @Q1[rpii] @Q1[rpix] @Q1[rmui] @Q1[rmux] @Q1[roi] @Q1[cpii] @Q1[cpix] @Q1[cmui] @Q1[cmux] @Q1[ccs] @Q1[betaac] @Q1[crbi] @Q1[tf] @Q1[ft] @Q1[p] @Q1[tk] @Q1[dtsh] |
||||
|
|
||||
|
|
||||
|
.MODEL P1 NPN LEVEL=8 |
||||
|
+ c10=9.074e-030 qp0=1.008e-013 hfe=10.01 hfc=20.04 hjei=3.382 hjci=0.2 |
||||
|
+ ibeis=1.328e-019 mbei=1.027 ireis=1.5e-014 mrei=2 ibeps=1.26e-019 mbep=1.042 |
||||
|
+ ireps=1.8e-014 mrep=1.8 mcf=1 tbhrec=1e-010 ibcis=4.603e-017 mbci=1.15 |
||||
|
+ ibcxs=0 mbcx=1 ibets=0.02035 abet=24 tunode=1 favl=18.96 qavl=5.092e-014 |
||||
|
+ alfav=-0.0024 alqav=-0.0006284 rbi0=4.444 rbx=2.568 fgeo=0.7409 fdqr0=0 |
||||
|
+ fcrbi=0 fqi=1 re=1.511 rcx=2.483 itss=0 msf=1 iscs=0 msc=1 |
||||
|
+ tsf=0 rsu=0 csu=0 cjei0=8.869e-015 vdei=0.714 zei=0.2489 ajei=1.65 |
||||
|
+ cjep0=2.178e-015 vdep=0.8501 zep=0.2632 ajep=1.6 cjci0=3.58e-015 vdci=0.8201 |
||||
|
+ zci=0.2857 vptci=1.79 cjcx0=6.299e-015 vdcx=0.8201 zcx=0.2863 vptcx=1.977 |
||||
|
+ fbcpar=0.3 fbepar=1 cjs0=2.6e-014 vds=0.9997 zs=0.4295 vpts=100 |
||||
|
+ t0=2.089e-013 dt0h=8e-014 tbvl=8.25e-014 tef0=3.271e-013 gtfe=3.548 thcs=5.001e-012 |
||||
|
+ ahc=0.05 fthc=0.7 rci0=9.523 vlim=0.6999 vces=0.01 vpt=2 tr=0 |
||||
|
+ cbepar=2.609e-014 cbcpar=1.64512e-014 alqf=0.166667 alit=0.333333 flnqs=0 kf=0 |
||||
|
+ af=2 cfbe=-1 latb=0 latl=0 vgb=0.91 alt0=0.004 kt0=6.588e-005 |
||||
|
+ zetaci=0.58 alvs=0.001 alces=-0.2286 zetarbi=0.3002 zetarbx=0.06011 zetarcx=-0.02768 |
||||
|
+ zetare=-0.9605 zetacx=0 vge=1.17 vgc=1.17 vgs=1.17 f1vg=-0.000102377 f2vg=0.00043215 |
||||
|
+ zetact=5 zetabet=4.892 flsh=0 rth=1113.4 cth=6.841e-012 zetarth=0 |
||||
|
+ alrth=0.002 flcomp=2.4 tnom=26.85 acbar=1.5 flcono=0 icbar=0.01 |
||||
|
+ vcbar=0.04 zetavgbe=0.7 hf0=40 ahjei=3 rhjei=2 delck=2 zetahjei=-0.5 |
||||
|
|
||||
|
|
||||
|
.END |
||||
@ -0,0 +1,112 @@ |
|||||
|
|
||||
|
No. of Data Rows : 101 |
||||
|
|
||||
|
Circuit: HICUML2 v2.4.0 Gummel Test |
||||
|
|
||||
|
Doing analysis at TEMP = 300.150000 and TNOM = 300.150000 |
||||
|
HICUM2 v2.4.0 Gummel Test |
||||
|
-------------------------------------------------------------------------------- |
||||
|
Index v-sweep abs(i(vc)) abs(i(vb)) |
||||
|
-------------------------------------------------------------------------------- |
||||
|
0 2.000000e-01 4.049275e-13 2.228959e-12 |
||||
|
1 2.100000e-01 5.113338e-13 2.714122e-12 |
||||
|
2 2.200000e-01 6.630638e-13 3.309110e-12 |
||||
|
3 2.300000e-01 8.814204e-13 4.039392e-12 |
||||
|
4 2.400000e-01 1.197716e-12 4.936361e-12 |
||||
|
5 2.500000e-01 1.657977e-12 6.038721e-12 |
||||
|
6 2.600000e-01 2.329849e-12 7.394200e-12 |
||||
|
7 2.700000e-01 3.312756e-12 9.061656e-12 |
||||
|
8 2.800000e-01 4.752819e-12 1.111369e-11 |
||||
|
9 2.900000e-01 6.864784e-12 1.363988e-11 |
||||
|
10 3.000000e-01 9.964231e-12 1.675076e-11 |
||||
|
11 3.100000e-01 1.451491e-11 2.058275e-11 |
||||
|
12 3.200000e-01 2.119828e-11 2.530429e-11 |
||||
|
13 3.300000e-01 3.101563e-11 3.112340e-11 |
||||
|
14 3.400000e-01 4.543821e-11 3.829703e-11 |
||||
|
15 3.500000e-01 6.662754e-11 4.714276e-11 |
||||
|
16 3.600000e-01 9.775923e-11 5.805316e-11 |
||||
|
17 3.700000e-01 1.434984e-10 7.151385e-11 |
||||
|
18 3.800000e-01 2.106980e-10 8.812576e-11 |
||||
|
19 3.900000e-01 3.094239e-10 1.086330e-10 |
||||
|
20 4.000000e-01 4.544605e-10 1.339576e-10 |
||||
|
21 4.100000e-01 6.675208e-10 1.652431e-10 |
||||
|
22 4.200000e-01 9.804908e-10 2.039088e-10 |
||||
|
23 4.300000e-01 1.440191e-09 2.517182e-10 |
||||
|
24 4.400000e-01 2.115368e-09 3.108651e-10 |
||||
|
25 4.500000e-01 3.106946e-09 3.840828e-10 |
||||
|
26 4.600000e-01 4.563079e-09 4.747811e-10 |
||||
|
27 4.700000e-01 6.701218e-09 5.872227e-10 |
||||
|
28 4.800000e-01 9.840494e-09 7.267467e-10 |
||||
|
29 4.900000e-01 1.444919e-08 9.000562e-10 |
||||
|
30 5.000000e-01 2.121433e-08 1.115590e-09 |
||||
|
31 5.100000e-01 3.114373e-08 1.384002e-09 |
||||
|
32 5.200000e-01 4.571544e-08 1.718799e-09 |
||||
|
33 5.300000e-01 6.709676e-08 2.137132e-09 |
||||
|
34 5.400000e-01 9.846489e-08 2.660929e-09 |
||||
|
35 5.500000e-01 1.444763e-07 3.318308e-09 |
||||
|
36 5.600000e-01 2.119536e-07 4.145522e-09 |
||||
|
37 5.700000e-01 3.108897e-07 5.189556e-09 |
||||
|
38 5.800000e-01 4.559164e-07 6.511663e-09 |
||||
|
39 5.900000e-01 6.684482e-07 8.192167e-09 |
||||
|
40 6.000000e-01 9.798144e-07 1.033707e-08 |
||||
|
41 6.100000e-01 1.435828e-06 1.308719e-08 |
||||
|
42 6.200000e-01 2.103455e-06 1.663074e-08 |
||||
|
43 6.300000e-01 3.080525e-06 2.122105e-08 |
||||
|
44 6.400000e-01 4.509880e-06 2.720120e-08 |
||||
|
45 6.500000e-01 6.596844e-06 3.503877e-08 |
||||
|
46 6.600000e-01 9.647940e-06 4.537475e-08 |
||||
|
47 6.700000e-01 1.410226e-05 5.909275e-08 |
||||
|
48 6.800000e-01 2.059972e-05 7.741690e-08 |
||||
|
49 6.900000e-01 3.006819e-05 1.020505e-07 |
||||
|
50 7.000000e-01 4.385020e-05 1.353718e-07 |
||||
|
51 7.100000e-01 6.388229e-05 1.807107e-07 |
||||
|
52 7.200000e-01 9.294511e-05 2.427359e-07 |
||||
|
53 7.300000e-01 1.350039e-04 3.279924e-07 |
||||
|
54 7.400000e-01 1.956548e-04 4.456394e-07 |
||||
|
55 7.500000e-01 2.826782e-04 6.084386e-07 |
||||
|
56 7.600000e-01 4.066653e-04 8.340431e-07 |
||||
|
57 7.700000e-01 5.816221e-04 1.146610e-06 |
||||
|
58 7.800000e-01 8.253658e-04 1.578709e-06 |
||||
|
59 7.900000e-01 1.159449e-03 2.173417e-06 |
||||
|
60 8.000000e-01 1.608349e-03 2.986417e-06 |
||||
|
61 8.100000e-01 2.197834e-03 4.087850e-06 |
||||
|
62 8.200000e-01 2.952755e-03 5.563725e-06 |
||||
|
63 8.300000e-01 3.894822e-03 7.516722e-06 |
||||
|
64 8.400000e-01 5.040995e-03 1.006634e-05 |
||||
|
65 8.500000e-01 6.402781e-03 1.334838e-05 |
||||
|
66 8.600000e-01 7.986391e-03 1.751363e-05 |
||||
|
67 8.700000e-01 9.793400e-03 2.272603e-05 |
||||
|
68 8.800000e-01 1.182159e-02 2.916016e-05 |
||||
|
69 8.900000e-01 1.406575e-02 3.699861e-05 |
||||
|
70 9.000000e-01 1.651838e-02 4.642947e-05 |
||||
|
71 9.100000e-01 1.917019e-02 5.764474e-05 |
||||
|
72 9.200000e-01 2.201052e-02 7.084062e-05 |
||||
|
73 9.300000e-01 2.502762e-02 8.622214e-05 |
||||
|
74 9.400000e-01 2.820878e-02 1.040182e-04 |
||||
|
75 9.500000e-01 3.154025e-02 1.245245e-04 |
||||
|
76 9.600000e-01 3.500674e-02 1.482245e-04 |
||||
|
77 9.700000e-01 3.858976e-02 1.761297e-04 |
||||
|
78 9.800000e-01 4.226323e-02 2.106934e-04 |
||||
|
79 9.900000e-01 4.598348e-02 2.579408e-04 |
||||
|
80 1.000000e+00 4.967483e-02 3.308659e-04 |
||||
|
81 1.010000e+00 5.323301e-02 4.499557e-04 |
||||
|
82 1.020000e+00 5.657993e-02 6.330012e-04 |
||||
|
83 1.030000e+00 5.972028e-02 8.813991e-04 |
||||
|
84 1.040000e+00 6.271680e-02 1.181850e-03 |
||||
|
85 1.050000e+00 6.563508e-02 1.518125e-03 |
||||
|
86 1.060000e+00 6.852092e-02 1.878222e-03 |
||||
|
87 1.070000e+00 7.140176e-02 2.255370e-03 |
||||
|
88 1.080000e+00 7.429288e-02 2.646645e-03 |
||||
|
89 1.090000e+00 7.720226e-02 3.051443e-03 |
||||
|
90 1.100000e+00 8.013339e-02 3.470405e-03 |
||||
|
91 1.110000e+00 8.308694e-02 3.904762e-03 |
||||
|
92 1.120000e+00 8.606171e-02 4.355986e-03 |
||||
|
93 1.130000e+00 8.905522e-02 4.825594e-03 |
||||
|
94 1.140000e+00 9.206412e-02 5.315066e-03 |
||||
|
95 1.150000e+00 9.508446e-02 5.825795e-03 |
||||
|
96 1.160000e+00 9.811193e-02 6.359080e-03 |
||||
|
97 1.170000e+00 1.011420e-01 6.916117e-03 |
||||
|
98 1.180000e+00 1.041701e-01 7.498008e-03 |
||||
|
99 1.190000e+00 1.071917e-01 8.105763e-03 |
||||
|
100 1.200000e+00 1.102022e-01 8.740302e-03 |
||||
|
|
||||
@ -0,0 +1,34 @@ |
|||||
|
HICUML2 v2.4.0 Gummel Test |
||||
|
VE Q1_E 0 1.0 |
||||
|
VC Q1_C 0 0.0 |
||||
|
VB Q1_B 0 0.0 |
||||
|
RT Q1_T 0 1M |
||||
|
Q1 Q1_C Q1_B Q1_E Q1_E Q1_T P1 |
||||
|
.DC VE -0.2 -1.2 -10m |
||||
|
.OPTIONS GMIN=1e-13 NOACCT |
||||
|
|
||||
|
.print dc abs(i(vc)) abs(i(vb)) |
||||
|
|
||||
|
.MODEL P1 NPN LEVEL=8 |
||||
|
+ c10=9.074e-030 qp0=1.008e-013 hfe=10.01 hfc=20.04 hjei=3.382 hjci=0.2 |
||||
|
+ ibeis=1.328e-019 mbei=1.027 ireis=1.5e-014 mrei=2 ibeps=1.26e-019 mbep=1.042 |
||||
|
+ ireps=1.8e-014 mrep=1.8 mcf=1 tbhrec=1e-010 ibcis=4.603e-017 mbci=1.15 |
||||
|
+ ibcxs=0 mbcx=1 ibets=0.02035 abet=24 tunode=1 favl=18.96 qavl=5.092e-014 |
||||
|
+ alfav=-0.0024 alqav=-0.0006284 rbi0=4.444 rbx=2.568 fgeo=0.7409 fdqr0=0 |
||||
|
+ fcrbi=0 fqi=1 re=1.511 rcx=2.483 itss=0 msf=1 iscs=0 msc=1 |
||||
|
+ tsf=0 rsu=0 csu=0 cjei0=8.869e-015 vdei=0.714 zei=0.2489 ajei=1.65 |
||||
|
+ cjep0=2.178e-015 vdep=0.8501 zep=0.2632 ajep=1.6 cjci0=3.58e-015 vdci=0.8201 |
||||
|
+ zci=0.2857 vptci=1.79 cjcx0=6.299e-015 vdcx=0.8201 zcx=0.2863 vptcx=1.977 |
||||
|
+ fbcpar=0.3 fbepar=1 cjs0=2.6e-014 vds=0.9997 zs=0.4295 vpts=100 |
||||
|
+ t0=2.089e-013 dt0h=8e-014 tbvl=8.25e-014 tef0=3.271e-013 gtfe=3.548 thcs=5.001e-012 |
||||
|
+ ahc=0.05 fthc=0.7 rci0=9.523 vlim=0.6999 vces=0.01 vpt=2 tr=0 |
||||
|
+ cbepar=2.609e-014 cbcpar=1.64512e-014 alqf=0.166667 alit=0.333333 flnqs=1 kf=0 |
||||
|
+ af=2 cfbe=-1 latb=0 latl=0 vgb=0.91 alt0=0.004 kt0=6.588e-005 |
||||
|
+ zetaci=0.58 alvs=0.001 alces=-0.2286 zetarbi=0.3002 zetarbx=0.06011 zetarcx=-0.02768 |
||||
|
+ zetare=-0.9605 zetacx=0 vge=1.17 vgc=1.17 vgs=1.17 f1vg=-0.000102377 f2vg=0.00043215 |
||||
|
+ zetact=5 zetabet=4.892 flsh=1 rth=1113.4 cth=6.841e-012 zetarth=0 |
||||
|
+ alrth=0.002 flcomp=2.4 tnom=26.85 acbar=1.5 flcono=0 icbar=0.01 |
||||
|
+ vcbar=0.04 zetavgbe=0.7 hf0=40 ahjei=3 rhjei=2 delck=2 zetahjei=-0.5 |
||||
|
|
||||
|
|
||||
|
.END |
||||
@ -0,0 +1,15 @@ |
|||||
|
## Process this file with automake to produce Makefile.in
|
||||
|
|
||||
|
|
||||
|
|
||||
|
TESTS = FG.cir \
|
||||
|
FG_sh.cir |
||||
|
|
||||
|
TESTS_ENVIRONMENT = $(SHELL) $(top_srcdir)/tests/bin/check.sh $(top_builddir)/src/ngspice |
||||
|
|
||||
|
EXTRA_DIST = \
|
||||
|
$(TESTS) \
|
||||
|
$(TESTS:.cir=.out) |
||||
|
|
||||
|
|
||||
|
MAINTAINERCLEANFILES = Makefile.in |
||||
@ -0,0 +1,41 @@ |
|||||
|
#use warnings |
||||
|
#use strict |
||||
|
|
||||
|
my $va_code = '../vacode/hicumL2V2p33.va'; |
||||
|
my %ref_para = (); |
||||
|
|
||||
|
open(FILE, "<$va_code"); |
||||
|
|
||||
|
while (<FILE>) { |
||||
|
my ($dummy, $name, $value) = /parameter\s*(real|integer)\s*(\w+)\s*=\s*([+-]?\d+(\.\d+)?([Ee][+-]?\d+)?)/; |
||||
|
|
||||
|
$ref_para{$name} = $value; |
||||
|
} |
||||
|
|
||||
|
my @para_names = keys %ref_para; |
||||
|
|
||||
|
close(FILE); |
||||
|
|
||||
|
my @parameters = ('npn_1D','npn_cornoise','npn_full','npn_full_sh','npn_full_subcoupl','npn_full_subtran','npn_internal','npn_lat_nqs','npn_vert_nqs'); |
||||
|
|
||||
|
foreach my $set (@parameters) { |
||||
|
open(FILE,"<$set"); |
||||
|
|
||||
|
my %act_para = (); |
||||
|
|
||||
|
while (<FILE>) { |
||||
|
my ($name, $value) = /\+\s?(\w+)\s?=\s?\(\s?([+-]?\d+(\.\d+)?([Ee][+-]?\d+)?)\s?\)/; |
||||
|
|
||||
|
$act_para{$name} = $value; |
||||
|
} |
||||
|
|
||||
|
my @neq = grep { $ref_para{$_} != $act_para{$_} } @para_names; |
||||
|
my @eq = grep { $ref_para{$_} == $act_para{$_} } @para_names; |
||||
|
|
||||
|
my $percentage = ($#neq/$#para_names)*100; |
||||
|
|
||||
|
print "$set : $percentage\n"; |
||||
|
#print join(' ', @eq), "\n"; |
||||
|
|
||||
|
close(FILE); |
||||
|
} |
||||
@ -0,0 +1,125 @@ |
|||||
|
+ c10 = ( 9.074e-030 ) |
||||
|
+ qp0 = ( 1.008e-013 ) |
||||
|
+ ich = ( 0 ) |
||||
|
+ hfe = ( 10.01 ) |
||||
|
+ hfc = ( 20.04 ) |
||||
|
+ hjei = ( 3.382 ) |
||||
|
+ hjci = ( 0.2 ) |
||||
|
+ ibeis = ( 1.328e-019 ) |
||||
|
+ mbei = ( 1.027 ) |
||||
|
+ ireis = ( 1.5e-014 ) |
||||
|
+ mrei = ( 2 ) |
||||
|
+ ibeps = ( 0 ) |
||||
|
+ mbep = ( 1 ) |
||||
|
+ ireps = ( 0 ) |
||||
|
+ mrep = ( 2 ) |
||||
|
+ mcf = ( 1 ) |
||||
|
+ tbhrec = ( 1e-010 ) |
||||
|
+ ibcis = ( 4.603e-017 ) |
||||
|
+ mbci = ( 1.15 ) |
||||
|
+ ibcxs = ( 0 ) |
||||
|
+ mbcx = ( 1 ) |
||||
|
+ ibets = ( 0 ) |
||||
|
+ abet = ( 40 ) |
||||
|
+ tunode = ( 1 ) |
||||
|
+ favl = ( 18.96 ) |
||||
|
+ qavl = ( 5.092e-014 ) |
||||
|
+ alfav = ( -0.0024 ) |
||||
|
+ alqav = ( -0.0006284 ) |
||||
|
+ rbi0 = ( 0 ) |
||||
|
+ rbx = ( 0 ) |
||||
|
+ fgeo = ( 0.6557 ) |
||||
|
+ fdqr0 = ( 0 ) |
||||
|
+ fcrbi = ( 0 ) |
||||
|
+ fqi = ( 1 ) |
||||
|
+ re = ( 0 ) |
||||
|
+ rcx = ( 0 ) |
||||
|
+ itss = ( 0 ) |
||||
|
+ msf = ( 1 ) |
||||
|
+ iscs = ( 0 ) |
||||
|
+ msc = ( 1 ) |
||||
|
+ tsf = ( 0 ) |
||||
|
+ rsu = ( 0 ) |
||||
|
+ csu = ( 0 ) |
||||
|
+ cjei0 = ( 8.869e-015 ) |
||||
|
+ vdei = ( 0.714 ) |
||||
|
+ zei = ( 0.2489 ) |
||||
|
+ ajei = ( 1.65 ) |
||||
|
+ cjep0 = ( 1e-020 ) |
||||
|
+ vdep = ( 0.9 ) |
||||
|
+ zep = ( 0.5 ) |
||||
|
+ ajep = ( 2.5 ) |
||||
|
+ cjci0 = ( 3.58e-015 ) |
||||
|
+ vdci = ( 0.8201 ) |
||||
|
+ zci = ( 0.2857 ) |
||||
|
+ vptci = ( 1.79 ) |
||||
|
+ cjcx0 = ( 1e-020 ) |
||||
|
+ vdcx = ( 0.7 ) |
||||
|
+ zcx = ( 0.4 ) |
||||
|
+ vptcx = ( 100 ) |
||||
|
+ fbcpar = ( 0 ) |
||||
|
+ fbepar = ( 1 ) |
||||
|
+ cjs0 = ( 0 ) |
||||
|
+ vds = ( 0.6 ) |
||||
|
+ zs = ( 0.5 ) |
||||
|
+ vpts = ( 100 ) |
||||
|
+ t0 = ( 2.089e-013 ) |
||||
|
+ dt0h = ( 8e-014 ) |
||||
|
+ tbvl = ( 8.25e-014 ) |
||||
|
+ tef0 = ( 3.271e-013 ) |
||||
|
+ gtfe = ( 3.548 ) |
||||
|
+ thcs = ( 5.001e-012 ) |
||||
|
+ ahc = ( 0.05 ) |
||||
|
+ fthc = ( 0.7 ) |
||||
|
+ rci0 = ( 9.523 ) |
||||
|
+ vlim = ( 0.6999 ) |
||||
|
+ vces = ( 0.01 ) |
||||
|
+ vpt = ( 2 ) |
||||
|
+ tr = ( 0 ) |
||||
|
+ cbepar = ( 0 ) |
||||
|
+ cbcpar = ( 0 ) |
||||
|
+ alqf = ( 0.166667 ) |
||||
|
+ alit = ( 0.333333 ) |
||||
|
+ flnqs = ( 0 ) |
||||
|
+ kf = ( 0 ) |
||||
|
+ af = ( 2 ) |
||||
|
+ cfbe = ( -1 ) |
||||
|
+ latb = ( 0 ) |
||||
|
+ latl = ( 0 ) |
||||
|
+ vgb = ( 0.91 ) |
||||
|
+ alt0 = ( 0.004 ) |
||||
|
+ kt0 = ( 6.588e-005 ) |
||||
|
+ zetaci = ( 0.58 ) |
||||
|
+ alvs = ( 0.001 ) |
||||
|
+ alces = ( -0.2286 ) |
||||
|
+ zetarbi = ( 0 ) |
||||
|
+ zetarbx = ( 0 ) |
||||
|
+ zetarcx = ( 0 ) |
||||
|
+ zetare = ( 0 ) |
||||
|
+ zetacx = ( 1 ) |
||||
|
+ vge = ( 1.17 ) |
||||
|
+ vgc = ( 1.17 ) |
||||
|
+ vgs = ( 1.17 ) |
||||
|
+ f1vg = ( -0.000102377 ) |
||||
|
+ f2vg = ( 0.00043215 ) |
||||
|
+ zetact = ( 5 ) |
||||
|
+ zetabet = ( 4.892 ) |
||||
|
+ alb = ( 0 ) |
||||
|
+ flsh = ( 0 ) |
||||
|
+ rth = ( 0 ) |
||||
|
+ cth = ( 0 ) |
||||
|
+ zetarth = ( 0 ) |
||||
|
+ alrth = ( 0 ) |
||||
|
+ flcomp = ( 2.3 ) |
||||
|
+ tnom = ( 26.85 ) |
||||
|
+ dt = ( 0 ) |
||||
|
+ acbar = ( 1.5 ) |
||||
|
+ flcono = ( 0 ) |
||||
|
+ icbar = ( 0.01 ) |
||||
|
+ vcbar = ( 0.04 ) |
||||
|
+ zetavgbe = ( 0.7 ) |
||||
|
+ hf0 = ( 40 ) |
||||
|
+ ahjei = ( 3 ) |
||||
|
+ rhjei = ( 2 ) |
||||
|
+ delck = ( 2 ) |
||||
|
+ zetahjei = ( -0.5 ) |
||||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue