473,793 Members | 2,974 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Enhancing valarray with "normal" arithmetic operators

The template std::valarray behaves pretty much like a mathematical
vector. Arithmetic operators apply elementwise. Now I'd like to extend
this to a user-defined type, e.g., complex.

Multiplying a double by a complex number gives a complex number. Now I
would like to multiply a valarray of doubles by a complex number and get
a valarray of complex numbers. Of course, a C++ compiler won't jump to
that conclusion; I need to define something to help it.

I didn't expect the following to compile:

#include <valarray>
#include <complex>
int main()
{
const double a0[] = {1.5, 4, 0};
std::valarray<d ouble> a(a0, 3);
std::complex<do uble> z(1,2);
std::valarray<s td::complex<dou ble> > c (3);
c = z * a; // error: no match for operator *
return 0;
}

And indeed it gives "no match for `std::complex<d ouble>& *
std::valarray<d ouble>&' operator". (BTW, c is irrelevant to the
problem; I just want to show you what I expect.)

Now the question is, what would be the clean way to provide such
functionality? I want to avoid putting any notational burden on the
user. If possible, I'd like to avoid code duplication. Is there a
"generic" approach?

Thanks

Christian

Jul 19 '05 #1
6 3666
Christian Brechbühler wrote:
The template std::valarray behaves pretty much like a mathematical
vector. Arithmetic operators apply elementwise. Now I'd like to extend
this to a user-defined type, e.g., complex.

Multiplying a double by a complex number gives a complex number. Now I
would like to multiply a valarray of doubles by a complex number and get
a valarray of complex numbers. Of course, a C++ compiler won't jump to
that conclusion; I need to define something to help it.

I didn't expect the following to compile:

#include <valarray>
#include <complex>
int main()
{
const double a0[] = {1.5, 4, 0};
std::valarray<d ouble> a(a0, 3);
std::complex<do uble> z(1,2);
std::valarray<s td::complex<dou ble> > c (3);
c = z * a; // error: no match for operator *
return 0;
}

And indeed it gives "no match for `std::complex<d ouble>& *
std::valarray<d ouble>&' operator". (BTW, c is irrelevant to the
problem; I just want to show you what I expect.)

Now the question is, what would be the clean way to provide such
functionality? I want to avoid putting any notational burden on the
user. If possible, I'd like to avoid code duplication. Is there a
"generic" approach?

Thanks

Christian


How about simply providing an override on operator* ?:

std::valarray<s td::complex<dou ble> >& operator*(doubl e scalar, const
std::valarray<s td::complex<dou ble> > &v)
{
return std::complex<do uble>(scalar) * v);
}

std::valarray<s td::complex<dou ble> >& operator*(const
std::valarray<s td::complex<dou ble> > &v, double scalar)
{
return std::complex<do uble>(scalar) * v);
}
}

Jul 19 '05 #2
red floyd wrote:
[ redacted ]


Oops. kill the paren after v in both routines, and the extra closing brace.

Jul 19 '05 #3
Christian Brechbühler wrote:

#include <valarray>
#include <complex>
int main()
{
const double a0[] = {1.5, 4, 0};
std::valarray<d ouble> a(a0, 3);
std::complex<do uble> z(1,2);
std::valarray<s td::complex<dou ble> > c (3);
c = z * a; // error: no match for operator *
return 0;
}


Have you tried to initialize z as double complex valarray with the same
length as a and all values set to (1,2)? I think then z*a should translate
into z[i]*a[i] (i.e. operator*(compl ex<..>, double)) which should be
defined. But I am certainly not sure about that.
Jul 19 '05 #4
I wrote:
#include <valarray>
#include <complex>
int main()
{
const double a0[] = {1.5, 4, 0};
std::valarray<d ouble> a(a0, 3);
std::complex<do uble> z(1,2);
std::valarray<s td::complex<dou ble> > c (3);
c = z * a; // error: no match for operator *
return 0;
}

Harald Grossauer replied: Have you tried to initialize z as double complex valarray with the same
length as a and all values set to (1,2)? I think then z*a should translate
into z[i]*a[i] (i.e. operator*(compl ex<..>, double)) which should be
defined. But I am certainly not sure about that.


I would have expected that it works, but this approach would put a
notational burden on the client code. I'd prefer to avoid that, i.e.,
I'd like my program, with an additional #include directive, to compile
as written.

To try it out, I changed the definition of z to

std::valarray<s td::complex<dou ble> > z(std::complex< double>(1,2), 3);

But this doesn't compile. E.g., g++ complains,

varr-complex-1.cc:10: no match for `valarray<compl ex<double> > & *
valarray<double > &'
/usr/include/g++-3/std/fcomplex.h:68: candidates are: complex<float>
operator* (const complex<float> &, float)
/usr/include/g++-3/std/fcomplex.h:70: complex<float>
operator* (float, const complex<float> &)
/usr/include/g++-3/std/dcomplex.h:68: complex<double>
operator* (const complex<double> &, double)
/usr/include/g++-3/std/dcomplex.h:70: complex<double>
operator* (double, const complex<double> &)
/usr/include/g++-3/std/ldcomplex.h:68: complex<long
double> operator* (const complex<long double> &, long double)
/usr/include/g++-3/std/ldcomplex.h:70: complex<long

Apparently the STL has specializations for multiplying valarrays of
float, double, and long.

What I would like to express is that any operation (say, + - * /)
applied to a valarray and a scalar of types for which the operation is
defined yields a valarray of the "wider" type. Where, e.g., double is
wider than float, and complex<double> is wider than double. But that
may be outside of what I can express in C++.

BTW, valarray<comple x> *= double is defined. But valarray<comple x> *
double is NOT.

Vielen Dank für den Vorschlag

Christian

Jul 19 '05 #5
I wrote:
I would like to multiply a valarray of doubles by a complex number and
get a valarray of complex numbers. Of course, a C++ compiler won't
jump to that conclusion; I need to define something to help it.

I didn't expect the following to compile:

#include <valarray>
#include <complex>
int main()
{
const double a0[] = {1.5, 4, 0};
std::valarray<d ouble> a(a0, 3);
std::complex<do uble> z(1,2);
std::valarray<s td::complex<dou ble> > c (3);
c = z * a; // error: no match for operator *
return 0;
} Now the question is, what would be the clean way to provide such
functionality? I want to avoid putting any notational burden on the
user. If possible, I'd like to avoid code duplication. Is there a
"generic" approach?

red floyd replied (his/her corrections applied): How about simply providing an override on operator* ?:

std::valarray<s td::complex<dou ble> >& operator*(doubl e scalar, const
std::valarray<s td::complex<dou ble> > &v)
{
return std::complex<do uble>(scalar) * v;
}

std::valarray<s td::complex<dou ble> >& operator*(const
std::valarray<s td::complex<dou ble> > &v, double scalar)
{
return std::complex<do uble>(scalar) * v;
}


Thanks, that works with some adaptation. I wanted to multiply
complex<T> * valarray<T>; the above defines T * valarray<comple x<T> > (T
being double). So if insert the adapted code

std::valarray<s td::complex<dou ble> >& operator*
(std::complex<d ouble> scalar,
const std::valarray<d ouble> &v)
{
return std::complex<do uble>(scalar) * v;
}

my program compiles. I can make it a little more generic,

template<class T>
std::valarray<s td::complex<T> >& operator*(std:: complex<T> scalar,
const std::valarray<T > &v)
{
return std::complex<T> (scalar) * v;
}

(BTW, in the C++ lingo, that would be called (operator) overloading;
overriding means redefining an inherited virtual function in a derived
class.) But I see some drawbacks with this solution:

(A) *Genericity*

As you show, I'd have to define both real * valarray<comple x> and
valarray<comple x> * real. As alluded, I'll need the same pair for
complex * valarray<real>.

I'd need to type the same set for every operator (at least +, -, *, /).

When I want to use some other types besides complex, I'd have to repeat
everything for each such type. I think it should be possible to write a
template<class A, class B> and specify that A Op_ valarray<B> gives a
valarray<Larger _Of<A,B> >.

(B) *Efficiency*

Multiplying real * complex takes 2 multiplications (of real numbers).
By converting to the scalar to comples, we trade that in for 4
multiplications and 2 additions; this happens for every element of the
valarray.

Correct me if I'm mistaken, but it looks like this operator* creates a
temporary valarray, passing it by reference to the caller, which then
copies all the values into the receiving valarray. The standard library
seems to use closures to avoid such copying.
It's generally considered BAD to use preprocessor macros in C++. Can we
do without? It seems not even the standard templates can. In
<valarray>, I see this:

#define _DEFINE_BINARY_ OPERATOR(_Op, _Name) \
template<typena me _Tp> \
inline _Expr<_BinClos< _Name,_ValArray ,_ValArray,_Tp, _Tp>, _Tp> \
operator _Op (const valarray<_Tp> &__v, const valarray<_Tp> &__w) \
// [omitted 20 lines defining this and two other operators]
}

_DEFINE_BINARY_ OPERATOR(+, plus)
_DEFINE_BINARY_ OPERATOR(-, minus)
_DEFINE_BINARY_ OPERATOR(*, multiplies)
_DEFINE_BINARY_ OPERATOR(/, divides)
_DEFINE_BINARY_ OPERATOR(%, modulus)
_DEFINE_BINARY_ OPERATOR(^, _Bitwise_xor)
_DEFINE_BINARY_ OPERATOR(&, _Bitwise_and)
_DEFINE_BINARY_ OPERATOR(|, _Bitwise_or)
_DEFINE_BINARY_ OPERATOR(<<, _Shift_left)
_DEFINE_BINARY_ OPERATOR(>>, _Shift_right)

#undef _DEFINE_BINARY_ OPERATOR

Well, there's the answer to not having to retype everything for every
operator. And it gives the optimizations of a closure.

The question stays, is this a reasonable approach for my own types? Can
it be templated so it works for adding int to double just like for
multiplying complex<double> with double? Could this feat be achieved
without preprocessor macros?

Christian

Jul 19 '05 #6
I wrote:
I would like to multiply a valarray of doubles by a complex number
and get a valarray of complex numbers. [...] What would be the clean way to provide such functionality?


red floyd replied (his/her corrections applied):
How about simply providing an override on operator* ?:

std::valarray<s td::complex<dou ble> >& operator*(doubl e scalar, const
std::valarray<s td::complex<dou ble> > &v)
{
return std::complex<do uble>(scalar) * v;
}

std::valarray<s td::complex<dou ble> >& operator*(const
std::valarray<s td::complex<dou ble> > &v, double scalar)
{
return std::complex<do uble>(scalar) * v;
}

Thanks, that works with some adaptation. I wanted to multiply
complex<T> * valarray<T>; the above defines T * valarray<comple x<T> > (T
being double). So if insert the adapted code

std::valarray<s td::complex<dou ble> >& operator*
(std::complex<d ouble> scalar,
const std::valarray<d ouble> &v)
{
return std::complex<do uble>(scalar) * v;
}

my program compiles.


Ooops, that was naive: this is simply an infinite recursion! (Yes it
compiles :-) )

Jul 19 '05 #7

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

Similar topics

20
1714
by: Andrew Poulos | last post by:
If I have a page with a bunch of content and some javascript in the head how do I notify the javascript disabled users that enabling javascript would enhance their experience. At the moment I'm trying the noscript tag but its content overlaps the "normal" content. I'd like to put a link to non-javascript pages and I'd rather not put the normal content in a document.write. Andrew Poulos
2
1787
by: David Trimboli | last post by:
If you look at http://www.trimboli.name/klingon/, you'll see that the headers on the page are displayed in small-caps. Usually, this is desired. However, the header "may'vaD ghuHmoH QoQ"* is surrounded by <span lang="tlh"> ("tlh" for "tlhIngan Hol"), and I have put a declaration of "font-variant: normal" in the main stylesheet. I can't figure out why the Klingon title is still in small-caps. I want all Klingon phrases to appear in normal...
25
2586
by: tsaar2003 | last post by:
Hi Pythonians, To begin with I'd like to apologize that I am not very experienced Python programmer so please forgive me if the following text does not make any sense. I have been missing constants in Python language. There are some workarounds available, for example the const-module. To me, this looks quite cumbersome and very unintuitive. For the interpreter, in the efficiency-wise, I just cannot tell.
6
9113
by: Zeng | last post by:
Math.Round has good behavior as following: Math.Round(3.45, 1); //Returns 3.4. The last '5' is thrown away because 4 is even Math.Round(3.75, 1); //Returns 3.8. The last '5' is used because '7' is odd However, if format.NumberDecimalDigits is 1 decimal d = 3.45M; d.ToString( "F", format ); //Return 3.5 - this is different from Math.Round;
1
1354
by: Deane | last post by:
I've run into this problem on many occasions -- I need to have the server side form tag on my Web form, of course. But I also need to have *another* form on the page that posts to a URL totally out of my control. I can think of three situations off the top of my head. In one case, it was a login to the client's PeopleSoft system. In another, it was a PayPal form.
4
2933
by: K | last post by:
Hello everyone, I understand that urllib and urllib2 serve as really simple page request libraries. I was wondering if there is a library out there that can get the HTTP requests for a given page. Example: URL: http://www.google.com/test.html Something like: urllib.urlopen('http://www.google.com/
0
9670
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
9518
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10159
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
9033
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6776
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
5436
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5560
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4111
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
3719
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.