I made my quaternion realization and to test it I used boost. I test it in cycle and I always have errors in multiplication and division. Then I used Wolfram to find out who was wrong and I find out that boost was wrong.
I am not sure that the boost library was Wong, maybe some one can find out what is going on?
Console output example:
0
Operation : [ * ]
First vector = [ -41.4168 -92.2373 -33.0126 -42.2364 ]
Second vector = [ -67.8087 -60.3523 58.8705 36.3265 ]
My multiplication = [ 719.45 10041.3 5700.03 -6062.97 ]
Boost multiplication = [ 719.45 10041.3 10041.3 5700.03 ]
main.cpp
#include "quaternion.h"
#include <boost/math/quaternion.hpp>
#include <random>
#include <time.h>
#include <QDebug>
using boost::math::quaternion;
double fRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
bool isEqual(double a, double b){
return std::abs(a-b) < std::numeric_limits<double>::epsilon();
}
bool isEqual(Quaternion& quat1, quaternion<double> quat2){
if (!isEqual(quat2.R_component_1(), quat1.real)) return false;
if (!isEqual(quat2.R_component_2(), quat1.imagine.data.at(0))) return false;
if (!isEqual(quat2.R_component_3(), quat1.imagine.data.at(1))) return false;
if (!isEqual(quat2.R_component_4(), quat1.imagine.data.at(2))) return false;
return true;
}
int main () {
std::srand(std::time(nullptr));
Quaternion compR;
quaternion<double> boost;
double a1, a2, a3, a4,
b1, b2, b3, b4;
try {
for (unsigned int i=0; i<10000000; ++i){
a1 = fRand(-100, 100);
a2 = fRand(-100, 100);
a3 = fRand(-100, 100);
a4 = fRand(-100, 100);
b1 = fRand(-100, 100);
b2 = fRand(-100, 100);
b3 = fRand(-100, 100);
b4 = fRand(-100, 100);
Quaternion comp1{a1,a2,a3,a4};
Quaternion comp2{b1,b2,b3,b4};
quaternion<double> a(a1,a2,a3,a4);
quaternion<double> b(b1,b2,b3,b4);
//if (i%50000==0)
qDebug() << i;
compR = comp1+comp2;
boost = a+b;
if (!isEqual(compR, boost))
throw std::runtime_error("+");
compR = comp1-comp2;
boost = a-b;
if (!isEqual(compR, boost))
throw std::runtime_error("-");
compR = comp1*comp2;
boost = a*b;
if (!isEqual(compR, boost))
throw std::runtime_error("*");
compR = comp1/comp2;
boost = a/b;
if (!isEqual(compR, boost))
throw std::runtime_error("/");
}
} catch (const std::runtime_error& error) {
qDebug() << "Operation : [" << error.what() << "]";
qDebug() << " First vector = [" << a1 << " " << a2 << " " << " " << a3 << " " << a4 << "]\n" <<
"Second vector = [" << b1 << " " << b2 << " " << " " << b3 << " " << b4 << "]";
qDebug() << " My multiplication = [" << compR.real << " " << compR.imagine.data.at(0) << " " << compR.imagine.data.at(1)<< " " << compR.imagine.data.at(2) << "]\n" <<
"Boost multiplication = [" << boost.R_component_1() << " " << boost.R_component_2() << " " << boost.R_component_2() << " " << boost.R_component_3() << "]";
}
return 0;
}
Full project:https://github.com/Yegres5/quaternion
You have two issues:
you have a bug printing the boost quaternion (you print the index 2 twice)
use a larger epsilon. Using epsilon as it is can only be suitable, if your numbers around 1. Your result is around 10,000, so you need to use at least 10,000x larger epsilon. At this still may not be large enough, as quaternion multiplication uses several operations, each one can add some additional error. So, to be safe, multiply epsilon further by ~10 or so.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
I have a snippet of code that I don't manage to understand.
To give some context: I have a line (defined by its angular coefficient m) and I search over a set of segments to find the intersecting one. A segment and a vector of segments are defined as:
typedef std::pair<Eigen::Vector2d, Eigen::Vector2d> Vector2dPair;
typedef std::vector<Vector2dPair> Vector2dPairVector;
The mentioned code is (to provide a minimal working example):
#include <iostream>
#include <Eigen/Dense>
typedef std::vector<Eigen::Vector2d> Vector2dVector;
typedef std::pair<Eigen::Vector2d, Eigen::Vector2d> Vector2dPair;
typedef std::vector<Vector2dPair> Vector2dPairVector;
int main()
{
Vector2dPair segment;
segment.first = Eigen::Vector2d(2, -2);
segment.second = Eigen::Vector2d(2, 2);
Vector2dPairVector segments;
segments.push_back(segment);
double angle_min = 0;
double angle_max = M_PI_4;
double angle_increment = M_PI / 16.0;
double range_min = 0.0;
double range_max = 10.0;
Vector2dVector points;
double field_of_view = angle_max - angle_min;
int num_ranges = static_cast<int>(std::nearbyint(std::abs(field_of_view) / angle_increment));
std::cerr << "fov: " << field_of_view << std::endl;
std::cerr << "num ranges: " << num_ranges << std::endl;
points.resize(num_ranges);
for (int i = 0; i < num_ranges; ++i)
{
const double angle = angle_min + i * angle_increment;
std::cerr << "angle: " << angle << std::endl;
const double m = std::tan(angle);
Eigen::Vector2d point = Eigen::Vector2d::Zero();
bool found = false;
for (const auto& segment : segments)
{
// compute segment coefficients (a*x + b*y = c)
double a = segment.second.y() - segment.first.y();
double b = segment.first.x() - segment.second.x();
double c = a * segment.first.x() + b * segment.first.y();
// build A matrix and w vector to setup linear system of equation
Eigen::Matrix2d A;
A << -m, 1, a, b;
Eigen::Vector2d w;
w << 0, c;
// solve linear system to find point of intersection
Eigen::Vector2d p = A.colPivHouseholderQr().solve(w);
// check that the point lies inside the segment
double x_min = std::min(segment.first.x(), segment.second.x());
double x_max = std::max(segment.first.x(), segment.second.x());
double y_min = std::min(segment.first.y(), segment.second.y());
double y_max = std::max(segment.first.y(), segment.second.y());
// point is outside the segment
if (p.x() < x_min || p.x() > x_max || p.y() < y_min || p.y() > y_max)
{
std::cerr << "p: " << p.transpose() << std::endl;
std::cerr << "min: " << x_min << ", " << y_min << std::endl;
std::cerr << "max: " << x_max << ", " << y_max << std::endl;
std::cerr << (p.x() < x_min ? "true" : "false") << std::endl;
std::cerr << (p.x() > x_max ? "true" : "false") << std::endl;
std::cerr << (p.y() < y_min ? "true" : "false") << std::endl;
std::cerr << (p.y() > y_max ? "true" : "false") << std::endl;
continue;
}
std::cerr << "found" << std::endl;
found = true;
point = p;
break;
}
if (!found)
{
throw std::runtime_error("wtf!!");
}
std::cerr << std::endl;
}
return 0;
}
The weird thing is that at some point the final check is not behaving as expected. In particular, I get:
p: 2 0.828427
min: 2, -2
max: 2, 2
true
false
false
false
That is the check p.x() < x_min is true when p.x() = 2 and x_min = 2.
Can someone please tell me what is the problem?
Thanks.
I found the problem. As usual, the computer is right!!!
By doing:
std::cerr.precision(60);
I find that:
p: 1.999999999999999555910790149937383830547332763671875000000000 0.828427124746190735038453567540273070335388183593750000000000
min: 2.000000000000000000000000000000000000000000000000000000000000, -2.000000000000000000000000000000000000000000000000000000000000
max: 2.000000000000000000000000000000000000000000000000000000000000, 2.000000000000000000000000000000000000000000000000000000000000
true
false
false
false
terminate called after throwing an instance of 'std::runtime_error'
what(): wtf!!
I am trying to load freetype chars, stuff them into a texture as subimages and then render them instanced.
While most of it seems to work, right now I have a problem with storing the texture coordinates into a glm::mat2x4 matrix.
As can be seen below each character has a struct with information I right now deem necessary, including a matrix called face, which should store the texture coordinates.
But when it comes to assigning the coordinates, after leaving the loop in which it takes place, suddenly all the values go crazy, without any (wanted/ intended) operation taking place from my side.
After creating the texture atlas with freetype and putting all my structs into the map, I assign the width and height of my texture aw & ah to a storage class called c_atlas.
I calculate the texture coordinates in the loop shown below, make the glm::mat2x4 a 0.0f matrix and then stuff them into it. Couting them into the console gives the values I want.
After leaving the for loop I start another one, browsing over the matrix and cout them into the console, which gives me more or less random values in the range of e^-23 to e^32.
All of this happens in namespace foo and is called in a constructor of a class in the same namespace (sth. like this:)
foo::class::constructor()
{
call_function();
}
int main()
{
foo::class c;
c.call_function();
}
I crafted a minimum working example, but unfortunatly I am not able to replicate the error.
So I have the following loop running (a part of call_function():
namespace foo
{
namespace alphabet
{
const char path_arial[] = "res/font/consola.ttf";
class character
{
public:
glm::vec2 advance;
glm::vec2 bearing;
glm::vec2 size;
glm::vec2 offset;
glm::mat2x4 face;
};
std::map<char, character> char_map;
FT_Library m_ftlib;
FT_Face m_ftface;
GLuint m_VBO, m_VAO;
}
c_atlas ascii;
}
void foo::call_function()
{
//creating all the charactur structs with freetype and store them in the char_map
std::ofstream f("atlas_data.csv", std::ios::openmode::_S_app);
f << "letter;topleft.x;topleft.y;topright.x;topright.y;bottomright.x;bottomright.y;bottomleft.x;bottomleft.y" << std::endl;
for(auto c : alphabet::char_map)
{
std::cout << "b4: " << c.second.offset.x;
c.second.offset /= glm::vec2(aw,ah);
std::cout << "\nafter: " << c.second.offset.x << std::endl;
glm::vec2 ts = c.second.size/glm::vec2(aw,ah);
//couts the right values
uint16_t n = 0;
c.second.face = glm::mat2x4(0.0f);
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " at init:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//couts the right values
c.second.face[0][n++] = c.second.offset.x;
c.second.face[0][n++] = c.second.offset.y;
c.second.face[0][n++] = c.second.offset.x+ts.x;
c.second.face[0][n++] = c.second.offset.y;
n = 0;
c.second.face[1][n++]= c.second.offset.x+ts.x;
c.second.face[1][n++] = c.second.offset.y+ts.y;
c.second.face[1][n++] = c.second.offset.x;
c.second.face[1][n++]= c.second.offset.y+ts.y;
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " assigned:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//still couts the right values
f << (char)c.first << ";" << c.second.face[0].x << ";" << c.second.face[0].y << ";" << c.second.face[0].z << ";" << c.second.face[0].w << ";" << c.second.face[1].x << ";" << c.second.face[1].y << ";" << c.second.face[1].z << ";" << c.second.face[1].w << std::endl;
//the file also have the right values
}
f.close();
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//yet here all the values totally off track, i.e. e^32 or e^-23 (while they should all be between 0.01f - 1.0f)
for(auto i : alphabet::char_map)
{
std::cout << "\ntopleft:\n";
std::cout << "X: " << i.second.face[0].x << " | " << "Y: " << i.second.face[0].x;
std::cout << "\ntopright:\n";
std::cout << "X: " << i.second.face[0].z << " | " << "Y: " << i.second.face[0].w;
std::cout << "\nbotleft:\n";
std::cout << "X: " << i.second.face[1].x << " | " << "Y: " << i.second.face[1].x;
std::cout << "\nbotright:\n";
std::cout << "X: " << i.second.face[1].z << " | " << "Y: " << i.second.face[1].w;
}
}
my mwe:
#include <iostream>
#include <string>
#include "glm/glm.hpp"
#include "GL/gl.h"
#include <map>
struct bin
{
glm::mat2x4 mat;
};
int main( int argc, char *argv[] )
{
std::map<char, bin> bucket;
uint16_t r = 0;
for(uint16_t n = 0; n < 7; ++n)
{
glm::vec4 v = glm::vec4(0.12128f, 0.12412f, 0.15532f, 0.23453f);
bin b;
r = 0;
b.mat[0][r++] = v.x;
b.mat[0][r++] = v.y;
b.mat[0][r++] = v.z;
b.mat[0][r++] = v.w;
r = 0;
b.mat[1][r++] = v.x;
b.mat[1][r++] = v.y;
b.mat[1][r++] = v.z;
b.mat[1][r++] = v.w;
bucket[n] = b;
}
for(auto it : bucket)
{
r = 0;
std::cout << "0:\t" << it.second.mat[0][0] << "\t" << it.second.mat[0][1] << "\t" << it.second.mat[0][2] << "\t" << it.second.mat[0][3] << "\n";
r = 0;
std::cout << "1:\t" << it.second.mat[1][0] << "\t" << it.second.mat[1][1] << "\t" << it.second.mat[1][2] << "\t" << it.second.mat[1][3] << std::endl;
}
return 0;
}
Right now I am totally lost, especially as my mwe works fine.
I am clueless what goes wrong after leaving the for-loop, so thanks for any thought on that!
Indeed, I could just rewrite that section and hope it would work - as my mwe does. But I would like to find out/ get help on finding out what exactly happens between the "assign" for loop and the "retrieve" for loop. Any ideas on that?
I made it work for me now:
Appartenly assigning the values this way:
for(auto c : alphabet::char_map)
{
c.second.face[0][n++] = c.second.offset.x;
//and so on
}
Did not work properly (for whatever reason..)
Changing this into a for(uint16_t i = 32; i < 128; ++i) worked for me. Also it was just the assigning loop, the auto-iterating ofer the map elsewhere works just fine.
I'm using eigen3 package in c++ to do some linear algebra, but one part of the code which includes some matrix-matrix and matrix-vector multiplications takes too long. my matrices and vectors are pretty big (order 20kx20k) but some are sparse. what I read from eigen documentation, it is designed to be working efficiently with sparse matrices. I don't know what I'm doing wrong or how I can improve it. Would appreciate any help.
Here is part of the code; we have n input data for which we calculate 'k' from a function and for each point we need to find a 'mean' value defined in the code:
#pragma omp parallel for ordered schedule(dynamic)
for (unsigned long n = 0; n < nNew; n++) {
SparseVector<double> kJ(totalJ);
double k = something; #calculates using a function
for(int i=0; i<totalJ; i++) {
double covTmp = xxx; #calculates using a function
kJ.insert(i) = covTmp;
}
SparseVector<double> CJikJ(totalJ);
CJikJ = CJi * kJ;
double kJTCJikJ = kJ.transpose().dot(CJikJ);
double mu = 1. / (k - kJTCJikJ);
SparseVector<double> mJ(totalJ);
mJ= -mu * CJikJ;
SparseMatrix<double> MJi(totalJ, totalJ);
MJi = CJ - kJ*kJ.transpose()*mu / (1. + mu * kJTCJikJ);
SparseMatrix<double> VNGJMJiGJTi(nstars, nstars);
VNGJMJiGJTi = invertMatrix(VN + GJ * (MJi * GJT), nstars);
SparseMatrix<double> RJi(totalJ, totalJ);
RJi = MJi - MJi * GJT * (VNGJMJiGJTi) * (GJ * MJi); ## this line takes too long
RJi.prune(prunelim);
SparseVector<double> RJimJ;
RJimJ = RJi*mJ;
double alpha = mu - mJ.dot(RJimJ);
double beta = AN.dot((VNi * GJ) * RJimJ);
double mean = -beta / alpha;
outfile << setprecision(8) << newposm[n][0] << ", " << newposm[n][1] << ", " << newposm[n][2] << ", " << alpha << ", " << beta << ", " << mean << ", " << variance << "\n";
if(params.vb) {
cout << setprecision(8) << "# l, b, dist, alpha, beta, mean, var" << endl;
cout << setprecision(8) << newposm[n][0] << ", " << newposm[n][1] << ", " << newposm[n][2] << ", " << alpha << ", " << beta << ", " << mean << ", " << variance << "\n";
}
}
I've written a program that calculates values in a series and all of the values are particularly lengthy doubles. I want to print these values each displaying 15 significant figures. Here's some code that illustrates the issue I'm having:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
cout << setprecision(15) << fixed << x << "\t" << y << "\n";
return 0;
}
With just setprecision trailing zeros are not shown so I added fixed as I have seen in other answers on this site. However, now I just seem to have 15 decimal places and for values that aren't 0.something this is not what I want. You can see this from the output of the above:
0.123456789012346 1.123456789012346
The first number has 15 sig figs but the second has 16. What can I do to resolve this?
EDIT: I have been specifically asked to use setprecision, so I am unable to try cout.precision.
You can simply use scientific (note the 14 instead of 15):
std::cout << std::scientific << std::setprecision(14) << -0.123456789012345678 << std::endl;
std::cout << std::scientific << std::setprecision(14) << -1.234567890123456789 << std::endl;
-1.23456789012346e-01
-1.23456789012346e+00
or you can use a function:
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <sstream>
enum vis_opt { scientific, decimal, decimal_relaxed };
std::string figures(double x, int nfig, vis_opt vo=decimal) {
std::stringstream str;
str << std::setprecision(nfig-1) << std::scientific << x;
std::string s = str.str();
if ( vo == scientific )
return s;
else {
std::stringstream out;
std::size_t pos;
int ileft = std::stoi(s,&pos);
std::string dec = s.substr(pos + 1, nfig - 1);
int e = std::stoi(s.substr(pos + nfig + 1));
if ( e < 0 ) {
std::string zeroes(-1-e,'0');
if ( ileft < 0 )
out << "-0." << zeroes << -ileft << dec;
else
out << "0." << zeroes << ileft << dec;
} else if ( e == 0) {
out << ileft << '.' << dec;
} else if ( e < ( nfig - 1) ) {
out << ileft << dec.substr(0,e) << '.' << dec.substr(e);
} else if ( e == ( nfig - 1) ) {
out << ileft << dec;
} else {
if ( vo == decimal_relaxed) {
out << s;
} else {
out << ileft << dec << std::string(e - nfig + 1,'0');
}
}
return out.str();
}
}
int main() {
std::vector<double> test_cases = {
-123456789012345,
-12.34567890123456789,
-0.1234567890123456789,
-0.0001234,
0,
0.0001234,
0.1234567890123456789,
12.34567890123456789,
1.234567890123456789,
12345678901234,
123456789012345,
1234567890123456789.0,
};
for ( auto i : test_cases) {
std::cout << std::setw(22) << std::right << figures(i,15,scientific);
std::cout << std::setw(22) << std::right << figures(i,15) << std::endl;
}
return 0;
}
My output is:
-1.23456789012345e+14 -123456789012345
-1.23456789012346e+01 -12.3456789012346
-1.23456789012346e-01 -0.123456789012346
-1.23400000000000e-04 -0.000123400000000000
0.00000000000000e+00 0.00000000000000
1.23400000000000e-04 0.000123400000000000
1.23456789012346e-01 0.123456789012346
1.23456789012346e+01 12.3456789012346
1.23456789012346e+00 1.23456789012346
1.23456789012340e+13 12345678901234.0
1.23456789012345e+14 123456789012345
1.23456789012346e+18 1234567890123460000
I've found some success in just computing the integer significant figures, and then setting the floating significant figures to be X - <integer sig figs>:
Edit
To address Bob's comments, I'll account for more edge cases. I've refactored the code somewhat to adjust the field precision based on leading and trailing zeros. There would still be an edge case I believe for very small values (like std::numeric_limits<double>::epsilon:
int AdjustPrecision(int desiredPrecision, double _in)
{
// case of all zeros
if (_in == 0.0)
return desiredPrecision;
// handle leading zeros before decimal place
size_t truncated = static_cast<size_t>(_in);
while(truncated != 0)
{
truncated /= 10;
--desiredPrecision;
}
// handle trailing zeros after decimal place
_in *= 10;
while(static_cast<size_t>(_in) == 0)
{
_in *= 10;
++desiredPrecision;
}
return desiredPrecision;
}
With more tests:
double a = 0.000123456789012345;
double b = 123456789012345;
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
double z = 11.12345678901234567890;
std::cout.setf( std::ios::fixed, std:: ios::floatfield);
std::cout << "a: " << std::setprecision(AdjustPrecision(15, a)) << a << std::endl;
std::cout << "b: " << std::setprecision(AdjustPrecision(15, b)) << b << std::endl;
std::cout << "x " << std::setprecision(AdjustPrecision(15, x)) << x << std::endl;
std::cout << "y " << std::setprecision(AdjustPrecision(15, y)) << y << std::endl;
std::cout << "z: " << std::setprecision(AdjustPrecision(15, z)) << z << std::endl;
Output:
a: 0.000123456789012345
b: 123456789012345
x 0.123456789012346
y 1.12345678901235
z: 11.1234567890123
Live Demo
int GetIntegerSigFigs(double _in)
{
int toReturn = 0;
int truncated = static_cast<int>(_in);
while(truncated != 0)
{
truncated /= 10;
++toReturn;
}
return toReturn;
}
(I'm sure there are some edge cases I'm missing)
And then using it:
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
std::cout << td::setprecision(15-GetIntegerSigFigs(x)) << x
<< "\t" << std::setprecision(15-GetIntegerSigFigs(y)) << y << "\n";
Prints:
0.123456789012346 1.12345678901235
Live Demo
I have been searching on Google an in this forum for a while, but I could not find any answer or tip for my problem. Tutorials couldn't help me either...
I want to redistribute some points, stored in a vector p_org. (x-value is stored as double).
Therefore I have the function distribute, which is defined in maths.h
distribute_tanh(&p_org_temp,&p_new_temp,iz,spacing[0],spacing[1],l_rot[(kk+1)*iz-2],status);
The function distribute_tanh does look like this:
inline void distribute_tanh (std::vector<double> *p_org, std::vector<double> *p_new, const int n_points, double spacing_begin, double spacing_end, const double total_length, double status){
//if status == 0: FLAP, if status == 1: SLAT
std::cout << "spacing_begin: " << spacing_begin << " spacing_end: " << spacing_end << std::endl;
double s_begin = spacing_begin / total_length;
double s_end = spacing_end / total_length;
double A = sqrt(s_end/s_begin);
double B = 1 / (sqrt(s_end*s_begin)*n_points);
std::cout << "A: " << A << " B: " << B << std::endl;
std::vector<double> u (n_points);
std::vector<double> sn (n_points);
double dx;
double dy;
std::cout << "Control at the beginning: p_org: " << (p_org) << " p_new: " << (p_new) << " n_points: " << n_points << " s_begin: " << s_begin << " s_end: " << s_end << " total_length: " << total_length << std::endl;
//problem no. 1
for (int i=0;i<n_points;i++){
if (B > 1.001) {
if (B < 2.7829681) {
double Bq=B-1;
dy=sqrt(6*Bq)*(1-0.15*Bq+0.057321429*pow(Bq,2)-0.024907295*pow(Bq,3)+0.0077424461*pow(Bq,4)-0.0010794123*pow(Bq,5));
} else if (B > 2.7829681) {
double Bv=log(B);
double Bw=1/B-0.028527431;
dy=Bv+(1+1/Bv)*log(2*Bv)-0.02041793+0.24902722*Bw+1.9496443*pow(Bw,2)-2.6294547*pow(Bw,3)+8.56795911*pow(Bw,4);
}
u[i]=0.5+(tanh(dy*(i*(1.0/n_points)-0.5))/(2*tanh(dy/2)));
}
else if (B < 0.999) {
if (B < 0.26938972) {
dx=M_PI*(1-B+pow(B,2)-(1+(pow(M_PI,2))/6)*pow(B,3)+6.794732*pow(B,4)-13.205501*pow(B,5)+11.726095*pow(B,6));
} else if (B > 0.26938972) {
double Bq=1-B;
dx=sqrt(6*Bq)*(1+0.15*Bq+0.057321429*pow(Bq,2)+0.048774238*pow(Bq,3)-0.053337753*pow(Bq,4)+0.075845134*pow(Bq,5));
}
u[i]=0.5+(tan(dx*(i*(1.0/n_points)-0.5))/(2*tan(dx/2)));
}
else {
u[i]=i*(1.0/n_points)*(1+2*(B-1)*(i*(1.0/n_points)-0.5)*(1-i*(1.0/n_points)));
}
sn[i]=u[i]/(A+(1.0-A)*u[i]);
std::cout << "sn(i): " << sn[i] << std::endl;
std::cout << "p_org[n_points]: " << &p_org[n_points-1] << std::endl;
if(status==0){
//p_new[i]=p_org[0]+(total_length*sn[i]);
std::cout << "FLAP maths.h" << std::endl;
}
//Here is the problem no. 2
else if(status==1){
//p_new[i]=p_org[0]-(total_length*sn[i]);
std::cout << "SLAT maths.h" << std::endl;
}
//std::cout << "p_new in math: " << p_new << std::endl;
}
}
My problem is, that I am unable to access the value of p_org or p_new. At the beginning I would like to give out the value of p_org and p_new. If I try it with a *, the compiler is complaining: error: no operator "<<" matches these operands
operand types are: std::basic_ostream> << std::vector>
std::cout << "Control at the beginning: p_org: " << (*p_org) << " p_new: " << (*p_new) << " n_points: " << n_points << " s_begin: " << s_begin << " s_end: " << s_end << " total_length: " << total_length << std::endl;
If I leave the * off, I get the addresses of p_org and p_new.
At the end of the code I would like to write the new value to p_new. If I use * to access the value, the compiler is complaining, if I leave it off, its complaining too with the following message:
error: no operator "-" matches these operands
operand types are: std::vector<double, std::allocator<double>> - double
p_new[i]=p_org[0]-(total_length*sn[i]);
^
I tried to understand both problems, but until now I had no success.
Thanks for your advice.
Your issue with the compiler error can be cut down to a very simple program.
#include <vector>
void foo(std::vector<int>* pV)
{
pV[0] = 10; // error.
}
int main()
{
std::vector<int> v(10);
foo(&v);
}
The issue is that operator[] as done above works for objects and references, not pointers. Since pv is a pointer, you must dereference it first to obtain the object, and then apply [] to the dereferenced pointer.
void foo(std::vector<int>* pV)
{
(*pV)[0] = 10; // No error
}
The other form of calling operator[] can be also used, but is a bit more verbose:
void foo(std::vector<int>* pV)
{
pv->operator[](0) = 10; // No error
}
However, to alleviate having to do this, pass the vector by reference. Then the "normal" way of using operator[] can be used.
#include <vector>
void foo(std::vector<int>& pV)
{
pV[0] = 10; // No error.
}
int main()
{
std::vector<int> v(10);
foo(v);
}