ngspice/src
Meisam Bahadori 79ba4be561 * Enhancement-306: ngspice — the E-241 twin in the fft expression function
Enhancement-241 fixed an amplitude normalization that divided by the ZERO-PADDED
transform size instead of the number of input samples -- in the `fft` COMMAND
(frontend/com_fft.c). The identical mistake survived in maths/cmaths/cmath4.c, the
vector-expression function reached by `let F = fft(v)`: a separate implementation of
the same computation.

Found by continuing the oracle campaign that produced E-241, and located with E-241's
own discriminator, the DC bin. One signal, 4001 samples padded to 4096, DC offset 2.0:

  fft s          ; the COMMAND    ->  mag(s)[0] = 2.000000    correct
  let F = fft(s) ; the FUNCTION   ->  mag(F)[0] = 1.953613    = 2.0 * 4001/4096

X[0] is the sum of the samples, D*length for a DC offset D, so dividing by the padded N
reads back D*length/N. As E-241 put it: a DC value cannot depend on how many samples
were taken.

This is a contradiction, not a matter of convention. cx_fft holds TWO complete
implementations -- one for complex input, one for real -- and each has an FFTW branch
and a Green's radix-2 branch. In BOTH, the FFTW branch already used the input length
while Green's used the padded size:

  real branch     FFTW: scale = ((double)length)/2.0    Green: ((double)N)/2   <- wrong
  complex branch  FFTW: scale = (double) fpts           Green: (double) N      <- wrong

the correct version sitting a few lines from the wrong one inside the same function --
the same shape as `avg` disagreeing with `integ` in E-302. HAVE_LIBFFTW3 is undefined in
this build, so Green's is the live path and the defect was reachable.

  oracle                              before      after       closed form
  real-input, DC bin                  1.953613    2.000000    2.0
  real-input, ifft(fft(x))            2.3e-02     1.1e-16     0
  complex-input, bin 0                0.9766780   0.9998683   0.9998683

The round trip is an INDEPENDENT confirmation: nothing here touches ifft, so its going
from 2.3% error to machine precision is evidence from a direction the fix did not aim
at -- the pair only inverts when the forward normalization is right. cx_ifft was
audited and deliberately left alone for that reason.

Every caller of the Green's radix-2 kernel was audited, not only the one that failed:
com_fft.c's fft (x2) and spec/PSD (x2) are correct from E-241; cx_ifft is correct;
trannoise/1-f-code.c cannot pad at all, since n_pts is grown to 2^n_exp by construction;
and fft/ifft are the only transform functions in the expression table, so there is no
spec twin to miss.

Verification: examples/fftexpr_examples/verify_fftexpr.py -- 6 checks under both
solvers, all against closed form (DC bin on both paths, round trip padded and unpadded,
complex-input bin 0 against the analytic mean of an RC response). It scores 3/6 on the
pre-fix binary, so it is a real regression guard. E-241's own suite (fftnorm_examples)
and ifftreal_examples pass unchanged. Full sweep 241/241 OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-02 19:56:26 +02:00
..
ciderlib Enable CIDER with KLU for DC, OP, and TRAN analyses. Small signal AC analysis is not yet supported for CIDER complex valued device KLU matrices. The examples/cider testcases produce printed simulation result values which have slight differences between Sparse and KLU. Differences are probably expected and in a few cases are ~1-2%, sometimes a little more. This should be good enough for most CIDER analyses. Francesco did a good piece of work. Runtimes are significantly shorter with KLU. 2026-02-03 13:55:12 +01:00
frontend * E-241: fft/spec — fix amplitude normalization for non-power-of-2 records 2026-08-02 18:51:45 +02:00
include Add command 'pyplot', invoking numpy/matplotlib plotting, 2026-07-18 16:04:03 +02:00
maths * Enhancement-306: ngspice — the E-241 twin in the fft expression function 2026-08-02 19:56:26 +02:00
misc Update the eng() function. 2026-04-28 11:49:13 +02:00
osdi Fixes a memory corruption bug resulting from improper parsing 2026-02-03 14:17:59 +01:00
spicelib Disable topology reduction by default. Enable it by setting 2026-07-17 10:56:55 +02:00
xspice * E-252: XSPICE xfer/file_source — fix two heap out-of-bounds writes in the file parsers 2026-08-02 19:00:14 +02:00
ChangeLog
Makefile.am rm ngnutmeg from build list of old apps 2026-02-03 14:22:29 +01:00
ciderinit
conf.c Updating links to ngspice web pages 2023-03-18 14:37:02 +01:00
conf.h unify #ifndef include wrapper 2013-12-31 12:54:32 +01:00
devaxis
devload
hist_info.c missing part of patch #56 2019-08-13 23:30:39 +02:00
hist_info.h missing part of patch #56 2019-08-13 23:30:39 +02:00
main.c Discard all XSPICE event data when using "-b -r", as there is no way 2026-04-01 07:35:20 +01:00
makeidx.c #1/4 #include <ngspice/...> --> #include "ngspice/..." 2011-12-11 18:05:00 +00:00
nghelp.c re-enable making the old help system for Linux/Cygwin 2021-07-08 15:34:41 +02:00
ngicon.rc adding the ngspice icon to the MINGW executable 2020-08-20 15:19:21 +02:00
ngmultidec.c use 'fabs()' 2016-10-15 15:06:17 +02:00
ngnutmeg.c cleanup, whitespace 2012-10-06 12:30:31 +02:00
ngproc2mod.c re-enable making old apps with --enable-oldapps 2020-03-15 08:51:16 +01:00
ngsconvert.c convert to lower case for spice2 input and remove few warnings 2026-02-03 14:22:37 +01:00
ngspice.c cleanup, whitespace 2012-10-06 12:30:31 +02:00
ngspice.ico adding the ngspice icon to the MINGW executable 2020-08-20 15:19:21 +02:00
ngspice.txt remove the ancient nobjthack option to fake 3-terminal bjt's 2016-11-01 11:56:48 +01:00
pkgIndex.tcl.in fix file modes 2012-06-12 21:26:29 +02:00
setplot
sharedspice.c newcompat.ki has already been set in sharedspice.c 2026-04-28 16:17:35 +02:00
spectrum
spice.def missing newline at end of file 2012-10-20 19:49:10 +02:00
spinit.in Add the non-nqs PSP103 OSDI model to spinit 2026-02-03 14:21:24 +01:00
tclspice.c Fix NULL dereference of getpwuid() result and missing tfree() 2026-04-21 20:00:46 +02:00
tclspice.map
tclspinit.in generate spinit and tclspinit at `make' time 2011-12-29 14:29:44 +00:00
winmain.c Just a small fix 2026-04-30 13:06:29 +02:00
winmain.h [PATCH #56] New history buffering 2019-08-13 23:30:05 +02:00