From 33efc5ed2c4115dc3e492f5ee7fe85b6b6905308 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 21 Jul 2025 17:49:28 +0200 Subject: [PATCH] Add functions for VS non-C99-compatible complex data manipulation, selected by #ifdef _MSC_VER switch. Update tlines project file, correct buiuld sequence for code models in vngspice. Add tlines to spinit. --- src/xspice/icm/tlines/cpline/cfunc.mod | 62 +++++++++++++++++++++++--- src/xspice/icm/tlines/cpmlin/cfunc.mod | 29 ++++++------ src/xspice/icm/tlines/mlin/cfunc.mod | 45 ++++++++++++++++--- src/xspice/icm/tlines/msopen/cfunc.mod | 40 ++++++++++++++--- src/xspice/icm/tlines/tline/cfunc.mod | 38 ++++++++++++++-- visualc/spinit_all | 1 + visualc/spinitd | 1 + visualc/spinitd64 | 2 +- visualc/spinitr | 1 + visualc/spinitr64 | 2 +- visualc/vngspice.sln | 3 ++ visualc/xspice/tlines.vcxproj | 4 +- 12 files changed, 190 insertions(+), 38 deletions(-) diff --git a/src/xspice/icm/tlines/cpline/cfunc.mod b/src/xspice/icm/tlines/cpline/cfunc.mod index 7bde30526..c963ae9d0 100644 --- a/src/xspice/icm/tlines/cpline/cfunc.mod +++ b/src/xspice/icm/tlines/cpline/cfunc.mod @@ -1,5 +1,5 @@ /* =========================================================================== - FILE cfunc.mod + FILE cfunc.mod for cm_cpline Copyright 2025 Vadim Kuznetsov Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -23,13 +23,37 @@ #include "msline_common.h" #include "tline_common.h" +#ifdef _MSC_VER +typedef _Dcomplex DoubleComplex; // double complex +#else +typedef double complex DoubleComplex; +#endif -static void copy_complex(double complex s, Complex_t *d) +static void copy_complex(DoubleComplex s, Complex_t *d) { d->real = creal(s); d->imag = cimag(s); } +#ifdef _MSC_VER +static DoubleComplex divide(DoubleComplex n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1._Val[0] * n2._Val[0] + n1._Val[1] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1._Val[1] * n2._Val[0] - n1._Val[0] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } + +static DoubleComplex rdivide(double n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1 * n2._Val[0] + n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1 * n2._Val[0] - n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } +#endif + + //cpline_state_t *sim_points = NULL; static void cm_cpline_callback(ARGS, Mif_Callback_Reason_t reason); @@ -83,14 +107,42 @@ void cm_cpline (ARGS) else if(ANALYSIS == AC) { double o = RAD_FREQ; - double complex _Z11, _Z12, _Z13, _Z14; - double complex arg_e = log(ae)*l/2.0 + I*o*l/C0*sqrt(ere); - double complex arg_o = log(ao)*l/2.0 + I*o*l/C0*sqrt(ero); + DoubleComplex _Z11, _Z12, _Z13, _Z14; + +#ifdef _MSC_VER + double aen = log(ae)*l/2.0; + double ben = o*l/C0*sqrt(ere); + double aon = log(ao)*l/2.0; + double bon = o*l/C0*sqrt(ero); + DoubleComplex ge = _Cbuild(aen, ben); + DoubleComplex go = _Cbuild(aon, bon); + DoubleComplex tango = _Cmulcr(ctanh(_Cmulcr(go, l)), 2.); + DoubleComplex tange = _Cmulcr(ctanh(_Cmulcr(ge, l)), 2.); + DoubleComplex singo = _Cmulcr(csinh(_Cmulcr(go, l)), 2.); + DoubleComplex singe = _Cmulcr(csinh(_Cmulcr(ge, l)), 2.); + + DoubleComplex zotango = rdivide(zo, tango); + DoubleComplex zetange = rdivide(ze, tange); + DoubleComplex zosingo = rdivide(zo, singo); + DoubleComplex zesinge = rdivide(ze, singe); + + _Z11._Val[0] = zotango._Val[0] + zetange._Val[0]; + _Z11._Val[1] = zotango._Val[1] + zetange._Val[1]; + _Z12._Val[0] = zosingo._Val[0] + zesinge._Val[0]; + _Z12._Val[1] = zosingo._Val[1] + zesinge._Val[1]; + _Z13._Val[0] = zesinge._Val[0] - zosingo._Val[0]; + _Z13._Val[1] = zesinge._Val[1] - zosingo._Val[1]; + _Z14._Val[0] = zetange._Val[0] - zotango._Val[0]; + _Z14._Val[1] = zetange._Val[1] - zotango._Val[1]; +#else + DoubleComplex arg_e = log(ae)*l/2.0 + I*o*l/C0*sqrt(ere); + DoubleComplex arg_o = log(ao)*l/2.0 + I*o*l/C0*sqrt(ero); _Z11 = zo / (2*ctanh(arg_o)) + ze / (2*ctanh(arg_e)); _Z12 = zo / (2*csinh(arg_o)) + ze / (2*csinh(arg_e)); _Z13 = ze / (2*csinh(arg_e)) - zo / (2*csinh(arg_o)); _Z14 = ze / (2*ctanh(arg_e)) - zo / (2*ctanh(arg_o)); +#endif copy_complex(_Z11,&z11); copy_complex(_Z12,&z12); diff --git a/src/xspice/icm/tlines/cpmlin/cfunc.mod b/src/xspice/icm/tlines/cpmlin/cfunc.mod index 3899b6aab..24c1b8981 100644 --- a/src/xspice/icm/tlines/cpmlin/cfunc.mod +++ b/src/xspice/icm/tlines/cpmlin/cfunc.mod @@ -1,5 +1,5 @@ /* =========================================================================== - FILE cfunc.mod + FILE cfunc.mod for cm_cpmline Copyright 2025 Vadim Kuznetsov Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -20,11 +20,9 @@ #include #include - #include "msline_common.h" #include "tline_common.h" - #ifdef _MSC_VER typedef _Dcomplex DoubleComplex; // double complex #else @@ -456,20 +454,19 @@ void cm_cpmline (ARGS) DoubleComplex tange = _Cmulcr(ctanh(_Cmulcr(ge, l)), 2.); DoubleComplex singo = _Cmulcr(csinh(_Cmulcr(go, l)), 2.); DoubleComplex singe = _Cmulcr(csinh(_Cmulcr(ge, l)), 2.); - _Z11._Val[0] = (rdivide(zo, tango))._Val[0] + (rdivide(ze, tange))._Val[0]; - _Z11._Val[1] = (rdivide(zo, tango))._Val[1] + (rdivide(ze, tange))._Val[1]; - _Z12._Val[0] = (rdivide(zo, singo))._Val[0] + (rdivide(ze, singe))._Val[0]; - _Z12._Val[1] = (rdivide(zo, singo))._Val[1] + (rdivide(ze, singe))._Val[1]; - _Z13._Val[0] = (rdivide(ze, singe))._Val[0] - (rdivide(zo, singo))._Val[0]; - _Z13._Val[1] = (rdivide(ze, singe))._Val[1] - (rdivide(zo, singo))._Val[1]; - _Z14._Val[0] = (rdivide(ze, tange))._Val[0] - (rdivide(zo, tango))._Val[0]; - _Z14._Val[1] = (rdivide(ze, tange))._Val[1] - (rdivide(zo, tango))._Val[1]; + DoubleComplex zotango = rdivide(zo, tango); + DoubleComplex zetange = rdivide(ze, tange); + DoubleComplex zosingo = rdivide(zo, singo); + DoubleComplex zesinge = rdivide(ze, singe); -// _Z11._Val[0] = (rdivide(zo, _Cmulcr(ctanh(_Cmulcr(go, l)), 2.)))._Val[0] + (rdivide(ze, _Cmulcr(ctanh(_Cmulcr(ge, l)), 2.)))._Val[0]; -// _Z11._Val[1] = (rdivide(zo, _Cmulcr(ctanh(_Cmulcr(go, l)), 2.)))._Val[1] + (rdivide(ze, _Cmulcr(ctanh(_Cmulcr(ge, l)), 2.)))._Val[1]; -// _Z12 = zo / (2*csinh(go*l)) + ze / (2*csinh(ge*l)); -// _Z13 = ze / (2*csinh(ge*l)) - zo / (2*csinh(go*l)); -// _Z14 = ze / (2*ctanh(ge*l)) - zo / (2*ctanh(go*l)); + _Z11._Val[0] = zotango._Val[0] + zetange._Val[0]; + _Z11._Val[1] = zotango._Val[1] + zetange._Val[1]; + _Z12._Val[0] = zosingo._Val[0] + zesinge._Val[0]; + _Z12._Val[1] = zosingo._Val[1] + zesinge._Val[1]; + _Z13._Val[0] = zesinge._Val[0] - zosingo._Val[0]; + _Z13._Val[1] = zesinge._Val[1] - zosingo._Val[1]; + _Z14._Val[0] = zetange._Val[0] - zotango._Val[0]; + _Z14._Val[1] = zetange._Val[1] - zotango._Val[1]; #else DoubleComplex ge = ae + I*be; DoubleComplex go = ao + I*bo; diff --git a/src/xspice/icm/tlines/mlin/cfunc.mod b/src/xspice/icm/tlines/mlin/cfunc.mod index caa53d2fe..d0520a8cf 100644 --- a/src/xspice/icm/tlines/mlin/cfunc.mod +++ b/src/xspice/icm/tlines/mlin/cfunc.mod @@ -1,5 +1,5 @@ /* =========================================================================== - FILE cfunc.mod + FILE cfunc.mod for cm_mlin Copyright 2025 Vadim Kuznetsov Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -22,6 +22,32 @@ #include "msline_common.h" +#ifdef _MSC_VER +typedef _Dcomplex DoubleComplex; // double complex +#else +typedef double complex DoubleComplex; +#endif + +#ifdef _MSC_VER +static DoubleComplex divide(DoubleComplex n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1._Val[0] * n2._Val[0] + n1._Val[1] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1._Val[1] * n2._Val[0] - n1._Val[0] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } + +static DoubleComplex rdivide(double n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1 * n2._Val[0] + n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1 * n2._Val[0] - n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } +#endif + + + //static tline_state_t *sim_points = NULL; static double zl, alpha, beta, ereff; @@ -102,10 +128,19 @@ void cm_mlin (ARGS) else if(ANALYSIS == AC) { double frequency = RAD_FREQ/(2.0*M_PI); calcPropagation(W,SModel,DModel,er,h,t,tand,rho,D,frequency); - - double complex g = alpha + beta*I; - double complex _Z11 = zl / ctanh(g*l); - double complex _Z21 = zl / csinh(g*l); +#ifdef _MSC_VER + DoubleComplex g = _Cbuild(alpha, beta); + DoubleComplex _Z11 = rdivide(zl, ctanh(_Cmulcr(g, l))); + DoubleComplex _Z21 = rdivide(zl, csinh(_Cmulcr(g, l))); + z11.real = creal(_Z11); z11.imag = cimag(_Z11); + z21.real = creal(_Z21); z21.imag = cimag(_Z21); +#else + DoubleComplex g = alpha + beta*I; + DoubleComplex _Z11 = zl / ctanh(g*l); + DoubleComplex _Z21 = zl / csinh(g*l); + z11.real = creal(_Z11); z11.imag = cimag(_Z11); + z21.real = creal(_Z21); z21.imag = cimag(_Z21); +#endif z11.real = creal(_Z11); z11.imag = cimag(_Z11); z21.real = creal(_Z21); z21.imag = cimag(_Z21); diff --git a/src/xspice/icm/tlines/msopen/cfunc.mod b/src/xspice/icm/tlines/msopen/cfunc.mod index c07a36cb0..08fa954cb 100644 --- a/src/xspice/icm/tlines/msopen/cfunc.mod +++ b/src/xspice/icm/tlines/msopen/cfunc.mod @@ -1,5 +1,5 @@ /* =========================================================================== - FILE cfunc.mod + FILE cfunc.mod for cm_msopen Copyright 2025 Vadim Kuznetsov Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -23,6 +23,29 @@ #include "msline_common.h" #include "tline_common.h" +#ifdef _MSC_VER +typedef _Dcomplex DoubleComplex; // double complex +#else +typedef double complex DoubleComplex; +#endif + +#ifdef _MSC_VER +static DoubleComplex divide(DoubleComplex n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1._Val[0] * n2._Val[0] + n1._Val[1] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1._Val[1] * n2._Val[0] - n1._Val[0] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } + +static DoubleComplex rdivide(double n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1 * n2._Val[0] + n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1 * n2._Val[0] - n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } +#endif #define MSOPEN_KIRSCHNING 0 #define MSOPEN_HAMMERSTAD 1 @@ -102,10 +125,17 @@ void cm_msopen (ARGS) l2 = (0.008285 * tanh (0.5665 * W / h) + 0.0103) * h / 2.54e-5 / 25 * ZlEffFreq * 1e-9; r2 = (1.024 * tanh (2.025 * W / h)) * ZlEffFreq; - double complex d1 = 0 + I*c1 * RAD_FREQ; - double complex d2 = r2 + I*(l2 * RAD_FREQ - 1.0 / c2 / RAD_FREQ); - double complex y = d1 + 1.0/d2; - +#ifdef _MSC_VER + DoubleComplex d1 = _Cbuild(0, c1 * RAD_FREQ); + DoubleComplex d2 = _Cbuild(r2, (l2 * RAD_FREQ - 1.0 / c2 / RAD_FREQ)); + DoubleComplex y; + y._Val[0]= d1._Val[0] + (rdivide(1.0, d2))._Val[0]; + y._Val[1]= d1._Val[1] + (rdivide(1.0, d2))._Val[1]; +#else + DoubleComplex d1 = 0 + I*c1 * RAD_FREQ; + DoubleComplex d2 = r2 + I*(l2 * RAD_FREQ - 1.0 / c2 / RAD_FREQ); + DoubleComplex y = d1 + 1.0/d2; +#endif ac_gain.real = creal(y); ac_gain.imag = cimag(y); AC_GAIN(p1, p1) = ac_gain; diff --git a/src/xspice/icm/tlines/tline/cfunc.mod b/src/xspice/icm/tlines/tline/cfunc.mod index 207a0ee58..60a9b6a64 100644 --- a/src/xspice/icm/tlines/tline/cfunc.mod +++ b/src/xspice/icm/tlines/tline/cfunc.mod @@ -1,5 +1,5 @@ /* =========================================================================== - FILE cfunc.mod + FILE cfunc.mod for cm_tline Copyright 2025 Vadim Kuznetsov Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -21,6 +21,30 @@ #include "msline_common.h" #include "tline_common.h" +#ifdef _MSC_VER +typedef _Dcomplex DoubleComplex; // double complex +#else +typedef double complex DoubleComplex; +#endif + +#ifdef _MSC_VER +static DoubleComplex divide(DoubleComplex n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1._Val[0] * n2._Val[0] + n1._Val[1] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1._Val[1] * n2._Val[0] - n1._Val[0] * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } + +static DoubleComplex rdivide(double n1, DoubleComplex n2) + { + DoubleComplex rez; + rez._Val[0] = (n1 * n2._Val[0] + n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + rez._Val[1] = (n1 * n2._Val[0] - n1 * n2._Val[1]) / (n2._Val[0] * n2._Val[0] + n2._Val[1] * n2._Val[1]); + return rez; + } +#endif + //static tline_state_t *sim_points = NULL; static void cm_tline_callback(ARGS, Mif_Callback_Reason_t reason); @@ -61,9 +85,15 @@ void cm_tline (ARGS) } else if(ANALYSIS == AC) { double beta = RAD_FREQ/C0; - double complex g = alpha + beta*I; - double complex _Z11 = z / ctanh(g*l); - double complex _Z21 = z / csinh (g*l); +#ifdef _MSC_VER + DoubleComplex g = _Cbuild(alpha, beta); + DoubleComplex _Z11 = rdivide(z, ctanh(_Cmulcr(g, l))); + DoubleComplex _Z21 = rdivide(z, csinh(_Cmulcr(g, l))); +#else + DoubleComplex g = alpha + beta*I; + DoubleComplex _Z11 = z / ctanh(g*l); + DoubleComplex _Z21 = z / csinh (g*l); +#endif z11.real = creal(_Z11); z11.imag = cimag(_Z11); diff --git a/visualc/spinit_all b/visualc/spinit_all index 21bdae5ef..b2605b9cd 100644 --- a/visualc/spinit_all +++ b/visualc/spinit_all @@ -27,6 +27,7 @@ if $?xspice_enabled codemodel ../lib/ngspice/xtradev.cm codemodel ../lib/ngspice/xtraevt.cm codemodel ../lib/ngspice/table.cm + codemodel ../lib/ngspice/tlines.cm end diff --git a/visualc/spinitd b/visualc/spinitd index 7a8a1399a..9e2da93db 100644 --- a/visualc/spinitd +++ b/visualc/spinitd @@ -27,6 +27,7 @@ if $?xspice_enabled codemodel C:/Spiced/lib/ngspice/xtradev.cm codemodel C:/Spiced/lib/ngspice/xtraevt.cm codemodel C:/Spiced/lib/ngspice/table.cm + codemodel C:/Spiced/lib/ngspice/tlines.cm end diff --git a/visualc/spinitd64 b/visualc/spinitd64 index c7dc1dbec..d0f3983a8 100644 --- a/visualc/spinitd64 +++ b/visualc/spinitd64 @@ -27,7 +27,7 @@ if $?xspice_enabled codemodel C:/Spice64d/lib/ngspice/xtradev.cm codemodel C:/Spice64d/lib/ngspice/xtraevt.cm codemodel C:/Spice64d/lib/ngspice/table.cm - + codemodel C:/Spice64d/lib/ngspice/tlines.cm end diff --git a/visualc/spinitr b/visualc/spinitr index 31de1dc45..197cae611 100644 --- a/visualc/spinitr +++ b/visualc/spinitr @@ -27,6 +27,7 @@ if $?xspice_enabled codemodel C:/Spice/lib/ngspice/xtradev.cm codemodel C:/Spice/lib/ngspice/xtraevt.cm codemodel C:/Spice/lib/ngspice/table.cm + codemodel C:/Spice/lib/ngspice/tlines.cm end diff --git a/visualc/spinitr64 b/visualc/spinitr64 index 19cefe139..197330fe0 100644 --- a/visualc/spinitr64 +++ b/visualc/spinitr64 @@ -27,7 +27,7 @@ if $?xspice_enabled codemodel C:/Spice64/lib/ngspice/xtradev.cm codemodel C:/Spice64/lib/ngspice/xtraevt.cm codemodel C:/Spice64/lib/ngspice/table.cm - + codemodel C:/Spice64/lib/ngspice/tlines.cm end diff --git a/visualc/vngspice.sln b/visualc/vngspice.sln index abffca691..0dff55166 100644 --- a/visualc/vngspice.sln +++ b/visualc/vngspice.sln @@ -51,6 +51,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KLU_COMPLEX", "KLU\KLU_COMPLEX.vcxproj", "{B8DD41C5-70C6-4183-9018-C4B518E8D36A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tlines", "xspice\tlines.vcxproj", "{2F52507B-4C61-4B8D-8E32-E9DF5EFF527F}" + ProjectSection(ProjectDependencies) = postProject + {7C865696-FA10-43AE-A20B-22AE72A165E2} = {7C865696-FA10-43AE-A20B-22AE72A165E2} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/visualc/xspice/tlines.vcxproj b/visualc/xspice/tlines.vcxproj index ece6f40a5..9e36eb0e0 100644 --- a/visualc/xspice/tlines.vcxproj +++ b/visualc/xspice/tlines.vcxproj @@ -215,9 +215,11 @@ - ..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories) + ..\..\src\xspice\icm\$(ProjectName);..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories) + +