Squashed commit of the following:
commit 4939bc89934899c16dcd14e11839bedd3c289ee9
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Oct 25 22:04:16 2020 +0100
added cppduals cleanly
commit 834cbc5aba9c1d5470a6f838161703a657d12810
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Oct 25 22:03:40 2020 +0100
remove cppduals
commit 69b922cef2
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Oct 25 21:59:00 2020 +0100
cppduals in new diretory
commit 4337cc0e33
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Oct 25 21:49:52 2020 +0100
hicum license cleaning
commit ba439dfdf5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Oct 17 13:19:05 2020 +0200
moved sh stamp, working
commit 29028ff34d
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Oct 17 12:56:54 2020 +0200
forgot something
commit 5743d2b551
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Oct 17 12:54:35 2020 +0200
rth stamp moved (no yet working)
commit 42d61da3eb
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Oct 17 11:54:10 2020 +0200
Hicum C/C++ code now under 3-clause BSD
commit 5088e869ea
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Oct 17 11:44:57 2020 +0200
cleaned comments
commit 18fc66e71b
Author: dwarning <dwarning>
Date: Sat Sep 12 19:48:11 2020 +0200
rm some less useful comments - no code change
commit 861f286fda
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Sep 8 15:45:46 2020 +0200
clean hicum2ask
commit a52274ba7d
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Sep 8 15:43:18 2020 +0200
fix nqs transient
commit fa7f96b4af
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Sep 7 13:17:42 2020 +0200
fix HICUM csu readin
commit 23183f10b6
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Aug 8 15:35:32 2020 +0200
added it to Hicum states -> noise
commit 020fc70607
Author: dwarning <dwarning>
Date: Tue Aug 4 09:18:05 2020 +0200
change inst to here
commit 33d06d9732
Author: dwarning <dwarning>
Date: Tue Aug 4 09:12:37 2020 +0200
reintroduce iavl and correct ibici shot noise
commit 7251265231
Author: dwarning <dwarning>
Date: Tue Aug 4 08:59:26 2020 +0200
more reasonable plot scaling
commit 67919b9bd8
Author: dwarning <dwarning>
Date: Tue Aug 4 08:56:04 2020 +0200
yet another try for flicker noise scaling
commit 689177a55f
Author: dwarning <dwarning>
Date: Mon Aug 3 10:41:44 2020 +0200
correct multiplier scaling for rsu
commit 58b89af40a
Author: dwarning <dwarning>
Date: Sun Aug 2 18:57:14 2020 +0200
prevent division by 0 for rbi
commit a4e7eb5b6c
Author: dwarning <dwarning>
Date: Sun Aug 2 18:25:51 2020 +0200
fix instance multiplier application for noise
commit 36862a7bc6
Author: dwarning <dwarning>
Date: Fri Jul 31 21:06:13 2020 +0200
white spaces
commit 8a0504bb13
Author: dwarning <dwarning>
Date: Fri Jul 31 18:32:45 2020 +0200
add a transient analysis example
commit c1f0348697
Author: dwarning <dwarning>
Date: Fri Jul 31 18:31:10 2020 +0200
still problems in different terminal configurations
commit 26e026e4c8
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jul 31 14:36:34 2020 +0200
fix stamp for Cth
commit dd84b1fcd3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jul 31 14:22:16 2020 +0200
fix bug in Cscp stamp
commit 1f13d2526f
Author: dwarning <dwarning>
Date: Fri Jul 31 11:29:25 2020 +0200
visualc mod - no impact to hicum
commit cff491feca
Author: dwarning <dwarning>
Date: Fri Jul 31 10:59:52 2020 +0200
wrong and twice assignment
commit 4a9dc52037
Author: dwarning <dwarning>
Date: Fri Jul 31 10:00:20 2020 +0200
twice assignment
commit c76bcc7cca
Author: dwarning <dwarning>
Date: Thu Jul 30 12:36:30 2020 +0200
delete base nodes from inner to outer
commit 4a472a3451
Author: dwarning <dwarning>
Date: Mon Jul 27 15:34:15 2020 +0200
correct the switch for Vbici limiting
commit f47bc449b3
Author: dwarning <dwarning>
Date: Sun Jul 26 21:56:48 2020 +0200
few parameter adaptions to version 2.40
commit 5901ec2902
Author: dwarning <dwarning>
Date: Sun Jul 26 16:37:44 2020 +0200
sign for CONSTCtoK must be +
commit 556171a905
Author: dwarning <dwarning>
Date: Sun Jul 26 16:36:15 2020 +0200
rbi is 0 if nodes are collapsed
commit 724887f32c
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jul 26 12:45:15 2020 +0200
add ngspice Temperature clipping in HICUM
commit d735f445e5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jul 26 12:13:39 2020 +0200
removed rbi fallback, removed rth_de
commit 162b174acd
Author: dwarning <dwarning>
Date: Sat Jul 25 12:31:05 2020 +0200
add few small-signal parameter
commit 5afb2dc8c8
Author: dwarning <dwarning>
Date: Fri Jul 24 16:49:11 2020 +0200
reduce unnecassary inits
commit 0efc047f5f
Author: dwarning <dwarning>
Date: Fri Jul 24 16:03:10 2020 +0200
few typos and comments
commit 14a5cd873b
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jul 24 11:25:51 2020 +0200
remove rbi stamps if nodes collapsed finish
commit f5461183f3
Author: 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
commit 00f51465e3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jul 24 11:07:58 2020 +0200
finish cleaning
commit 019ef4e07e
Author: 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)
commit 154036c09f
Author: 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
commit 03c3efd762
Author: Markus Mueller <metroid120@googlemail.com>
Date: Thu Jul 23 16:22:46 2020 +0200
finally: avalanche at very high T fix
commit 64704fd53e
Merge: 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 a26b3ee2b2
Author: Markus Mueller <metroid120@googlemail.com>
Date: Thu Jul 23 15:56:17 2020 +0200
start bugfix
commit f6db74ac50
Author: dwarning <dwarning>
Date: Tue Jul 21 18:56:32 2020 +0200
rm obsolete files
commit 9854038f2c
Author: dwarning <dwarning>
Date: Tue Jul 21 16:48:56 2020 +0200
allow periphal resistors and rbi default 0
commit 34f579c08f
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jul 21 13:05:54 2020 +0200
fix bug node collapsing BI BP
commit 6f5627f441
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jul 21 11:48:22 2020 +0200
node collapsing BI BP HICUM
commit 187d391383
Author: dwarning <dwarning>
Date: Tue Jul 21 09:58:59 2020 +0200
few corrections and reordering
commit 0fc39a424e
Author: dwarning <dwarning>
Date: Mon Jul 20 19:36:15 2020 +0200
unify nqs flag for setup/unsetup
commit 8944ad2e32
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 18 14:23:30 2020 +0200
iavl_Vbiei changed sign back ...
commit cc9682f9e5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 18 14:05:12 2020 +0200
HICUM limit for avalanche
commit 284583e0cc
Author: dwarning <dwarning>
Date: Wed Jul 15 10:11:46 2020 +0200
cleanup initial conditions to the traditional spice usage
commit c3cadb8de1
Author: dwarning <dwarning>
Date: Wed Jul 15 08:57:03 2020 +0200
rm unused files
commit 8bc687ddbe
Author: dwarning <dwarning>
Date: Mon Jul 13 10:44:56 2020 +0200
correct check6 init
commit 9250464ac1
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 0fb86510aa
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 11 15:02:04 2020 +0200
fix gmin in HICUM
commit 735339e288
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
commit fd5b7a6485
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 11 14:44:01 2020 +0200
fix HICUM gmin
commit 1659190b21
Author: 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
commit aaa94e5c10
Author: dwarning <dwarning>
Date: Thu Jul 9 18:10:04 2020 +0200
add hspice to qa
commit 6fe586cf9d
Author: dwarning <dwarning>
Date: Thu Jul 9 17:26:28 2020 +0200
relax convergence criteria for qa test
commit 127c2ca451
Author: dwarning <dwarning>
Date: Thu Jul 9 14:02:48 2020 +0200
correct loop stopping criteria
commit cfae080c1a
Author: dwarning <dwarning>
Date: Wed Jul 8 18:02:13 2020 +0200
examples now version 2.4.0
commit 7b099242da
Author: dwarning <dwarning>
Date: Wed Jul 8 17:18:28 2020 +0200
rm non qa file
commit 0c2ef2f7c4
Author: dwarning <dwarning>
Date: Wed Jul 8 17:15:58 2020 +0200
qa test is now version 2.4.0
commit e90939126d
Author: dwarning <dwarning>
Date: Wed Jul 8 17:13:29 2020 +0200
qa test is now version 2.4.0
commit 114aeee5c5
Author: dwarning <dwarning>
Date: Wed Jul 8 17:12:05 2020 +0200
now version 2.4.0
commit 0f33776513
Author: dwarning <dwarning>
Date: Wed Jul 8 11:40:43 2020 +0200
reactivate convergence check
commit 6f382c76d8
Author: dwarning <dwarning>
Date: Wed Jul 8 11:02:30 2020 +0200
rm old comments and artefacts
commit 5950a2fb03
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jul 8 09:51:03 2020 +0200
example print for dual number
commit abab054352
Author: dwarning <dwarning>
Date: Tue Jul 7 08:51:51 2020 +0200
nqs must set after defaulting model parameters
commit 4c34e54c7b
Author: dwarning <dwarning>
Date: Mon Jul 6 21:37:04 2020 +0200
prevent false branch because of rounding error for flcomp
commit 4bb09b35c3
Author: dwarning <dwarning>
Date: Sun Jul 5 22:16:28 2020 +0200
clear separation between geometry and temperature scaling
commit 90ab76d876
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jul 5 18:14:08 2020 +0200
fix comments in HICUM scaling
commit d7dd26880c
Author: 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
commit 320a66c0a4
Merge: 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
commit d78032109f
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jul 5 17:26:45 2020 +0200
HICUM scaling with "area" and "m" parameters.
commit b09edc706a
Author: dwarning <dwarning>
Date: Sun Jul 5 17:10:51 2020 +0200
must fallthrough because icVbe is after icVce
commit dbd99a33a5
Author: dwarning <dwarning>
Date: Sun Jul 5 09:59:09 2020 +0200
some useful examples to show hicum2 capabilities
commit ba1c2de06e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 4 20:21:38 2020 +0200
added comment to IC vars
commit 6fce26437e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 4 20:03:13 2020 +0200
remove hicum inital conditions that are not spice-like
commit aa283f40ef
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jul 4 19:55:58 2020 +0200
added HICUM pole zero analysis
commit 2165afdf27
Author: dwarning <dwarning>
Date: Fri Jul 3 17:39:03 2020 +0200
another cut&paste error and typo
commit 8b680b0c28
Author: dwarning <dwarning>
Date: Fri Jul 3 17:28:40 2020 +0200
another cut&paste error
commit f1698c7a81
Author: dwarning <dwarning>
Date: Fri Jul 3 15:42:37 2020 +0200
add shot noise sources for it and ibiei
commit 966891d5f7
Author: dwarning <dwarning>
Date: Fri Jul 3 14:39:31 2020 +0200
correct multiplier for flicker noise and base-emitter source connection
commit 80e932424f
Author: dwarning <dwarning>
Date: Fri Jul 3 14:27:52 2020 +0200
cut&paste error
commit 61ee68c782
Author: dwarning <dwarning>
Date: Thu Jul 2 21:05:58 2020 +0200
few corrections in noise model
commit ad16be59ba
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jul 1 14:44:13 2020 +0200
reorder code
commit e81b41c653
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jul 1 14:33:12 2020 +0200
fix bugs HICHUM acload
commit 1d5f88e93d
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 28 11:51:10 2020 +0200
fix bugs
commit bbb729ae8f
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 28 11:03:48 2020 +0200
intermediate state
commit a95aade55a
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 27 20:16:37 2020 +0200
fix derivative in NQS network
commit a54c52221c
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 27 20:05:58 2020 +0200
small fixes HICUM
commit 7407302d50
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 27 17:48:23 2020 +0200
fix bug in HICUMacload
commit bb03c8f663
Merge: 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
commit 1fa7898747
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 24 13:16:20 2020 +0200
remove nqs from limit function and gmin
commit e7d143e044
Author: dwarning <dwarning>
Date: Tue Jun 23 18:22:40 2020 +0200
tk is not an alias parameter name
commit 75e3a4da64
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 23 16:24:59 2020 +0200
protect nqs network
commit 1c36e997ba
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 23 15:44:46 2020 +0200
nqs in ac
commit 524abe95f3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 23 15:21:27 2020 +0200
NQS in acload
commit 0833f955ef
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 23 14:47:35 2020 +0200
move cross-coupled charges from state vector to here struct
commit 03b4a87477
Author: dwarning <dwarning>
Date: Mon Jun 22 11:52:42 2020 +0200
prevent crash if tnode is given but she parameter not
commit 9ab20e2f35
Author: dwarning <dwarning>
Date: Mon Jun 22 11:51:47 2020 +0200
alias for tnom
commit 3140bedc3f
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 21 21:50:39 2020 +0200
fix nqs
commit 8dfd2e5a4d
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 20 18:41:35 2020 +0200
fix HICUM setup
commit f6e4bba9e3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 20 18:40:04 2020 +0200
finish NQS for DC case
commit 21862cbdb9
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 20 17:55:01 2020 +0200
first test ok ... modify state vector now
commit 1c5773292e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 20 17:45:57 2020 +0200
first implementation of NQS, not tested
commit 4fd24db766
Author: dwarning <dwarning>
Date: Fri Jun 19 22:12:49 2020 +0200
external temp node has number 5
commit 8fb3f2ce9a
Merge: 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 b7e4c39d80
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jun 19 19:03:46 2020 +0200
fix unset t node HICUM
commit 5f4085d4a8
Author: dwarning <dwarning>
Date: Wed Jun 17 20:34:02 2020 +0200
unify self-heating switch
commit c927c32541
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 17 18:41:15 2020 +0200
qaSpec with ads run
commit d05eaa744e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 17 17:38:50 2020 +0200
added derivatives for NQS network
commit 88cf4bb925
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 7161253342
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
commit a46cb231a0
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 16 17:32:20 2020 +0200
tmp node to gnd in HICUM if no SH
commit e2bb25b125
Author: dwarning <dwarning>
Date: Mon Jun 15 08:54:50 2020 +0200
qaSpec guess for ads
commit bbde282b51
Author: dwarning <dwarning>
Date: Mon Jun 15 08:33:17 2020 +0200
typo 1D
commit 4e6deec579
Merge: 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
commit 5da1d7031c
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 14 19:57:56 2020 +0200
HICUMload transient part first review, small fixes
commit 96af16e673
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 14 18:53:49 2020 +0200
gmin fix
commit 6fbbeb06d9
Author: dwarning <dwarning>
Date: Sun Jun 14 11:05:12 2020 +0200
complete device node request for temp node
commit eae118787e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 13 21:52:32 2020 +0200
fix hicumACload singular matrix bug
commit 2a1f47e1e5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 13 20:29:04 2020 +0200
cleaned
commit 7e5fdae917
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 13 20:19:51 2020 +0200
refactor gmin in HICUM
commit 7aadd9af4a
Merge: 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
commit f55f613c24
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat Jun 13 19:31:39 2020 +0200
added dual numbers include in ngspice/include
commit 595e464479
Author: dwarning <dwarning>
Date: Fri Jun 12 19:13:26 2020 +0200
introduce version parameter to prevent warnings in qa test
commit 147bf5eb4a
Author: dwarning <dwarning>
Date: Fri Jun 12 17:16:48 2020 +0200
use standard include path configuration for external cppduals
commit 7a41174b5e
Author: dwarning <dwarning>
Date: Thu Jun 11 18:22:42 2020 +0200
add ads for qa test
commit 3942fc48ce
Author: Markus Mueller <metroid120@googlemail.com>
Date: Thu Jun 11 17:40:13 2020 +0200
added charges for SHE in HICUMacload
commit 12fa8a8cf7
Author: dwarning <dwarning>
Date: Thu Jun 11 15:34:06 2020 +0200
resolve confusing naming of instance parameter structure
commit 7578aec2a8
Author: dwarning <dwarning>
Date: Thu Jun 11 15:29:40 2020 +0200
introduce version parameter to prevent warnings in qa test
commit b401428cdd
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 10 18:17:44 2020 +0200
minor cleaning
commit 5d28b97fb5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 7 16:46:21 2020 +0200
added SHE stamps for DC currents in HICUMacload
commit 9737dc7a5b
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 7 16:36:36 2020 +0200
HICUM acload initial review
commit 6eefe34d56
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 7 13:58:24 2020 +0200
add real part of AC matrix
commit 55e14e62e7
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 7 13:20:12 2020 +0200
dirty fix iavl
commit 99a21e9f61
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun Jun 7 12:15:39 2020 +0200
some minor modificaitons, avalanche current problems
commit 99f8c9a9ed
Merge: 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
commit 17898981cd
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri Jun 5 10:20:21 2020 +0200
minor cleaning, fix derivative iavl
commit 6b9f5647ca
Author: dwarning <dwarning>
Date: Thu Jun 4 18:23:10 2020 +0200
first version for cmc qa check
commit 3f11d38774
Author: Markus Mueller <metroid120@googlemail.com>
Date: Thu Jun 4 16:37:09 2020 +0200
implemented experimental rth direct evaluation
commit 40900da8bf
Author: Markus Mueller <metroid120@googlemail.com>
Date: Thu Jun 4 14:45:12 2020 +0200
small correction
commit 7f1493bddb
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 3 19:25:35 2020 +0200
minor changes, cleaning
commit 55367a44a5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 3 19:05:39 2020 +0200
completed all del voltages
commit d32ff77aef
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 3 18:23:19 2020 +0200
renaming variables for cleaner code
commit e4b4978368
Author: 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
commit a6b39a749c
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 3 17:29:37 2020 +0200
correct Temperature update
commit 55c33ad675
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Jun 3 17:21:31 2020 +0200
before changing Temp in load
commit 7f7b31e5c0
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 2 20:01:07 2020 +0200
fixing small bugs
commit 7555278074
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 2 19:39:48 2020 +0200
fixed some stamps
commit 0d59e12518
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Jun 2 19:13:50 2020 +0200
fixed avalanche
commit ee25c6ce42
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Jun 1 20:07:25 2020 +0200
cleaned up
commit d61b510207
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Jun 1 19:18:45 2020 +0200
hicumL2 load routine seems to be working, next ac?
commit 29a61f21e2
Merge: 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
commit c94120cbf9
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Jun 1 14:30:40 2020 +0200
first hicum convergence with SH
commit dcf4a44871
Merge: 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 c37a88bec8
Author: dwarning <dwarning>
Date: Mon Jun 1 10:56:53 2020 +0200
set the cppduals include folder above ngspice dir
commit c1444a06b6
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun May 31 20:38:16 2020 +0200
finish hicum SH review, next testing.
commit e3c194e050
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 59c50d5095
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 f7012280e6
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sat May 30 17:12:37 2020 +0200
fix rbi convergence
commit 326b29c4d8
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri May 29 16:54:30 2020 +0200
started work on self heating
commit 4994feaa2b
Author: Markus Mueller <metroid120@googlemail.com>
Date: Fri May 29 16:08:18 2020 +0200
corrected rbi stamp...
commit 460e7ec04b
Author: mariok <mario.krattenmacher@web.de>
Date: Wed May 20 11:22:01 2020 +0200
more thermal stuff implemented
commit 194331867e
Author: mariok <mario.krattenmacher@web.de>
Date: Tue May 19 16:24:34 2020 +0200
added HICUMtempCollPtr HICUMtempBasePtr HICUMtempEmitPtr
commit 697af41531
Author: dwarning <dwarning>
Date: Tue May 19 08:03:35 2020 +0200
exchange hicum2temp file in VS project
commit 03750cd24e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun May 17 20:20:00 2020 +0200
ziwschenstand, checked code for maths errors
commit 418966c6e5
Author: mariok <mario.krattenmacher@web.de>
Date: Wed May 13 10:25:49 2020 +0200
can not call a function inside a comparision
commit abecd18651
Author: mariok <mario.krattenmacher@web.de>
Date: Wed May 13 10:09:11 2020 +0200
removed all buggs from hicumL2 to debug.
commit 1fe3cc8b12
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 afdffacd4b
Author: mariok <mario.krattenmacher@web.de>
Date: Tue May 12 19:59:09 2020 +0200
ac und pz load
commit 890ccc415f
Author: mariok <mario.krattenmacher@web.de>
Date: Tue May 12 19:55:23 2020 +0200
implemented hicum_diode as example
commit 63bf7113d4
Author: mariok <mario.krattenmacher@web.de>
Date: Tue May 12 18:33:51 2020 +0200
all temperature scaling equations done using dual numbers
commit 96c66dd645
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 58f66c1d46
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue May 12 12:28:50 2020 +0200
fix Vbe initialization
commit 35deffa742
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue May 12 12:25:48 2020 +0200
cleaned further
commit 304dd91f58
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue May 12 12:15:52 2020 +0200
cleaned up, small fixes, include Tf
commit 1d7da49e27
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue May 12 09:37:39 2020 +0200
fixed bugs
commit 479c2a19ea
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon May 11 15:50:01 2020 +0200
forgot Nan catcher
commit 5bbe0f9cf7
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon May 11 15:48:03 2020 +0200
bugfix Q_p calculation
commit 67857cf983
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 d6ee2c206e
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon May 11 14:08:18 2020 +0200
resolved some un-initialized variables
commit 76ed5cb36a
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun May 10 20:48:38 2020 +0200
finished clean
commit ba6e6d5e49
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun May 10 18:48:24 2020 +0200
added all remaining hicum l2 elements
commit 36244b809a
Author: Markus Mueller <metroid120@googlemail.com>
Date: Sun May 10 17:45:27 2020 +0200
resolved Dietmar comments from email
commit eaa5be9716
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue May 5 16:38:08 2020 +0200
added base emitter recombination current and derivatives
commit 4318b7165b
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 3008c526bf
Author: mariok <mario.krattenmacher@web.de>
Date: Mon May 4 19:00:31 2020 +0200
removed QpT and testing only 1 OP
commit 9cb4c1546f
Author: mariok <mario.krattenmacher@web.de>
Date: Mon May 4 18:37:52 2020 +0200
icVBE and icVCE used for DC
commit 8a73697675
Author: mariok <mario.krattenmacher@web.de>
Date: Mon May 4 18:03:46 2020 +0200
fixed dual number Q_0_hjei_vbe
commit 5783938b08
Author: mariok <mario.krattenmacher@web.de>
Date: Mon May 4 16:30:41 2020 +0200
reintroduced dtemp as instance parameter
commit 9350f3f3be
Author: dwarning <dwarning>
Date: Sun May 3 17:25:12 2020 +0200
Revert some namings
commit 197f6db83b
Author: dwarning <dwarning>
Date: Sat May 2 23:18:58 2020 +0200
Adapt VS project to C++
commit af32f79641
Author: dwarning <dwarning>
Date: Sat May 2 23:18:43 2020 +0200
Skip NQS effekt and revert some namings
commit a995aa0cce
Author: dwarning <dwarning>
Date: Sat May 2 23:18:27 2020 +0200
Skip NQS effekt
commit d7295cbe78
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
commit 2502b57eee
Author: Markus Mueller <metroid120@googlemail.com>
Date: Wed Apr 29 19:03:26 2020 +0200
added quests, derivative vciei changed to vbiei vbici
commit 6ca440e584
Author: dwarning <dwarning>
Date: Wed Apr 29 09:35:12 2020 +0200
add hicumL2.cpp instead of hicum2load.c in VS project
commit 6e98506a7f
Author: dwarning <dwarning>
Date: Wed Apr 29 09:33:08 2020 +0200
cmath seems not to have M_PI
commit d6332815b3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Apr 28 20:58:35 2020 +0200
derivatives it looking good
commit aaaace7247
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Apr 28 19:39:48 2020 +0200
adding hicum derivatives like a mad-man
commit 2d8a3e3629
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Apr 28 18:44:46 2020 +0200
added Q_pT and derivatives...fun
commit 50a3e372cf
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Apr 28 17:17:17 2020 +0200
starting work on transfer current
commit 8fd70e2f15
Author: Markus Mueller <metroid120@googlemail.com>
Date: Tue Apr 28 13:01:18 2020 +0200
added asks, found bug with ibci
commit 2baac89ae3
Merge: 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 c897e60c8b
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 27 18:12:40 2020 +0200
pointer in ask
commit 3b0551c544
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 27 17:36:19 2020 +0200
two small bugfixes
commit b02c763ed1
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 27 17:13:30 2020 +0200
HICUM2ask done according to VA-Code
commit 97a0aa856b
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 afbde80500
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 27 16:21:25 2020 +0200
zwischenstand
commit d86caadb07
Author: mariok <mario.krattenmacher@web.de>
Date: Thu Apr 23 18:23:40 2020 +0200
added nodes for NQS
commit 1b0cf0d08c
Author: mariok <mario.krattenmacher@web.de>
Date: Thu Apr 23 16:59:55 2020 +0200
testing with and without self heating
commit 64c0c41180
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 0d0c6a0800
Author: mariok <mario.krattenmacher@web.de>
Date: Thu Apr 23 16:26:37 2020 +0200
assigned the temperature derivates to me
commit 1b00fad771
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 f5a1c35d80
Author: mariok <mario.krattenmacher@web.de>
Date: Thu Apr 23 14:14:40 2020 +0200
removed dummdumm
commit dc7891f7b5
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 19:16:36 2020 +0200
added more junction caps, checklist and overview
commit 0dbf31bc73
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 19:00:16 2020 +0200
derivatives rbi
commit 330d009fa6
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 18:40:24 2020 +0200
more derivatives avalanche current, ibcis
commit ce200d75e3
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 18:05:49 2020 +0200
derivatives peripheral junction caps, diodes
commit 8ce9733f91
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 17:45:42 2020 +0200
derivatives tunneling current
commit 806ff80138
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 17:17:14 2020 +0200
derivatives critical current
commit 8f49490cec
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 16:59:09 2020 +0200
derivatives T_f0
commit 3164dbe594
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 16:38:34 2020 +0200
derivatives hole charge at low bias
commit b32bf6dd14
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 16:27:38 2020 +0200
zwischenstand
commit 84307c4acf
Author: Markus Mueller <metroid120@googlemail.com>
Date: Mon Apr 20 16:19:25 2020 +0200
zwischenstand
commit 0d94c5d56d
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 20 10:56:58 2020 +0200
moved cppduals to system lib include
commit 9da946bf2d
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 20 09:59:49 2020 +0200
started derivatives of hicum2 minority charge
commit a2946e98a4
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 c7e5df27db
Author: mariok <mario.krattenmacher@web.de>
Date: Thu Apr 16 14:44:41 2020 +0200
DC runs with Ixf
commit 08a0e6a019
Author: mariok <mario.krattenmacher@web.de>
Date: Wed Apr 15 18:15:26 2020 +0200
gummel works with flsh = 1 and flnqs = 0
commit b83e05ee95
Author: mariok <mario.krattenmacher@web.de>
Date: Tue Apr 14 16:09:42 2020 +0200
added test to makefile
commit 7d29a9a269
Author: mariok <mario.krattenmacher@web.de>
Date: Tue Apr 14 10:06:27 2020 +0200
test circuit and results
commit 14c46bc3bd
Author: mariok <mario.krattenmacher@web.de>
Date: Mon Apr 13 18:12:06 2020 +0200
cleaned renaming in all files
commit 67ddd98f75
Author: dwarning <dwarning>
Date: Wed Jan 29 13:08:02 2020 +0100
rename
commit 9551b6df92
Author: dwarning <dwarning>
Date: Wed Jan 29 13:07:42 2020 +0100
rename
commit 12bb866ba5
Author: dwarning <dwarning>
Date: Wed Jan 29 13:06:45 2020 +0100
rename
commit 414eeb4067
Author: dwarning <dwarning>
Date: Tue Jan 28 22:18:08 2020 +0100
clarify charge and capacitance implementation
commit c318ef15ee
Author: dwarning <dwarning>
Date: Sat Jan 25 14:57:55 2020 +0100
introduce first excess phase network and update to 2.4.0
commit 85c34cfb0f
Author: dwarning <dwarning>
Date: Wed Jan 22 18:16:54 2020 +0100
VS update
commit 86ff2778f8
Author: dwarning <dwarning>
Date: Wed Jan 22 18:16:29 2020 +0100
OP infos
commit 1607f4d88c
Author: dwarning <dwarning>
Date: Wed Jan 22 18:16:19 2020 +0100
OP infos
commit ca1e114922
Author: dwarning <dwarning>
Date: Wed Jan 22 18:16:11 2020 +0100
OP infos
commit 408440d33b
Author: dwarning <dwarning>
Date: Tue Jan 21 11:25:56 2020 +0100
some cleanings
commit 3364f6da87
Author: dwarning <dwarning>
Date: Tue Jan 14 09:55:58 2020 +0100
VS update
commit 6fbefe4afa
Author: dwarning <dwarning>
Date: Tue Jan 14 09:55:48 2020 +0100
Ongoing derivations
commit 86521dd7c0
Author: dwarning <dwarning>
Date: Tue Jan 14 09:02:52 2020 +0100
VS update
commit ba5b106fae
Author: dwarning <dwarning>
Date: Tue Jan 14 09:01:30 2020 +0100
Ongoing derivations
commit ea6254eca3
Author: dwarning <dwarning>
Date: Sat Jan 11 17:17:21 2020 +0100
Initial HICUM2 integration
commit 2bd0f1bdab
Author: dwarning <dwarning>
Date: Mon Jan 6 00:11:48 2020 +0100
Initial HICUM2 integration
commit 7d160f659e
Author: dwarning <dwarning>
Date: Sun Jan 5 15:01:20 2020 +0100
Initial HICUM2 integration
commit 420ca90e55
Author: dwarning <dwarning>
Date: Sun Jan 5 15:00:06 2020 +0100
Initial HICUM2 integration
This commit is contained in:
parent
d06ff2abab
commit
6ff354c4a7
|
|
@ -76,8 +76,11 @@ Makefile.in
|
|||
|
||||
# Visual Studio user options files
|
||||
**/*.vcxproj.user
|
||||
.vscode/
|
||||
|
||||
src/frontend/parse-bison.c
|
||||
src/frontend/parse-bison.h
|
||||
src/spicelib/parser/inpptree-parser.c
|
||||
src/spicelib/parser/inpptree-parser.h
|
||||
# Visual Studio Code user options files
|
||||
.vscode/
|
||||
|
|
|
|||
11
configure.ac
11
configure.ac
|
|
@ -35,6 +35,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|||
ext_CFLAGS="${CFLAGS+yes}"
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AX_PROG_CC_FOR_BUILD
|
||||
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
|
|
@ -43,6 +44,8 @@ AC_SUBST([AM_CPPFLAGS], ['-I. -I$(srcdir) -I$(top_builddir)/src/include'])
|
|||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
|
||||
|
||||
# Package Options
|
||||
# ---------------
|
||||
|
||||
|
|
@ -683,6 +686,7 @@ AC_ARG_ENABLE([rpath],
|
|||
]
|
||||
)
|
||||
|
||||
|
||||
if test "x$_use_rpath" = xyes ; then
|
||||
# Try to figure out if we need -Rpath for finding X11 libs
|
||||
# at runtime. Why autoconf doesn't already do this, I don't
|
||||
|
|
@ -767,6 +771,11 @@ esac
|
|||
AM_CONDITIONAL([NO_X], [test "x$has_no_x" = xtrue])
|
||||
AM_CONDITIONAL([NO_HELP], [test "x$has_no_help" = xtrue])
|
||||
|
||||
# Additional libs of hicum group
|
||||
AC_CHECK_LIB(stdc++, main, XTRALIBS="$XTRALIBS -lstdc++",,)
|
||||
AC_SUBST(XTRALIBS, $XTRALIBS)
|
||||
|
||||
LIBS="$LIBS $XTRALIBS"
|
||||
|
||||
# enabling making of the old and outdated applications
|
||||
# ngsconvert ngproc2mod ngmultidec ngmakeidx nghelp
|
||||
|
|
@ -1239,6 +1248,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/spicelib/devices/isrc/Makefile
|
||||
src/spicelib/devices/hfet1/Makefile
|
||||
src/spicelib/devices/hfet2/Makefile
|
||||
src/spicelib/devices/hicum2/Makefile
|
||||
src/spicelib/devices/hisim2/Makefile
|
||||
src/spicelib/devices/hisimhv1/Makefile
|
||||
src/spicelib/devices/hisimhv2/Makefile
|
||||
|
|
@ -1315,6 +1325,7 @@ AC_CONFIG_FILES([Makefile
|
|||
tests/filters/Makefile
|
||||
tests/general/Makefile
|
||||
tests/hfet/Makefile
|
||||
tests/hicum2/Makefile
|
||||
tests/hisim/Makefile
|
||||
tests/hisimhv1/Makefile
|
||||
tests/hisimhv2/Makefile
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -73,6 +73,7 @@ DYNAMIC_DEVICELIBS = \
|
|||
spicelib/devices/isrc/libisrc.la \
|
||||
spicelib/devices/hfet1/libhfet.la \
|
||||
spicelib/devices/hfet2/libhfet2.la \
|
||||
spicelib/devices/hicum2/libhicum2.la \
|
||||
spicelib/devices/hisim2/libhisim2.la \
|
||||
spicelib/devices/hisimhv1/libhisimhv1.la \
|
||||
spicelib/devices/hisimhv2/libhisimhv2.la \
|
||||
|
|
@ -581,6 +582,7 @@ libngspice_la_LIBADD += \
|
|||
libngspice_la_CFLAGS = -shared
|
||||
|
||||
libngspice_la_LDFLAGS = -shared
|
||||
libngspice_la_LDFLAGS += -lstdc++
|
||||
|
||||
if SHWIN
|
||||
libngspice_la_LDFLAGS += -Wl,--output-def=ngspice.def -Wl,--out-implib=ngspice.dll.a
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
Binary file not shown.
|
After Width: | Height: | 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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();
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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)
|
||||
|
|
@ -2,10 +2,13 @@
|
|||
#define ngspice_BOOL_H
|
||||
|
||||
//typedef unsigned char bool;
|
||||
#ifndef __cplusplus
|
||||
typedef int bool;
|
||||
#endif
|
||||
|
||||
typedef int BOOL;
|
||||
|
||||
|
||||
#define BOOLEAN int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
|
@ -13,4 +16,5 @@ typedef int BOOL;
|
|||
#define YES 1
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -428,6 +428,10 @@ extern int DCpss(CKTcircuit *, int);
|
|||
/* SP */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
extern int NaskQuest(CKTcircuit *, JOB *, int, IFvalue *);
|
||||
extern int NsetParm(CKTcircuit *, JOB *, int, IFvalue *);
|
||||
extern int NIacIter(CKTcircuit *);
|
||||
|
|
@ -445,6 +449,9 @@ extern int NIreinit(CKTcircuit *);
|
|||
extern int NIsenReinit(CKTcircuit *);
|
||||
extern int NIdIter (CKTcircuit *);
|
||||
extern void NInzIter(CKTcircuit *, int, int);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PREDICTOR
|
||||
extern int NIpred(CKTcircuit *ckt);
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ NIintegrate(CKTcircuit *ckt, double *geq, double *ceq, double cap, int qcap)
|
|||
case TRAPEZOIDAL:
|
||||
switch(ckt->CKTorder) {
|
||||
case 1:
|
||||
ckt->CKTstate0[ccap] = ckt->CKTag[0] * ckt->CKTstate0[qcap]
|
||||
ckt->CKTstate0[ccap] = ckt->CKTag[0] * ckt->CKTstate0[qcap]
|
||||
+ ckt->CKTag[1] * ckt->CKTstate1[qcap];
|
||||
break;
|
||||
case 2:
|
||||
ckt->CKTstate0[ccap] = - ckt->CKTstate1[ccap] * ckt->CKTag[1] +
|
||||
ckt->CKTag[0] *
|
||||
ckt->CKTstate0[ccap] = - ckt->CKTstate1[ccap] * ckt->CKTag[1] +
|
||||
ckt->CKTag[0] *
|
||||
( ckt->CKTstate0[qcap] - ckt->CKTstate1[qcap] );
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ SUBDIRS = \
|
|||
isrc \
|
||||
hfet1 \
|
||||
hfet2 \
|
||||
hicum2 \
|
||||
hisim2 \
|
||||
hisimhv1 \
|
||||
hisimhv2 \
|
||||
|
|
@ -88,6 +89,7 @@ DIST_SUBDIRS = \
|
|||
isrc \
|
||||
hfet1 \
|
||||
hfet2 \
|
||||
hicum2 \
|
||||
hisim2 \
|
||||
hisimhv1 \
|
||||
hisimhv2 \
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* uninterrupted or error-free. The end-user understands that the
|
||||
* program was developed for research purposes and is advised not to
|
||||
* rely exclusively on the program for any reason.
|
||||
*
|
||||
*
|
||||
* IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,
|
||||
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
|
||||
* LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
|
||||
|
|
@ -97,6 +97,7 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
|
|||
#include "dio/dioitf.h"
|
||||
#include "hfet1/hfetitf.h"
|
||||
#include "hfet2/hfet2itf.h"
|
||||
#include "hicum2/hicum2itf.h"
|
||||
#include "hisim2/hsm2itf.h"
|
||||
#include "hisimhv1/hsmhvitf.h"
|
||||
#include "hisimhv2/hsmhv2itf.h"
|
||||
|
|
@ -126,7 +127,6 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
|
|||
#include "vdmos/vdmositf.h"
|
||||
#ifdef ADMS
|
||||
#include "adms/hicum0/hicum0itf.h"
|
||||
#include "adms/hicum2/hicum2itf.h"
|
||||
#include "adms/mextram/bjt504titf.h"
|
||||
#include "adms/ekv/ekvitf.h"
|
||||
#include "adms/psp102/psp102itf.h"
|
||||
|
|
@ -170,6 +170,7 @@ static SPICEdev *(*static_devices[])(void) = {
|
|||
get_dio_info,
|
||||
get_hfeta_info,
|
||||
get_hfet2_info,
|
||||
get_hicum_info,
|
||||
get_hsm2_info,
|
||||
get_hsmhv_info,
|
||||
get_hsmhv2_info,
|
||||
|
|
@ -207,7 +208,6 @@ static SPICEdev *(*static_devices[])(void) = {
|
|||
|
||||
#ifdef ADMS
|
||||
(SPICEdev *(*)(void)) get_hicum0_info,
|
||||
(SPICEdev *(*)(void)) get_hicum2_info,
|
||||
(SPICEdev *(*)(void)) get_bjt504t_info,
|
||||
(SPICEdev *(*)(void)) get_ekv_info,
|
||||
(SPICEdev *(*)(void)) get_psp102_info,
|
||||
|
|
@ -264,7 +264,7 @@ spice_init_devices(void)
|
|||
g_evt_udn_info = TMALLOC(Evt_Udn_Info_t *, 1);
|
||||
g_evt_num_udn_types = 1;
|
||||
g_evt_udn_info[0] = &idn_digital_info;
|
||||
|
||||
|
||||
DEVicesfl = TMALLOC(int, DEVNUM);
|
||||
/* tmalloc should automatically zero the array! */
|
||||
#endif
|
||||
|
|
@ -298,12 +298,12 @@ SPICEdev ** devices(void)
|
|||
#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \
|
||||
"bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \
|
||||
"cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \
|
||||
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum0", "hicum2", "bjt504t", "ekv", "psp102"}
|
||||
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum0", "bjt504t", "ekv", "psp102"}
|
||||
#else
|
||||
#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \
|
||||
"bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \
|
||||
"cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \
|
||||
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc"}
|
||||
"mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum2"}
|
||||
#endif
|
||||
int load_dev(char *name) {
|
||||
char *msg;
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@ next1: if (model->DIOsatSWCurGiven) { /* sidewall current */
|
|||
}
|
||||
|
||||
} else { /* merge saturation currents and use same characteristic as bottom diode */
|
||||
|
||||
csat = csat + csatsw;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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 */
|
||||
|
|
@ -17,11 +17,11 @@ model_numnodes(int type)
|
|||
{
|
||||
#ifdef ADMS
|
||||
if (type == INPtypelook("hicum0") ||
|
||||
type == INPtypelook("hicum2") ||
|
||||
type == INPtypelook("bjt504t"))
|
||||
return 5;
|
||||
#else
|
||||
if (type == INPtypelook("VBIC"))
|
||||
if (type == INPtypelook("VBIC") ||
|
||||
type == INPtypelook("hicum2"))
|
||||
return 5;
|
||||
#endif
|
||||
|
||||
|
|
@ -101,9 +101,9 @@ void INP2Q(CKTcircuit *ckt, INPtables * tab, struct card *current, CKTnode *gnod
|
|||
#endif
|
||||
#ifdef ADMS
|
||||
thismodel->INPmodType != INPtypelook("hicum0") &&
|
||||
thismodel->INPmodType != INPtypelook("hicum2") &&
|
||||
thismodel->INPmodType != INPtypelook("bjt504t") &&
|
||||
#endif
|
||||
thismodel->INPmodType != INPtypelook("hicum2") &&
|
||||
thismodel->INPmodType != INPtypelook("VBIC"))
|
||||
{
|
||||
LITERR("incorrect model type");
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
|
|||
"Device type HICUM0 not available in this binary\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 8:
|
||||
type = INPtypelook("hicum2");
|
||||
if(type < 0) {
|
||||
|
|
@ -85,7 +86,6 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab)
|
|||
"Device type HICUM2 not available in this binary\n");
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: /* placeholder; use level 4 for the next model */
|
||||
#ifdef ADMS
|
||||
err = INPmkTemp(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ DIST_SUBDIRS = \
|
|||
filters \
|
||||
general \
|
||||
hfet \
|
||||
hicum2 \
|
||||
hisim \
|
||||
hisimhv1 \
|
||||
hisimhv2 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -435,7 +435,7 @@ sub generateCommonNetlistInfo {
|
|||
my($variant,$temperature)=@_;
|
||||
my(@Pin_x,$arg,$name,$value,$eFactor,$fFactor,$pin);
|
||||
foreach $pin (@main::Pin) {push(@Pin_x,"${pin}_x")}
|
||||
print OF ".options temp=$temperature gmin=1e-15 abstol=1e-14 reltol=1e-8";
|
||||
print OF ".options temp=$temperature gmin=1e-13 abstol=1e-13 reltol=1e-3";
|
||||
if ($variant=~/^scale$/) {
|
||||
die("ERROR: there is no scale or shrink option for ngspice, stopped");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if [ -z "$testProgramFlags" ] ; then
|
|||
testProgramFlags="-nw"
|
||||
fi
|
||||
|
||||
#testProgramFlags="-d -V"
|
||||
testProgramFlags="-d -V"
|
||||
|
||||
|
||||
help() {
|
||||
|
|
@ -32,6 +32,8 @@ help() {
|
|||
|
||||
hspice run tests and compare results hspice
|
||||
|
||||
ads run tests and compare results ads
|
||||
|
||||
clean remove all previously generated simulation results
|
||||
|
||||
NOTE: if test results exist they are not resimulated
|
||||
|
|
@ -126,6 +128,10 @@ hspice() {
|
|||
run_test hspice
|
||||
}
|
||||
|
||||
ads() {
|
||||
run_test ads
|
||||
}
|
||||
|
||||
|
||||
#####
|
||||
##### clean
|
||||
|
|
@ -134,6 +140,7 @@ hspice() {
|
|||
clean() {
|
||||
rm -rf ${qaResultsDirectory}/ngspice ngspiceCkt*
|
||||
rm -rf ${qaResultsDirectory}/hspice hspiceCkt*
|
||||
rm -rf ${qaResultsDirectory}/ads adsCkt*
|
||||
}
|
||||
|
||||
clean_ngspice() {
|
||||
|
|
@ -144,9 +151,13 @@ clean_hspice() {
|
|||
rm -rf ${qaResultsDirectory}/hspice hspiceCkt*
|
||||
}
|
||||
|
||||
clean_ads() {
|
||||
rm -rf ${qaResultsDirectory}/ads adsCkt*
|
||||
}
|
||||
|
||||
|
||||
all() {
|
||||
ngspice hspice
|
||||
ngspice hspice ads
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -172,7 +183,7 @@ done
|
|||
|
||||
for arg in $@ ; do
|
||||
case "$arg" in
|
||||
all | clean | clean_ngspice | ngspice | clean_hspice | hspice)
|
||||
all | clean | clean_ngspice | ngspice | clean_hspice | hspice | clean_ads | ads)
|
||||
"$arg"
|
||||
;;
|
||||
*)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue