ehsan_faal
یک شنبه 01 شهریور 1394, 22:59 عصر
سلام دوستان.
بنده کدی به زبان متلب داشتم و بنا به دلایلی مجبورم توی ++C هم پیاده سازیش کنم.منتها از اون جایی که خیلی از توابعی که توی متلب بود رو خودم بایستی پیاده سازی کنم حجم کد خیلی زیاد میشه که برای جلوگیری از این حجم زیاد خواستم از template استفاده کنم که ظاهرا باید جزئیات زیادی رو ازش بدونم.
حالا من در آخرای کار هستم.یکبار کد رو به پایتون تبدیل کردم تا ریزه کاریهای مربوط به اندیس آرایه ها با ++C همخوانی داشته باشه.
حالا همون کد رو میخوام توی ++C بنویسم. برای نمونه این کد پایتون که پیچیده ترین قسمت کار من رو شامل میشه رو هنوز نتونستم توی ++C بیارمش:
def impedanceCreator(Ns,Ds,N):
Sections = int((N+1)/2)
oldABCD = np.zeros((2,2),dtype = np.ndarray)
oldABCD[0,0] = evenIndex(list(map(add,Ns,Ds)))[::-1]
oldABCD[0,1] = oddIndex(list(map(add,Ns,Ds)))[::-1]
oldABCD[1,0] = oddIndex(list(map(sub,Ds,Ns)))[::-1]
oldABCD[1,1] = evenIndex(list(map(sub,Ds,Ns)))[::-1]
Z = [0]*(Sections)
Z[0] = (polyval(1,oldABCD[0,0])/polyval(1,oldABCD[1,0])).real
tempMatrix = np.ones((2,2),dtype = np.ndarray)
newABCDmatrix = np.zeros((2,2),dtype = np.ndarray)
for index in range(1,Sections):
tempMatrix[0,1] = [0,-Z[index-1]]
tempMatrix[1,0] = [0,-1/Z[index-1]]
newABCDmatrix[0,0] = polydiv(polyadd(oldABCD[0,0],polymul(tempMatrix[0,1],oldABCD[1,0])),[1,0,-1])[0]
newABCDmatrix[0,1] = polydiv(polyadd(oldABCD[0,1],polymul(tempMatrix[0,1],oldABCD[1,1])),[1,0,-1])[0]
newABCDmatrix[1,0] = polydiv(polyadd(polymul(tempMatrix[1,0],oldABCD[0,0]),oldABCD[1,0]),[1,0,-1])[0]
newABCDmatrix[1,1] = polydiv(polyadd(polymul(tempMatrix[1,0],oldABCD[0,1]),oldABCD[1,1]),[1,0,-1])[0]
oldABCD[0,0] = newABCDmatrix[0,0]
oldABCD[0,1] = newABCDmatrix[0,1]
oldABCD[1,0] = newABCDmatrix[1,0]
oldABCD[1,1] = newABCDmatrix[1,1]
Z[index] = (polyval(1,newABCDmatrix[0,0])/polyval(1,newABCDmatrix[1,0])).real
return Z
کد معادلش تقریبا این میشه :
#include <iostream>
#include "armadillo"
using namespace std;
using namespace arma;
enum class state
:char {
EvenMode, OddMode
};
enum class ComplexOrOrdinary
:char {
ComplexNumber, OrdinaryNumber
};
enum class VectorType
:char {
ComplexType, OrdinaryType
};
template<typename T>
auto polyval(const T &input, const double& Target,
const VectorType& WhichType)->decltype(input(0)) {
//using filter algorithm from matlab:
const size_t top = input.size();
Col<decltype(input(0))> result(top);
if (WhichType == VectorType::ComplexType) {
result(0) = input(0);
for (size_t counter = 1; counter < top; counter++) {
result(counter) -= (-Target) * result(counter - 1);
result(counter) += input(counter);
}
} else if (WhichType == VectorType::OrdinaryType) {
result(0) = input(0);
for (size_t counter = 1; counter < top; counter++) {
result(counter) -= (-Target) * result(counter - 1);
result(counter) += input(counter);
}
}
return result(top - 1);
}
template<typename T>
auto getDegree(const T& polynomial, const ComplexOrOrdinary& Mood) ->int {
size_t degree { 0 };
if (Mood == ComplexOrOrdinary::OrdinaryNumber) {
degree = polynomial.n_elem - 1;
if (polynomial(degree).real() == 0) {
while (polynomial(degree).real() == 0) {
degree--;
}
}
} else if (Mood == ComplexOrOrdinary::ComplexNumber) {
degree = polynomial.n_elem - 1;
if (polynomial(degree).real() == 0) {
while (polynomial(degree).real() == 0) {
degree--;
}
}
}
return degree;
}
template<typename T>
auto shiftPolynomial(const T& input, const int& howMuch,
const VectorType& WhichType) ->T {
if (WhichType == VectorType::ComplexType) {
if (howMuch > 0) {
vector<complex<double>> tmp(input.n_elem);
for (size_t index = 0; index < howMuch; index++) {
tmp[index] = 0.0;
}
for (size_t index = howMuch; index < tmp.size(); index++) {
tmp[index] = input(index - howMuch);
}
return cx_vec { tmp };
} else {
return input;
}
} else if (WhichType == VectorType::OrdinaryType) {
if (howMuch > 0) {
vector<double> tmp(input.n_elem);
for (size_t index = 0; index < howMuch; index++) {
tmp[index] = 0.0;
}
for (size_t index = howMuch; index < tmp.size(); index++) {
tmp[index] = input(index - howMuch);
}
return vec { tmp };
} else {
return input;
}
}
}
//template<typename T1, typename T2>
//cx_vec polydiv(const T1& ON, const T2& OD, const VectorType& FirstType,
// const VectorType& SecondType) {
// if (FirstType == VectorType::ComplexType
// && SecondType == VectorType::OrdinaryType) {
//
// } else if (FirstType == VectorType::ComplexType
// && SecondType == VectorType::ComplexType) {
//
// } else if (FirstType == VectorType::OrdinaryType
// && SecondType == VectorType::OrdinaryType) {
//
// } else if (FirstType == VectorType::OrdinaryType
// && SecondType == VectorType::ComplexType) {
//
// }
//
//}
int main() {
cx_vec N { { 1, 2 }, { 3, 4 } };
cout << polyval(N, 2, VectorType::ComplexType) << endl;
return 0;
}
من از کتابخانه armadillo استفاده کردم. توی این کتابخانه بردار دابل با vec و بردار مختلط دابل با cx_vec شناخنه میشه.
سوال من اینجاست که چجوری میتونم توابعی که توی کد بالا هست رو جنریک بنویسم طوری که رو هر کدام از دو نوع معرفی درست کار کنه.البته کد ++C هنوز کامل نیست فقط اگه یه راهنمایی برای این مبحث template بدید بهم بقیه رو امیدوارم بتونم خودم جلو ببرم.
با تشکر
بنده کدی به زبان متلب داشتم و بنا به دلایلی مجبورم توی ++C هم پیاده سازیش کنم.منتها از اون جایی که خیلی از توابعی که توی متلب بود رو خودم بایستی پیاده سازی کنم حجم کد خیلی زیاد میشه که برای جلوگیری از این حجم زیاد خواستم از template استفاده کنم که ظاهرا باید جزئیات زیادی رو ازش بدونم.
حالا من در آخرای کار هستم.یکبار کد رو به پایتون تبدیل کردم تا ریزه کاریهای مربوط به اندیس آرایه ها با ++C همخوانی داشته باشه.
حالا همون کد رو میخوام توی ++C بنویسم. برای نمونه این کد پایتون که پیچیده ترین قسمت کار من رو شامل میشه رو هنوز نتونستم توی ++C بیارمش:
def impedanceCreator(Ns,Ds,N):
Sections = int((N+1)/2)
oldABCD = np.zeros((2,2),dtype = np.ndarray)
oldABCD[0,0] = evenIndex(list(map(add,Ns,Ds)))[::-1]
oldABCD[0,1] = oddIndex(list(map(add,Ns,Ds)))[::-1]
oldABCD[1,0] = oddIndex(list(map(sub,Ds,Ns)))[::-1]
oldABCD[1,1] = evenIndex(list(map(sub,Ds,Ns)))[::-1]
Z = [0]*(Sections)
Z[0] = (polyval(1,oldABCD[0,0])/polyval(1,oldABCD[1,0])).real
tempMatrix = np.ones((2,2),dtype = np.ndarray)
newABCDmatrix = np.zeros((2,2),dtype = np.ndarray)
for index in range(1,Sections):
tempMatrix[0,1] = [0,-Z[index-1]]
tempMatrix[1,0] = [0,-1/Z[index-1]]
newABCDmatrix[0,0] = polydiv(polyadd(oldABCD[0,0],polymul(tempMatrix[0,1],oldABCD[1,0])),[1,0,-1])[0]
newABCDmatrix[0,1] = polydiv(polyadd(oldABCD[0,1],polymul(tempMatrix[0,1],oldABCD[1,1])),[1,0,-1])[0]
newABCDmatrix[1,0] = polydiv(polyadd(polymul(tempMatrix[1,0],oldABCD[0,0]),oldABCD[1,0]),[1,0,-1])[0]
newABCDmatrix[1,1] = polydiv(polyadd(polymul(tempMatrix[1,0],oldABCD[0,1]),oldABCD[1,1]),[1,0,-1])[0]
oldABCD[0,0] = newABCDmatrix[0,0]
oldABCD[0,1] = newABCDmatrix[0,1]
oldABCD[1,0] = newABCDmatrix[1,0]
oldABCD[1,1] = newABCDmatrix[1,1]
Z[index] = (polyval(1,newABCDmatrix[0,0])/polyval(1,newABCDmatrix[1,0])).real
return Z
کد معادلش تقریبا این میشه :
#include <iostream>
#include "armadillo"
using namespace std;
using namespace arma;
enum class state
:char {
EvenMode, OddMode
};
enum class ComplexOrOrdinary
:char {
ComplexNumber, OrdinaryNumber
};
enum class VectorType
:char {
ComplexType, OrdinaryType
};
template<typename T>
auto polyval(const T &input, const double& Target,
const VectorType& WhichType)->decltype(input(0)) {
//using filter algorithm from matlab:
const size_t top = input.size();
Col<decltype(input(0))> result(top);
if (WhichType == VectorType::ComplexType) {
result(0) = input(0);
for (size_t counter = 1; counter < top; counter++) {
result(counter) -= (-Target) * result(counter - 1);
result(counter) += input(counter);
}
} else if (WhichType == VectorType::OrdinaryType) {
result(0) = input(0);
for (size_t counter = 1; counter < top; counter++) {
result(counter) -= (-Target) * result(counter - 1);
result(counter) += input(counter);
}
}
return result(top - 1);
}
template<typename T>
auto getDegree(const T& polynomial, const ComplexOrOrdinary& Mood) ->int {
size_t degree { 0 };
if (Mood == ComplexOrOrdinary::OrdinaryNumber) {
degree = polynomial.n_elem - 1;
if (polynomial(degree).real() == 0) {
while (polynomial(degree).real() == 0) {
degree--;
}
}
} else if (Mood == ComplexOrOrdinary::ComplexNumber) {
degree = polynomial.n_elem - 1;
if (polynomial(degree).real() == 0) {
while (polynomial(degree).real() == 0) {
degree--;
}
}
}
return degree;
}
template<typename T>
auto shiftPolynomial(const T& input, const int& howMuch,
const VectorType& WhichType) ->T {
if (WhichType == VectorType::ComplexType) {
if (howMuch > 0) {
vector<complex<double>> tmp(input.n_elem);
for (size_t index = 0; index < howMuch; index++) {
tmp[index] = 0.0;
}
for (size_t index = howMuch; index < tmp.size(); index++) {
tmp[index] = input(index - howMuch);
}
return cx_vec { tmp };
} else {
return input;
}
} else if (WhichType == VectorType::OrdinaryType) {
if (howMuch > 0) {
vector<double> tmp(input.n_elem);
for (size_t index = 0; index < howMuch; index++) {
tmp[index] = 0.0;
}
for (size_t index = howMuch; index < tmp.size(); index++) {
tmp[index] = input(index - howMuch);
}
return vec { tmp };
} else {
return input;
}
}
}
//template<typename T1, typename T2>
//cx_vec polydiv(const T1& ON, const T2& OD, const VectorType& FirstType,
// const VectorType& SecondType) {
// if (FirstType == VectorType::ComplexType
// && SecondType == VectorType::OrdinaryType) {
//
// } else if (FirstType == VectorType::ComplexType
// && SecondType == VectorType::ComplexType) {
//
// } else if (FirstType == VectorType::OrdinaryType
// && SecondType == VectorType::OrdinaryType) {
//
// } else if (FirstType == VectorType::OrdinaryType
// && SecondType == VectorType::ComplexType) {
//
// }
//
//}
int main() {
cx_vec N { { 1, 2 }, { 3, 4 } };
cout << polyval(N, 2, VectorType::ComplexType) << endl;
return 0;
}
من از کتابخانه armadillo استفاده کردم. توی این کتابخانه بردار دابل با vec و بردار مختلط دابل با cx_vec شناخنه میشه.
سوال من اینجاست که چجوری میتونم توابعی که توی کد بالا هست رو جنریک بنویسم طوری که رو هر کدام از دو نوع معرفی درست کار کنه.البته کد ++C هنوز کامل نیست فقط اگه یه راهنمایی برای این مبحث template بدید بهم بقیه رو امیدوارم بتونم خودم جلو ببرم.
با تشکر