473,729 Members | 2,344 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Compile-time matrix dimension checking and template friend question

Hi all,

I am writing a template matrix class in which the template parameters are
the number of rows and number of columns. There are a number of reasons
why this is an appropriate tradeoff for my particular application. One of the
advantages is that the _compiler_ can force inner matrix dimensions used in
multiplication to agree. A _complie-time_ error will be triggered if you
write A * B and the number of coluns in A does not equal the number of
rows in B. Here's simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix {
public:
double data[nRows][nCols];

// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Note that while this code works under all g++ versions I tested, from
g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++
6.

The problem with this code is that the data field must be public. Otherwise,
Matrix<4,3>::op erator* will not have access to Matrix<4,1>'s or
Matrix<3,1>'s data. Thus, I would like to make Matrix<4,1> and
Matrix<3,1> friends of Matrix<4,3>. Is this possible? If so, what's the
syntax? I tried the code below and some other variations, but they were
all incorrect. The code below generated "partial specialization
`Matrix<nRows, nNewCols>' declared `friend'" and "partial specialization
`Matrix<nCols, nNewCols>' declared `friend'" errors under g++-3.0.4 and
did not give Matrix<4,3> access to the private data of Matrix<4,1> or
of Matrix<3,1>.

template<int nRows, int nCols> class Matrix {
private:
double data[nRows][nCols];

public:
// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}

template<int nNewCols> friend class Matrix<nRows,nN ewCols>;
template<int nNewCols> friend class Matrix<nCols,nN ewCols>;
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Can this be done and if so, how? Thanks for any help,

Ben :-)
Jul 22 '05 #1
6 3330

"Ben Ingram" <bt************ @catgufu.mit.ed u> wrote in message
news:a9******** *************** *******@news.so nicnews.com...
Hi all,

I am writing a template matrix class in which the template parameters are
the number of rows and number of columns. There are a number of reasons
why this is an appropriate tradeoff for my particular application. One of the advantages is that the _compiler_ can force inner matrix dimensions used in multiplication to agree. A _complie-time_ error will be triggered if you
write A * B and the number of coluns in A does not equal the number of
rows in B. Here's simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix {
public:
double data[nRows][nCols];

// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Note that while this code works under all g++ versions I tested, from
g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++
6.

The problem with this code is that the data field must be public. Otherwise,
[SNIP]

Having the data field public is not really a good idea and it is not
necessary. I'd recommend to implement the data access via the operator()
like the following for example:

inline double& operator()( unsigned int Row, unsigned int Col ) {
assert( Row < MaxRow && Col < MaxCol ); // you
can store the dimensions at the time of construction!
return data[Row][Col];
}

inline double operator()( int Row, int Col ) const {
assert( Row < MaxRow && Col < MaxCol );
return data[Row][Col];
}

Therefore you can simply write A(3, 5) to access the respective matrix
element. Furthermore the physical way of data management is hidden, because
you might consider to use a 1D array for speed purposes or whatever reason.
However, the problem you're facing with VC++ 6.0 seems to be related to its
shortcomings regarding templates & partial specialization. I think that
using a later version should resolve your problem.

For an easy sample matrix implementation look at:

http://www.parashift.com/c++-faq-lit...html#faq-16.17

Can this be done and if so, how? Thanks for any help,

Ben :-)


HTH
Chris
Jul 22 '05 #2
On Thu, 29 Jan 2004 01:35:22 -0800, Chris Theis wrote:
"Ben Ingram" <bt************ @catgufu.mit.ed u> wrote in message
news:a9******** *************** *******@news.so nicnews.com...
Hi all,

I am writing a template matrix class in which the template parameters
are the number of rows and number of columns. There are a number of
reasons why this is an appropriate tradeoff for my particular
application. One of

the
advantages is that the _compiler_ can force inner matrix dimensions
used

in
multiplication to agree. A _complie-time_ error will be triggered if
you write A * B and the number of coluns in A does not equal the number
of rows in B. Here's simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix { public:
double data[nRows][nCols];

// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&) //
since inner dimensions don't agree

return 0;
}
}
Note that while this code works under all g++ versions I tested, from
g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++
6.

The problem with this code is that the data field must be public.

Otherwise,
[SNIP]

Having the data field public is not really a good idea and it is not
necessary. I'd recommend to implement the data access via the operator()
like the following for example:

inline double& operator()( unsigned int Row, unsigned int Col ) {
assert( Row < MaxRow && Col < MaxCol ); //
you
can store the dimensions at the time of construction!
return data[Row][Col];
}
}
inline double operator()( int Row, int Col ) const {
assert( Row < MaxRow && Col < MaxCol ); return data[Row][Col];
}
}
Therefore you can simply write A(3, 5) to access the respective matrix
element. Furthermore the physical way of data management is hidden,
because you might consider to use a 1D array for speed purposes or
whatever reason. However, the problem you're facing with VC++ 6.0 seems
to be related to its shortcomings regarding templates & partial
specialization. I think that using a later version should resolve your
problem.

For an easy sample matrix implementation look at:

http://www.parashift.com/c++-faq-lit...html#faq-16.17

Can this be done and if so, how? Thanks for any help,

Ben :-)


HTH
Chris


Thank you for your suggestion, Chris, but if I can figure out the friend
issue, the template strategy has several advantages. As I mentioned in my
first post, dimensions can be checked at compile-time, not at run-time.
This is true for all operations - addition, subtraction, inversion, etc. -
not just multiplication. Compile-time dimension checking is a boon for me
because the library will be used in an airborne real-time system where
run-time failure is not an option. The template solution I proposed also
makes it easier for the compiler to optimize out bounds-checks that are
gaurantee to pass (like your A(3,5) example) and to perform the named
return value optimizations. Templates also facilitate a custom new() and
delete() strategy that improves the speed of the filter the library is
used for by a factor of 3 by avoiding the creation and deletion of
temporary objects. I know that one can avoid unnecessary creation and
deletion using expression templates, but it seems to me that expression
templates require O(n^4) operations to evaluate A * B * C instead of the
O(n^3) operations that are necessary.

What I'm most curious about isn't whether the template solution is the
best one for my needs, it's how can I use the template solution and keep
the data private at the same time. The template solution may not be the
best one, but I'm still curious if and how this kind of templated friendship
works.

Ben :-)
Jul 22 '05 #3
Ben Ingram wrote:
Hi all,

I am writing a template matrix class in which the template parameters are
the number of rows and number of columns. There are a number of reasons
why this is an appropriate tradeoff for my particular application. One of the
advantages is that the _compiler_ can force inner matrix dimensions used in
multiplication to agree. A _complie-time_ error will be triggered if you
write A * B and the number of coluns in A does not equal the number of
rows in B. Here's simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix {
public:
double data[nRows][nCols];

// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Note that while this code works under all g++ versions I tested, from
g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++
6.

The problem with this code is that the data field must be public. Otherwise,
Matrix<4,3>::op erator* will not have access to Matrix<4,1>'s or
Matrix<3,1>'s data. Thus, I would like to make Matrix<4,1> and
Matrix<3,1> friends of Matrix<4,3>. Is this possible? If so, what's the
syntax? I tried the code below and some other variations, but they were
all incorrect. The code below generated "partial specialization
`Matrix<nRows, nNewCols>' declared `friend'" and "partial specialization
`Matrix<nCols, nNewCols>' declared `friend'" errors under g++-3.0.4 and
did not give Matrix<4,3> access to the private data of Matrix<4,1> or
of Matrix<3,1>.

template<int nRows, int nCols> class Matrix {
private:
double data[nRows][nCols];

public:
// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}

template<int nNewCols> friend class Matrix<nRows,nN ewCols>;
template<int nNewCols> friend class Matrix<nCols,nN ewCols>;
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Can this be done and if so, how? Thanks for any help,

Ben :-)

I'd make the multiply operator a friend, rather than an internal function:

template<int Rows, int Cols>
class Matrix {
friend template <int R, int C, int N>
Matrix<R,N> operator*(const Matrix<R,C>&, const Matrix<C, N>&);

};

template <int R, int C, int N>
Matrix<R,N> operator*(const Matrix<R,C>&, const Matrix<C, N>&);
Jul 22 '05 #4

"Ben Ingram" <bt************ @catgufu.mit.ed u> wrote in message
news:44******** *************** *******@news.so nicnews.com...
[SNIP]
What I'm most curious about isn't whether the template solution is the
best one for my needs, it's how can I use the template solution and keep
the data private at the same time. The template solution may not be the
best one, but I'm still curious if and how this kind of templated friendship works.

Ben :-)


Well, to keep the data private without having to use friend declarations,
just use the operator() for access. The advantages of this are also covered
in the FAQ. However, to compile your class with VC++ you might have to
resort to version 7.X as there are many unresolved issures regarding partial
specialization with VC++ 6.0

Cheers
Chris
Jul 22 '05 #5
On Thu, 29 Jan 2004 08:59:42 -0800, red floyd wrote:
Ben Ingram wrote:
Hi all,

I am writing a template matrix class in which the template parameters
are the number of rows and number of columns. There are a number of
reasons why this is an appropriate tradeoff for my particular
application. One of the advantages is that the _compiler_ can force
inner matrix dimensions used in multiplication to agree. A
_complie-time_ error will be triggered if you write A * B and the
number of coluns in A does not equal the number of rows in B. Here's
simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix { public:
double data[nRows][nCols];

// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&) //
since inner dimensions don't agree

return 0;
}
}
Note that while this code works under all g++ versions I tested, from
g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++
6.

The problem with this code is that the data field must be public.
Otherwise, Matrix<4,3>::op erator* will not have access to Matrix<4,1>'s
or Matrix<3,1>'s data. Thus, I would like to make Matrix<4,1> and
Matrix<3,1> friends of Matrix<4,3>. Is this possible? If so, what's the
syntax? I tried the code below and some other variations, but they were
all incorrect. The code below generated "partial specialization
`Matrix<nRows, nNewCols>' declared `friend'" and "partial
specialization `Matrix<nCols, nNewCols>' declared `friend'" errors
under g++-3.0.4 and did not give Matrix<4,3> access to the private data
of Matrix<4,1> or of Matrix<3,1>.

template<int nRows, int nCols> class Matrix { private:
double data[nRows][nCols];

public:
// operator*: return this * A
template<int nNewCols> Matrix<nRows,nN ewCols>
operator*(const Matrix<nCols,nN ewCols> &A) const {
Matrix<nRows,nN ewCols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nNewCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nCols; iInner++) {
innerProd += data[iRow][iInner] * A.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}
}
template<int nNewCols> friend class Matrix<nRows,nN ewCols>;
template<int nNewCols> friend class Matrix<nCols,nN ewCols>;
};

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&) //
since inner dimensions don't agree

return 0;
}
}
Can this be done and if so, how? Thanks for any help,

Ben :-)

I'd make the multiply operator a friend, rather than an internal
function:

template<int Rows, int Cols>
class Matrix {
friend template <int R, int C, int N>
Matrix<R,N> operator*(const Matrix<R,C>&, const Matrix<C, N>&);

};

template <int R, int C, int N>
Matrix<R,N> operator*(const Matrix<R,C>&, const Matrix<C, N>&);

Perfect!!! Almost. friend should come after, not before template<...>.
Thanks so much for the help!!! Below is the modified code:

template<int nRows, int nCols> class Matrix {
private:
double data[nRows][nCols];

public:
// operator*: return this * A
template<int multRows, int multInner, int multCols>
friend Matrix<multRows ,multCols> operator*(
const Matrix<multRows ,multInner> &,
const Matrix<multInne r,multCols> &);
};

template <int nRows, int nInner, int nCols>
Matrix<nRows,nC ols> operator*(const Matrix<nRows,nI nner> &A,
const Matrix<nInner,n Cols> &B) {
Matrix<nRows,nC ols> ret;
for(int iRow = 0; iRow < nRows; iRow++) {
for(int iCol = 0; iCol < nCols; iCol++) {
double innerProd = 0.0;
for(int iInner = 0; iInner < nInner; iInner++) {
innerProd += A.data[iRow][iInner] * B.data[iInner][iCol];
}
ret.data[iRow][iCol] = innerProd;
}
}
return ret;
}

int main(int argc, char **argv) {
Matrix<4,3> A;
Matrix<3,1> x;
Matrix<2,1> y;

A*x; // compiler creates
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<3,1>&)
//A*y; // compile-time error thrown since compiler can't create
// Matrix<4,1> Matrix<4,3>::op erator*(const Matrix<2,1>&)
// since inner dimensions don't agree

return 0;
}

Ben :-)
Jul 22 '05 #6
Ben Ingram wrote:
[Redacted for space]

Perfect!!! Almost. friend should come after, not before template<...>.
Thanks so much for the help!!! Below is the modified code:

[Redacted for space]


Glad I could help, Ben! To be honest, I've never tried playing with
friend templates, so I'm amazed that that I got the syntax as close as I
did.

red floyd
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2812
by: janeaustine50 | last post by:
Python's InteractiveInterpreter uses the built-in compile function. According to the ref. manual, it doesn't seem to concern about the encoding of the source string. When I hand in an unicode object, it is encoded in utf-8 automatically. It can be a problem when I'm building an interactive environment using "compile", with a different encoding from utf-8. IDLE itself has the same problem. ( '<a string with non-ascii-encoding>' is...
1
4468
by: Mario T. Lanza | last post by:
I am working with Visual Studio. The solution I am developing is composed of about 8 separate projects. Some of these projects represent different tiers in the N-tiered architecture (data, business logic, presentation, etc.). Right now, some of the projects are inter-related and reference each other using Project References. When I select "Rebuild Solution" to compile, each project is successfully compiled into its own directory (and...
2
6966
by: Tony Johansson | last post by:
Hello! I get compile error when compiling using the command javac from the command terminal window(CMD). I have just two classes which are called HelloWorld.java and Slask.java. I have both classes in the directory called temp and I do cd temp to this directory. Then I do javac HelloWorld.java Now I get the compile error HelloWorld.java:9 cannot find symbol
10
19723
by: Chris LaJoie | last post by:
Our company has been developing a program in C# for some time now, and we haven't had any problems with it, but just last night something cropped up that has me, and everyone else, stumped. I have a struct that contains several different types of data. This struct is used throuout the program. Now, when I compile, I get 6 errors, all of them "Use of possibly unassigned field 'awayTime'" or "Use of possibly unassigned field 'intlTime'"....
3
3202
by: Peter | last post by:
Hi, I am trying to compile an existing project (originally c) in .NET (rename .c files to .cpp). After fixing some problems, here are the ones that I don't know how to deal with: -------------------------------------------------------------------------- .... .... \myfile.cpp(987) : error C2440: 'initializing' : cannot convert from 'int (__cdecl *)(mytype *,char *,int)' to 'int (__cdecl *)(void)'
6
2858
by: Thomas Connolly | last post by:
I have 2 pages referencing the same codebehind file in my project. Originally the pages referenced separate code behind files. Once I changed the reference to the same file, everything worked fine while the file was in the project directory. When the obsolete file was removed from the project directory, my application will no longer compile. Can someone please help with this issue? Thank in advance, Tom
7
1679
by: Arne | last post by:
I am porting a website to ASP.net 2.0. Temporarily I compile with Visual Studio 2003 and deploying to ASP.net 2.0. How do I compile my website under ASP.Net 2.0? I know it can compile each page as I touch it. During the beta there used to be something like mywebsite.com/compile.??? that you could run. Does it still exist?
3
2304
by: NvrBst | last post by:
Right now I have C99 code in .c extensions. I compile it in VSC++ and it complains about a lot of errors. I change the extensions to .cpp and compile in VSC++ and it succeeds. Is there a way to keep my extensions .c, but tell VSC++ (through an project option) to compile as C++98 code (as if it had .cpp extensions).
2
6924
by: Andrus | last post by:
I need compile in-memory assembly which references to other in-memory assembly. Compiling second assembly fails with error Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' could not be found Saving assembly to Windows temp directory for referencing only creates huge amout of temporary
6
1951
by: Ed Leafe | last post by:
I've noticed an odd behavior with compile() and code that does not contain a trailing newline: if the last line is a comment inside of any block, a syntax error is thrown, but if the last line is a non- comment Python statement, there is no error. Here's an example (using 2.5.1 on OS X) .... def foo(): .... print 'bar' """ <code object <moduleat 0x79608, file "", line 2>
0
8917
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9281
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9200
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9142
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6722
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6022
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4795
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3238
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2680
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.