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.
This commit is contained in:
Holger Vogt 2025-07-21 17:49:28 +02:00
parent 0aa5c92a58
commit 33efc5ed2c
12 changed files with 190 additions and 38 deletions

View File

@ -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);

View File

@ -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 <math.h>
#include <complex.h>
#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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -215,9 +215,11 @@
<ClCompile Include="icm\tlines\msopen\msopen-cfunc.c" />
<ClCompile Include="icm\tlines\msopen\msopen-ifspec.c" />
<ClCompile Include="icm\tlines\tline\tline-cfunc.c">
<AdditionalIncludeDirectories>..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\src\xspice\icm\$(ProjectName);..\..\src\xspice\%(RelativeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="icm\tlines\tline\tline-ifspec.c" />
<ClCompile Include="..\..\src\xspice\icm\dlmain.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\xspice\icm\tlines\cpline\cfunc.mod" />