Hi,
I have written a C++ program, very small, under Windows.
Normally I work under Linux, but I had to use a Windows machine over the
weekend.
The program does not use anything special, only
#include <iostream>
#include <stdlib.h>
#include "math.h"
I have copied the .cpp files from my Windows machine to my Linux machine
now.
Compiling with g++ 3.3.2-r5 under Gentoo works fine, but when I execute, the
results I get are just wrong, totally wrong. So this is nothing due to
rounding or so, there is no slight difference, it is just totally wrong.
I am not a C++ guru since I usually code in other languages.
What can be the reason for that ?
Since it is few lines of code only (< 200 lines) I can also post it if that
helps...
Thanks ! 9 1484
"Alex Neumann" <no***@here.de> wrote in message
news:2k***********@uni-berlin.de... Since it is few lines of code only (< 200 lines) I can also post it if
that helps...
You'll have to post *something*, at least! Are we supposed to guess what
the problem is? We don't even know what the correct or incorrect results
are. (To be just a "wee" bit facetious: does it fly around the room singing
"Mammy", instead of sorting your fruits into apples and oranges? :-))
More seriously, if you could at least post the relevant parts of your code,
along with an explanation about what is expected and what it actually seen,
that would help us (and you).
-Howard
Howard wrote: "Alex Neumann" <no***@here.de> wrote in message news:2k***********@uni-berlin.de...
Since it is few lines of code only (< 200 lines) I can also post it if that helps...
You'll have to post *something*, at least! Are we supposed to guess what the problem is? We don't even know what the correct or incorrect results are. (To be just a "wee" bit facetious: does it fly around the room singing "Mammy", instead of sorting your fruits into apples and oranges? :-))
More seriously, if you could at least post the relevant parts of your code, along with an explanation about what is expected and what it actually seen, that would help us (and you).
-Howard
Ok... here the code first:
---
FILE 1: porcupine.cpp
---
#include <iostream>
#include <stdlib.h>
#include "math.h"
#include "point2D.h"
using namespace std;
// Helper to calculate the normal vector
Point2D norm_vector(Point2D point)
{
return Point2D(-point.y, point.x);
}
// Helper to calculate the norm
float norm(Point2D point)
{
return sqrt( pow(point.x, 2) + pow(point.y, 2) );
}
// Helper to calculate the vectorproduct
float vectorproduct(Point2D point_a, Point2D point_b)
{
return point_a.x * point_b.y - point_a.y * point_b.x;
}
// Helper to calculate the faculty
int faculty(int n)
{
int faculty = 1;
for(n; n>0; n--)
{
faculty = faculty * n;
}
return faculty;
}
// Helper to calculate the binomial
float binomial(int n, int i)
{
return faculty(n) / (faculty(i) * faculty(n-i));
}
// Helper to calculate Bernstein
float bernstein(float t, int n, int i)
{
return binomial(n,i) * pow(t,i) * pow( (1.0-t), (n-i) );
}
// Helper to calculate Bezier
Point2D bezier(float t, int n, Point2D points[])
{
Point2D result;
int i = 0;
for(i; i<=n; i++)
{
result.x += bernstein(t,n,i) * points[i].x;
result.y += bernstein(t,n,i) * points[i].y;
}
return result;
}
// Helper to calculate the 1st derivative of a Bezier curve
Point2D bezier_first_derivative(float t, int n, Point2D points[])
{
Point2D result;
int intervallborder_s = 0;
int intervallborder_t = 1;
int i = 0;
for(i; i<=n-1; i++)
{
result.x += bernstein(t,n-1,i) * (points[i+1].x - points[i].x);
result.y += bernstein(t,n-1,i) * (points[i+1].y - points[i].y);
}
result.x = result.x * (n / (intervallborder_t - intervallborder_s));
result.y = result.y * (n / (intervallborder_t - intervallborder_s));
return result;
}
// Helper to calculate the 1st derivative of a Bezier curve
Point2D bezier_second_derivative(float t, int n, Point2D points[])
{
Point2D result;
int intervallborder_s = 0;
int intervallborder_t = 1;
int i = 0;
for(i; i<=n-2; i++)
{
result.x += bernstein(t,n-2,i) * (points[i+2].x - 2*points[i+1].x +
points[i].x);
result.y += bernstein(t,n-2,i) * (points[i+2].y - 2*points[i+1].y +
points[i].y);
}
result.x = result.x * ( n*(n-1.0) / pow( (double)(intervallborder_t -
intervallborder_s), 2) );
result.y = result.y * ( n*(n-1.0) / pow( (double)(intervallborder_t -
intervallborder_s), 2) );
return result;
}
// Calculate curvature
float curvature(float t, int n, Point2D points[])
{
Point2D bsd = bezier_second_derivative(t,n,points);
Point2D bfd = bezier_first_derivative(t,n,points);
float vp = vectorproduct(bsd, bfd);
float n_bfd = norm(bfd);
return vp / pow(n_bfd, 3);
}
// Calculate curvature vector
Point2D curvature_vector(float t, int n, Point2D points[])
{
Point2D bfd = bezier_first_derivative(t,n,points);
// Calculate normal vector
Point2D norm_bfd = norm_vector(bfd);
// Multiply with curvature
float c = curvature(t,n,points);
Point2D result = Point2D(norm_bfd.x * c, norm_bfd.y * c);
return result;
}
// Main
int main(int argc, char *argv[])
{
// Read the value specifying the degree
int n = atoi(argv[1]);
// Read the corresponding Bezier points
Point2D points[n];
int j = 0;
for (int i=2; i<(2*(n+1))+2; i+=2)
{
points[j] = Point2D(atof(argv[i]), atof(argv[i+1]));
j += 1;
}
// Set a start value for t
float t = 0.0;
// Iterate and print the p_i's and the corresponding curvature values
for (int k=0; k<=20; k++)
{
Point2D pi = bezier(t, n, points);
//Point2D pi = curvature_vector(t, n, points);
//cout << curvature(t,n,points) << endl;
cout << pi.x << "\t\t" << pi.y << endl;
t = t + 0.05;
}
return 0;
}
---
File 2: point2d.h
---
class Point2D
{
public:
float x;
float y;
Point2D();
Point2D(float x, float y);
};
Point2D::Point2D()
{
this->x=0;
this->y=0;
}
Point2D::Point2D(float x, float y)
{
this->x=x;
this->y=y;
}
This is what I get:
bash-2.05b# ./porcupine 2 0 0 1 1 2 1
13073.4 9.21956e-41
11798.7 8.32063e-41
10589.4 7.4678e-41
9445.51 6.66107e-41
8366.96 5.90059e-41
7353.77 5.18607e-41
6405.95 4.51765e-41
5523.5 3.89533e-41
4706.41 3.31898e-41
3954.7 2.78886e-41
3268.34 2.30486e-41
2647.36 1.86695e-41
2091.74 1.47515e-41
1601.49 1.12945e-41
1176.6 8.29709e-42
817.085 5.76354e-42
522.934 3.68962e-42
294.15 2.07532e-42
130.733 9.23456e-43
32.6832 2.31214e-43
1.85784e-10 1.4013e-45
And this is what is expected (and what I get under windows):
(-0.353553, 0.353553)
(-0.362023, 0.381077)
(-0.369594, 0.41066)
(-0.375993, 0.442345)
(-0.380912, 0.47614)
(-0.384, 0.512)
(-0.384874, 0.54982)
(-0.38312, 0.589416)
(-0.378306, 0.63051)
(-0.369995, 0.672719)
(-0.357771, 0.715542)
(-0.34126, 0.758355)
(-0.320164, 0.800411)
(-0.294299, 0.840854)
(-0.263622, 0.87874)
(-0.228269, 0.913075)
(-0.188573, 0.942866)
(-0.145076, 0.967175)
(-0.0985185, 0.985185)
(-0.0498131, 0.996262)***
(-0, 1)
Any suggestions ?
Thanks.
Alex Neumann wrote: Howard wrote:
"Alex Neumann" <no***@here.de> wrote in message news:2k***********@uni-berlin.de...
Since it is few lines of code only (< 200 lines) I can also post it if that helps...
You'll have to post *something*, at least! Are we supposed to guess what the problem is? We don't even know what the correct or incorrect results are. (To be just a "wee" bit facetious: does it fly around the room singing "Mammy", instead of sorting your fruits into apples and oranges? :-))
More seriously, if you could at least post the relevant parts of your code, along with an explanation about what is expected and what it actually seen, that would help us (and you).
-Howard
Ok... here the code first:
--- FILE 1: porcupine.cpp --- #include <iostream> #include <stdlib.h> #include "math.h" #include "point2D.h"
using namespace std;
// Helper to calculate the normal vector Point2D norm_vector(Point2D point) { return Point2D(-point.y, point.x); }
// Helper to calculate the norm float norm(Point2D point) { return sqrt( pow(point.x, 2) + pow(point.y, 2) ); }
// Helper to calculate the vectorproduct float vectorproduct(Point2D point_a, Point2D point_b) { return point_a.x * point_b.y - point_a.y * point_b.x; }
// Helper to calculate the faculty int faculty(int n) { int faculty = 1;
for(n; n>0; n--) { faculty = faculty * n; }
return faculty; }
// Helper to calculate the binomial float binomial(int n, int i) { return faculty(n) / (faculty(i) * faculty(n-i)); }
// Helper to calculate Bernstein float bernstein(float t, int n, int i) { return binomial(n,i) * pow(t,i) * pow( (1.0-t), (n-i) ); }
// Helper to calculate Bezier Point2D bezier(float t, int n, Point2D points[]) { Point2D result; int i = 0;
for(i; i<=n; i++) { result.x += bernstein(t,n,i) * points[i].x; result.y += bernstein(t,n,i) * points[i].y; }
return result; }
// Helper to calculate the 1st derivative of a Bezier curve Point2D bezier_first_derivative(float t, int n, Point2D points[]) { Point2D result; int intervallborder_s = 0; int intervallborder_t = 1; int i = 0;
for(i; i<=n-1; i++) { result.x += bernstein(t,n-1,i) * (points[i+1].x - points[i].x); result.y += bernstein(t,n-1,i) * (points[i+1].y - points[i].y); }
result.x = result.x * (n / (intervallborder_t - intervallborder_s)); result.y = result.y * (n / (intervallborder_t - intervallborder_s));
return result; }
// Helper to calculate the 1st derivative of a Bezier curve Point2D bezier_second_derivative(float t, int n, Point2D points[]) { Point2D result; int intervallborder_s = 0; int intervallborder_t = 1; int i = 0;
for(i; i<=n-2; i++) { result.x += bernstein(t,n-2,i) * (points[i+2].x - 2*points[i+1].x + points[i].x); result.y += bernstein(t,n-2,i) * (points[i+2].y - 2*points[i+1].y + points[i].y); }
result.x = result.x * ( n*(n-1.0) / pow( (double)(intervallborder_t - intervallborder_s), 2) ); result.y = result.y * ( n*(n-1.0) / pow( (double)(intervallborder_t - intervallborder_s), 2) );
return result; }
// Calculate curvature float curvature(float t, int n, Point2D points[]) { Point2D bsd = bezier_second_derivative(t,n,points); Point2D bfd = bezier_first_derivative(t,n,points);
float vp = vectorproduct(bsd, bfd); float n_bfd = norm(bfd);
return vp / pow(n_bfd, 3); }
// Calculate curvature vector Point2D curvature_vector(float t, int n, Point2D points[]) { Point2D bfd = bezier_first_derivative(t,n,points);
// Calculate normal vector Point2D norm_bfd = norm_vector(bfd);
// Multiply with curvature float c = curvature(t,n,points);
Point2D result = Point2D(norm_bfd.x * c, norm_bfd.y * c);
return result; }
// Main int main(int argc, char *argv[]) { // Read the value specifying the degree int n = atoi(argv[1]);
// Read the corresponding Bezier points Point2D points[n]; int j = 0;
for (int i=2; i<(2*(n+1))+2; i+=2) { points[j] = Point2D(atof(argv[i]), atof(argv[i+1])); j += 1; }
// Set a start value for t float t = 0.0;
// Iterate and print the p_i's and the corresponding curvature values for (int k=0; k<=20; k++) { Point2D pi = bezier(t, n, points); //Point2D pi = curvature_vector(t, n, points); //cout << curvature(t,n,points) << endl; cout << pi.x << "\t\t" << pi.y << endl; t = t + 0.05; }
return 0; } --- File 2: point2d.h --- class Point2D { public: float x; float y;
Point2D(); Point2D(float x, float y); };
Point2D::Point2D() { this->x=0; this->y=0; }
Point2D::Point2D(float x, float y) { this->x=x; this->y=y; } This is what I get:
bash-2.05b# ./porcupine 2 0 0 1 1 2 1 13073.4 9.21956e-41 11798.7 8.32063e-41 10589.4 7.4678e-41 9445.51 6.66107e-41 8366.96 5.90059e-41 7353.77 5.18607e-41 6405.95 4.51765e-41 5523.5 3.89533e-41 4706.41 3.31898e-41 3954.7 2.78886e-41 3268.34 2.30486e-41 2647.36 1.86695e-41 2091.74 1.47515e-41 1601.49 1.12945e-41 1176.6 8.29709e-42 817.085 5.76354e-42 522.934 3.68962e-42 294.15 2.07532e-42 130.733 9.23456e-43 32.6832 2.31214e-43 1.85784e-10 1.4013e-45
And this is what is expected (and what I get under windows):
Sorry, correction: This is expected:
(0, 0)
(0.1, 0.0975)
(0.2, 0.19)
(0.3, 0.2775)
(0.4, 0.36)
(0.5, 0.4375)
(0.6, 0.51)
(0.7, 0.5775)
(0.8, 0.64)
(0.9, 0.6975)
(1, 0.75)
(1.1, 0.7975)
(1.2, 0.84)
(1.3, 0.8775)
(1.4, 0.91)
(1.5, 0.9375)
(1.6, 0.96)
(1.7, 0.9775)
(1.8, 0.99)
(1.9, 0.9975)
(2, 1)
"Alex Neumann" <no***@here.de> wrote in message
news:2k***********@uni-berlin.de... Howard wrote:
// Main int main(int argc, char *argv[]) { // Read the value specifying the degree int n = atoi(argv[1]);
// Read the corresponding Bezier points Point2D points[n]; int j = 0;
for (int i=2; i<(2*(n+1))+2; i+=2) { points[j] = Point2D(atof(argv[i]), atof(argv[i+1])); j += 1; }
Without looking at the rest of your code carefully, I see a couple problems
right off.
Does this even compile? You're declaring an array (Point2D) of size n, but
n is a run-time variable. Arrays can only be declared in this manner with a
constant expression, not a variable. I get a compile error if I try to
compile code like that. You need to use a dynamic array if you want to
declare an array size based on a variable.
Also, even if you *had* used a dynamic array (with something like "Point2D*
points = new Point2D[n];"), then you've still got a problem, in that you're
creating three points, but n is 2, so your array only holds 2 points. So,
your code will write past the end of the array, causing undefined behavior.
Anything could happen after that. Your array needs to be of size n+1.
(I haven't looked any further, because these problems make the program
incorrect already.)
-Howard
"Alex Neumann" <no***@here.de> wrote in message
news:2k***********@uni-berlin.de... Hi,
I have written a C++ program, very small, under Windows. Normally I work under Linux, but I had to use a Windows machine over the weekend. The program does not use anything special, only
#include <iostream> #include <stdlib.h> #include "math.h"
I have copied the .cpp files from my Windows machine to my Linux machine now. Compiling with g++ 3.3.2-r5 under Gentoo works fine, but when I execute,
the results I get are just wrong, totally wrong. So this is nothing due to rounding or so, there is no slight difference, it is just totally wrong.
I am not a C++ guru since I usually code in other languages.
What can be the reason for that ?
Undefined behaviour.
Programs which break the rules of C++ often result in what the C++ standard
calls undefined behaviour. When a program has undefined behaviour it can do
anything. It can work fine on one machine and fail on another, it can work
fine when you run it for your boss, but fail when you run it for a customer,
anything.
Now how you've broken the rules of C++ is another question, but if you are
not an experienced C++ programmer it is very easy to do.
john
"Alex Neumann" <no***@here.de> wrote in message
news:2k***********@uni-berlin.de... Ok... here the code first:
Some comments and explanations as I skim through...
FILE 1: porcupine.cpp --- #include <iostream> #include <stdlib.h> #include "math.h"
In C++, using stdlib.h or math.h is non standard.
For portability, replace this with:
#include <cstdlib>
#include <cmath>
= proper C++, plus will declare all functions in namespace std
// Helper to calculate the faculty int faculty(int n)
ok... I call this factorial... will do.
// Helper to calculate the binomial float binomial(int n, int i) { return faculty(n) / (faculty(i) * faculty(n-i));
NB: this approach will overflow int very quickly.
faculty(>=13) will overflow on a 32-bit platform.
I'm not sure this is what causes the problem you observe, as I won't go
through your algorithms...
(I suggest you post on comp.graphics for this...)
// Main int main(int argc, char *argv[]) { // Read the value specifying the degree int n = atoi(argv[1]);
// Read the corresponding Bezier points Point2D points[n];
Declaring an array of a run-time-specified size (n is not a compile-time
constant) is not supported in standard C++.
Some C++ compilers support it as an extension (because it is now allowed in
C).
The portable and safer way to do the same is:
#include <vector>
....
std::vector<Point2D> points(n);
That's it for what I can say from the C++ side...
hth - Ivan
-- http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com
"Ivan Vecerina" <NO**********************************@vecerina.com > wrote in
message news:cb**********@newshispeed.ch... "Alex Neumann" <no***@here.de> wrote in message news:2k***********@uni-berlin.de... Ok... here the code first: Some comments and explanations as I skim through...
FILE 1: porcupine.cpp --- #include <iostream> #include <stdlib.h> #include "math.h" In C++, using stdlib.h or math.h is non standard.
Nope. The only nonstandard thing here is writing "math.h"
instead of <math.h>.
For portability, replace this with: #include <cstdlib> #include <cmath>
= proper C++, plus will declare all functions in namespace std
Yes, these headers do declare (most) C names in namespace std,
which can be helpful. But there's more than one flavor of
"proper C++".
P.J. Plauger
Dinkumware, Ltd. http://www.dinkumware.com
"P.J. Plauger" <pj*@dinkumware.com> wrote in message
news:jI******************@nwrddc03.gnilink.net... "Ivan Vecerina" <NO**********************************@vecerina.com > wrote
in message news:cb**********@newshispeed.ch...
.... #include "math.h" In C++, using stdlib.h or math.h is non standard.
Nope. The only nonstandard thing here is writing "math.h" instead of <math.h>.
I trust what you say. Could you point me to where the C++
standard guarantee the availability of C headers?
Is it unconceivable/illegal for a C++ platform to not be
providing the C-named headers in the default include path?
Plus what is a user supposed to expect in terms of the
presence or absence of overloads defined in C++? = proper C++, plus will declare all functions in namespace std
Yes, these headers do declare (most) C names in namespace std, which can be helpful. But there's more than one flavor of "proper C++".
My instinct when writing standard-compliant C++ code
has been to use the headers as I saw them defined in the
C++ standard. As of today, I thought this offers a relatively
good guarantee of portability, and is the practice to encourage.
Though I will be happy if the C and C++ standards are
kept on a converging path...
Best regards,
Ivan
-- http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Ivan Vecerina wrote: I trust what you say. Could you point me to where the C++ standard guarantee the availability of C headers?
17.4.1.2 p3-end
and
Annex D - D.5
Is it unconceivable/illegal for a C++ platform to not be providing the C-named headers in the default include path?
yes. they must be there.
Plus what is a user supposed to expect in terms of the presence or absence of overloads defined in C++?
it is specified that all macros remain macros, regardless of whether or
not they can be "improved" via inline functions, constants or templates.
i believe (off the top of my head) that overloads are added for many of
the math functions, allowing double, float or long(?) to be used
transparently. check in <cmath> and <cstdlib>. i can't recall any others. = proper C++, plus will declare all functions in namespace std
Yes, these headers do declare (most) C names in namespace std, which can be helpful. But there's more than one flavor of "proper C++".
My instinct when writing standard-compliant C++ code has been to use the headers as I saw them defined in the C++ standard. As of today, I thought this offers a relatively good guarantee of portability, and is the practice to encourage. Though I will be happy if the C and C++ standards are kept on a converging path...
that's actually been a topic of focus recently. apparently, the last(?)
meetings of the c and c++ committees were essentially held together
(some people are members of both).
if you're writing a c++ program, i say take advantage of namespace std
and prefer <cmath> over <math.h>. there is no difference except the
stuff in <cmath> is in namespace std, and some overloads are added.
i don't follow the c committee's work, but i can't imagine that c
namespaces haven't been considered, and if they are implemented, they
will probably take the same form as c++'s, with similar "new" headers.
still, you should probably ask the c group that if it's a decision factor.
mark This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Azhar Bilgrami |
last post by:
Dear
Hi:
Hope to see u in good health.
" I want to migrate a database which is currently running
Unix as Operating System and Oracle ver 6 as
Database, it is also using oracle froms version 3...
|
by: Pawel Gruszka |
last post by:
Hello!
I need a mdb 2 PostgtreSQL migration tool (something similar to pgAdmin
plugin - "Database migration wizard") that don't needs M$ Windows or
XWindow.
It should also transfer data and...
|
by: DEATH TO KENT WEST HILL |
last post by:
Praise
http://linux-ntfs.sourceforge.net/misc.html#praise
If you have a success story you'd like to share, let me know
(webmaster@flatcap.org).
Your project just saved me!! I run red hat...
|
by: Dave |
last post by:
We are trying to migrate a MS SQL server app to DB2 8.1 Linux platform.
Our database has got about 300+tables with total size - 150 GB
We are using MS SQL's BCP utility to extract data from...
|
by: Scott |
last post by:
I have written windows applications using MFC for several years and
have frequently used MFC techniques.
Now I'm moving to C# .NET WinForm. Mostly C# books describes C#
language (sometimes...
|
by: rob |
last post by:
Dear All,
I have a very small test project to convert asp to asp.net using the
Microsoft/Artisan ASP to ASP.NET Migration Assistant...
|
by: pkr |
last post by:
Hi,
In my shop, we have database in diverse platforms like mainframe,
Linux, Windows 2000. We are planning to consolidate all iDB in a single
platform and build one big monster DB, this monster...
|
by: Gladiator |
last post by:
DB2 migration issue from AIX to Linux
I am trying to migrate database from AIX box to Linux box using the
db2move and db2look command. Everything worked fine for the tables with
user defined...
|
by: jsmith |
last post by:
hi all
i use delphi for win32 applications and C for microcontrollers.
i going to migrate to C for windows (and linux soon), while developing
from win32 to DotNet.
there are several compilers...
|
by: pssraju |
last post by:
Hi,
At present application was built on solaris 9 using sun studio 9 (Sun C++ 5.6) & rouguewave sorce pro 5. We are planning to port the same application onto SuSE Linux 9.5.0 using GCC 3.3.3 & RW...
|
by: CloudSolutions |
last post by:
Introduction:
For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome former...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
| |