Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

class of unsigned 32 bit and overflow

63 views
Skip to first unread message

asetof...@gmail.com

unread,
Jun 1, 2015, 4:19:51 AM6/1/15
to
Instead of speak of nothing
I.e. Smart pointers and exceptions
c++11 C++17 etc

Why do not speak how would you
implement a class of 32 bit
unsigned and signed that catch
overflow store it in itself element?

The same for double, that allow
Something as:
a=b*c+y+564;
Many other operation on a
If(ov(a)==1)
. than a is in overflow or
. error in a
. due some calculation
. where a appear as result
return a;

It should be easy and useful..

Why no one speak about a class of
fixed float point numbers
[float points number for me are not
ok]
and big numbers with not
fixed width (width can grow using
available memory)?

These arguments are too much
difficult? Or you consider them
unimportant?



Message has been deleted

asetof...@gmail.com

unread,
Jun 1, 2015, 4:42:27 AM6/1/15
to
Stefan wrote:"
Why speak about? When person
pay for, you then code the
classes. When no person pay
money, you sit coffee drink
enjoy life."

You are right, but the overflow
type is a matter of days for me
or hours for you and can be
very useful as library etc
Because the mod() behavior
in many case it is not the right one

For fixed point and big number library, I agree 99%

bartek

unread,
Jun 1, 2015, 5:26:41 AM6/1/15
to
On 01.06.2015 10:19, asetof...@gmail.com wrote:
> Instead of speak of nothing
> I.e. Smart pointers and exceptions
> c++11 C++17 etc
>
> Why do not speak how would you
> implement a class of 32 bit
> unsigned and signed that catch
> overflow store it in itself element?
>
> The same for double,

For floating points we have nan, +-inf.

> that allow
> Something as:
> a=b*c+y+564;
> Many other operation on a
> If(ov(a)==1)
> . than a is in overflow or
> . error in a
> . due some calculation
> . where a appear as result
> return a;

if (!isfinite(a))....



> It should be easy and useful..

For integers sometimes it is, but it is simple
and quite boring. Just check overflow on
every arithmetic operation.


> Why no one speak about a class of
> fixed float point numbers
> [float points number for me are not
> ok]

Fixed point? For what?
I can think only about using this in uC.
So it will be small number.

c = (proper_int)((a*(bigger int)b)>>offset);

Put in a class.
Make +,-,*,/ operators
???
Profit.
;-)

A couple minutes of work.

But there will be a problem with overflow control...
oh, I see... ;-)

> and big numbers with not
> fixed width (width can grow using
> available memory)?

GMP, pari-gp(shell, but also c++ library), MPFR...


> These arguments are too much
> difficult? Or you consider them
> unimportant?

Unimportant or done.

My question is, why the committee cant put better
base for numerical calculation. For matrix calculation
I use eigen, but it will be nice to see standard
(well designed) interface. Then, in my imagination,
i will use standard implementation, or connect with
Eigen, ATLAS or Intel MKL without rewriting.

;-)


bartekltg

asetof...@gmail.com

unread,
Jun 1, 2015, 2:45:04 PM6/1/15
to
This is my first attempt ...
It would be good if there is a
way to convert types in new type
For not write each operator
Example *, +
for each type possible

....
/*
In one asm file compile for result .obj code
section _DATA use32 public class=DATA

global u32omul
global u32oadd
global u32osub
global i32omul
global i32oadd
global i32osub

section _BSS use32 public class=BSS
section _TEXT use32 public class=CODE

;u32 __stdcall u32omul(u32 a, u32 b)
; 0ra, 4P_a, 8P_b
align 4
u32omul:
mov eax, dword[esp+ 4]
cmp eax, -1
je .1
mov edx, dword[esp+ 8]
cmp edx, -1
je .0
mul edx
cmp edx, 0
je .1
.0: mov eax, -1
.1: ret 8

;u32 __stdcall u32oadd(u32 a, u32 b)
align 4
u32oadd:
mov eax, dword[esp+ 4]
mov edx, dword[esp+ 8]
add eax, edx
jnc .0
mov eax, -1
.0: ret 8

;u32 __stdcall u32osub(u32 a, u32 b)
align 4
u32osub:
mov eax, dword[esp+ 4]
cmp eax, -1
je .1
mov edx, dword[esp+ 8]
cmp edx, -1
je .0
sub eax, edx
jae .1
.0: mov eax, -1
.1: ret 8

;i32 __stdcall i32omul(i32 a, i32 b)
align 4
i32omul:
mov eax, dword[esp+ 4]
cmp eax, 0x80000000
je .1
mov edx, dword[esp+ 8]
cmp edx, 0x80000000
je .0
imul edx
jno .1
.0: mov eax, 0x80000000
.1: ret 8


;i32 __stdcall i32oadd(i32 a, i32 b)
align 4
i32oadd:
mov eax, dword[esp+ 4]
cmp eax, 0x80000000
je .1
mov edx, dword[esp+ 8]
cmp edx, 0x80000000
je .0
add eax, edx
jno .1
.0: mov eax, 0x80000000
.1: ret 8

;i32 __stdcall i32osub(i32 a, i32 b)
align 4
i32osub:
mov eax, dword[esp+ 4]
cmp eax, 0x80000000
je .1
mov edx, dword[esp+ 8]
cmp edx, 0x80000000
je .0
sub eax, edx
jno .1
.0: mov eax, 0x80000000
.1: ret 8

*/

// bcc32 thisfile.cpp asmfile.obj
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
#include <limits.h>
#include <iostream.h>

#define G(a,b) if(a)goto b
#define R return
#define P printf
#define M malloc
#define Fr free
#define F for
#define S sizeof
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned
#define i32 int
#define d64 double

// functions for detect u32 or i32 overflow in asm
extern "C" {
u32 __stdcall u32omul(u32 a, u32 b);
u32 __stdcall u32oadd(u32 a, u32 b);
u32 __stdcall u32osub(u32 a, u32 b);
i32 __stdcall i32omul(i32 a, i32 b);
i32 __stdcall i32oadd(i32 a, i32 b);
i32 __stdcall i32osub(i32 a, i32 b);
}

// 32 bit unsigned and signed with overflow
class ou32{
public:

ou32* val(void)
{u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;}

u32 ErrVal(void){R -1;} // value for error

ou32(){v=0;}
ou32(u32 a){v=a;}
//operator u32() const{R v;}
ou32& operator=(u32 h){v=h; R *this;}


ou32 operator =( ou32 a){v=a.v; R *this;}
ou32& operator*=(ou32& a){v=u32omul(v, a.v); R *this;}
ou32& operator*=( u32 a){v=u32omul(v, a); R *this;}

ou32& operator+=(ou32& a){v=u32oadd(v, a.v); R *this;}
ou32& operator+=( u32 a){v=u32oadd(v, a ); R *this;}

ou32& operator-=(ou32& a){v=u32osub(v, a.v); R *this;}
ou32& operator-=( u32 a){v=u32osub(v, a ); R *this;}

ou32& operator/=(ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1;
else v=v/a.v;
R *this;
}
ou32& operator/=(u32 a){if(v==-1||a==-1||a==0) v=-1;
else v=v/a;
R *this;
}

ou32& operator++(){v=(v==-1? -1: ++v); R *this;}

ou32& operator++(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) ++v; R *t;}

ou32& operator--(){v=(v==-1? -1: --v); R *this;}

ou32& operator--(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) --v; R *t;}

friend ou32& operator*(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32omul(a.v, b.v); R *r;}

friend ou32& operator*(ou32& a, u32 b)
{ou32 *r; r=a.val(); r->v=u32omul(a.v, b ); R *r;}

friend ou32& operator*(u32 a, ou32& b)
{ou32 *r; r=b.val(); r->v=u32omul(a, b.v); R *r;}

friend ou32& operator+(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32oadd(a.v, b.v); R *r;}

friend ou32& operator+(ou32& a, u32 b)
{ou32 *r; r=a.val(); r->v=u32oadd(a.v, b); R *r;}

friend ou32& operator-(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32osub(a.v, b.v); R *r;}

friend ou32& operator-(ou32& a, u32 b)
{ou32 *r; r=a.val(); r->v=u32osub(a.v, b); R *r;}

friend ou32& operator/(ou32& a, ou32& b)
{ou32 *r;
r=a.val();
if(a.v==-1||b.v==-1||b.v==0) r->v=-1;
else r->v=a.v/b.v;
R *r;
}

friend ou32& operator/(ou32& a, u32 b)
{ou32 *r;
r=a.val();
if(a.v==-1||b==-1||b==0) r->v=-1;
else r->v=a.v/b;
R *r;
}


friend ostream& operator<<(ostream& ostr, ou32& a)
{if( a.v==-1 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;}
friend i32 operator==(ou32& a, ou32& b){R a.v==b.v;}
friend i32 operator!=(ou32& a, ou32& b){R a.v==b.v;}
friend i32 operator<=(ou32& a, ou32& b){R a.v<=b.v;}
friend i32 operator>=(ou32& a, ou32& b){R a.v>=b.v;}
friend i32 operator<( ou32& a, ou32& b){R a.v< b.v;}
friend i32 operator>( ou32& a, ou32& b){R a.v> b.v;}

friend i32 operator==(ou32& a, u32 b){R a.v==b;}
friend i32 operator!=(ou32& a, u32 b){R a.v==b;}
friend i32 operator<=(ou32& a, u32 b){R a.v<=b;}
friend i32 operator>=(ou32& a, u32 b){R a.v>=b;}
friend i32 operator<( ou32& a, u32 b){R a.v< b;}
friend i32 operator>( ou32& a, u32 b){R a.v> b;}

u32 v;
static u32 ic;
static ou32 *maa;
};

u32 ou32::ic=0;
ou32 ma[64];
ou32* ou32::maa=ma;

class oi32{
public:
oi32* val(void)
{u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;}

i32 ErrVal(void){R 0x80000000;} // value for error


oi32(){v=0;}

operator i32() const{R v;}
oi32& operator=(i32 h){v=h; R *this;}

oi32 operator=(oi32 a){v=a.v; R *this;}
oi32& operator*=(oi32& a){v=i32omul(v, a.v); R *this;}
oi32& operator+=(oi32& a){v=i32oadd(v, a.v); R *this;}
oi32& operator-=(oi32& a){v=i32osub(v, a.v); R *this;}
oi32& operator/=(oi32& a)
{if(v==0x80000000||a.v==0x80000000||a.v==0) v=0x80000000;
else v=v/a.v;
R *this;
}
oi32& operator++(){v=(v==0x80000000? 0x80000000: ++v); R *this;}
oi32& operator++(int)
{oi32 *t; t=val(); *t=*this; if(v!=0x80000000) ++v; R *t;}
oi32& operator--(){v=(v==0x80000000? 0x80000000: --v); R *this;}
oi32& operator--(int)
{oi32 *t; t=val(); *t=*this; if(v!=0x80000000) --v; R *t;}

friend oi32& operator*(oi32& a, oi32& b)
{oi32 *r; r=a.val(); r->v=i32omul(a.v, b.v); R *r;}
friend oi32& operator*(oi32& a, i32 b)
{oi32 *r; r=a.val(); r->v=i32omul(a.v, b); R *r;}

friend oi32& operator+(oi32& a, oi32& b)
{oi32 *r; r=a.val(); r->v=i32oadd(a.v, b.v); R *r;}
friend oi32& operator+(oi32& a, i32 b)
{oi32 *r; r=a.val(); r->v=i32oadd(a.v, b); R *r;}

friend oi32& operator-(oi32& a, oi32& b)
{oi32 *r; r=a.val(); r->v=i32osub(a.v, b.v); R *r;}
friend oi32& operator-(oi32& a, i32 b)
{oi32 *r; r=a.val(); r->v=i32osub(a.v, b); R *r;}

friend oi32& operator/(oi32& a, oi32& b)
{oi32 *r;
r=a.val();
if(a.v==0x80000000||b.v==0x80000000||b.v==0) r->v=0x80000000;
else r->v=a.v/b.v;
R *r;
}

friend oi32& operator/(oi32& a, i32 b)
{oi32 *r;
r=a.val();
if(a.v==0x80000000||b==0x80000000||b==0) r->v=0x80000000;
else r->v=a.v/b;
R *r;
}

friend ostream& operator<<(ostream& ostr, oi32& a)
{if( a.v==0x80000000 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;}
friend i32 operator==(oi32& a, oi32& b){R a.v==b.v;}
friend i32 operator!=(oi32& a, oi32& b){R a.v==b.v;}
friend i32 operator<=(oi32& a, oi32& b){R a.v<=b.v;}
friend i32 operator>=(oi32& a, oi32& b){R a.v>=b.v;}
friend i32 operator<( oi32& a, oi32& b){R a.v< b.v;}
friend i32 operator>( oi32& a, oi32& b){R a.v> b.v;}

i32 v;
static u32 ic;
static oi32 *maa;
};

u32 oi32::ic=0;
oi32 mai[64];
oi32* oi32::maa=mai;


class of64{
public:
of64* val(void)
{u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;}

of64(){v=0.0;}

u32 overf(void)
{R _isnan(v)|| ! _finite(v) || v>=DBL_MAX || v<=DBL_MIN? 1: 0;}

friend doverf(double v)
{R _isnan(v)|| ! _finite(v) || v==DBL_MAX? 1: 0;}

double ErrVal(void){R DBL_MAX;} // value for error

operator double() const{R v;}

of64& operator=(i32 h){v=h; R *this;}
of64& operator=(double h){v=h; R *this;}

of64 operator=(of64 a){v=a.v; R *this;}
of64& operator*=(of64& a)
{if(a.overf()) v=ErrVal();
else v=v*a.v;
R *this;
}

of64& operator+=(of64& a)
{if(a.overf()) v=ErrVal();
else v=v+a.v;
R *this;
}

of64& operator-=(of64& a)
{if(a.overf()) v=ErrVal();
else v=v-a.v;
R *this;
}

of64& operator/=(of64& a)
{if(a.overf()||a.v==0.0) v=ErrVal();
else v=v/a.v;
R *this;
}

of64& operator++(){v=(overf()? DBL_MAX: ++v); R *this;}

of64& operator++(int)
{of64 *t; t=val(); *t=*this; if(!overf()) ++v; R *t;}

of64& operator--(){v=(overf()? DBL_MAX: --v); R *this;}

of64& operator--(int)
{of64 *t; t=val(); *t=*this; if(!overf()) --v; R *t;}

friend of64& operator*(of64& a, of64& b)
{of64 *r;
r=a.val();
if(a.overf()||b.overf()) r->v=a.ErrVal();
else r->v=a.v*b.v;
R *r;
}

friend of64& operator*(of64& a, double b)
{of64 *r;
r=a.val();
if(a.overf()||doverf(b)) r->v=a.ErrVal();
else r->v=a.v*b;
R *r;
}

friend of64& operator+(of64& a, of64& b)
{of64 *r;
r=a.val();
if(a.overf()||b.overf()) r->v=a.ErrVal();
else r->v=a.v+b.v;
R *r;
}

friend of64& operator+(of64& a, double b)
{of64 *r;
r=a.val();
if(a.overf()||doverf(b)) r->v=a.ErrVal();
else r->v=a.v+b;
R *r;
}

friend of64& operator-(of64& a, of64& b)
{of64 *r;
r=a.val();
if(a.overf()||b.overf()) r->v=a.ErrVal();
else r->v=a.v-b.v;
R *r;
}

friend of64& operator-(of64& a, double b)
{of64 *r;
r=a.val();
if(a.overf()||doverf(b)) r->v=a.ErrVal();
else r->v=a.v-b;
R *r;
}

friend of64& operator/(of64& a, of64& b)
{of64 *r;
r=a.val();
if(a.overf()||b.overf()||b.v==0.0) r->v=a.ErrVal();
else r->v=a.v/b.v;
R *r;
}

friend of64& operator/(of64& a, double b)
{of64 *r;
r=a.val();
if(a.overf()||doverf(b)||b==0.0) r->v=a.ErrVal();
else r->v=a.v/b;
R *r;
}

friend ostream& operator<<(ostream& ostr, of64& a)
{if( a.overf() ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;}

friend i32 operator==(of64& a, of64& b){R a.v==b.v;}
friend i32 operator!=(of64& a, of64& b){R a.v==b.v;}
friend i32 operator<=(of64& a, of64& b){R a.v<=b.v;}
friend i32 operator>=(of64& a, of64& b){R a.v>=b.v;}
friend i32 operator<( of64& a, of64& b){R a.v< b.v;}
friend i32 operator>( of64& a, of64& b){R a.v> b.v;}

double v;
static u32 ic;
static of64 *maa;
};

u32 of64::ic=0;
of64 maf[64];
of64* of64::maa=maf;


void fo(void)
{double di, dj, dk;
of64 ddi, ddj, ddk;
u32 i, j, k;
ou32 ui, uj, uk;
i32 ai, aj, ak;
oi32 aai, aaj, aak;

// ou32
ui.v=ui.ErrVal(); // ui.v=-1
--ui.v;
uj=ui+3u; // overflow +
if(uj.v!=-1) P("ou32 error +\n");

ui=3u;
uj=ui-7u; // overflow -
if(uj.v!=-1) P("ou32 error -\n");


ui=0xFFFFF;
uj=ui*(u32)0xFFFF; // overflow *
if(uj.v!=-1) P("ou32 error *\n");

ui=0xFFFFF;
uj=ui/(u32)0; // overflow /
if(uj.v!=-1) P("ou32 error / \n");

// oi32
aai.v=INT_MAX; aak.v=INT_MIN+1;
aaj.v=aai+4;
if(aaj.v!=aai.ErrVal()) P("oi32 error +\n");
aaj.v=aak-4;
if(aaj.v!=aai.ErrVal()) P("oi32 error -\n");
aaj.v=aak*2;
if(aaj.v!=aai.ErrVal()) P("oi32 error *\n");

// of64
ddi.v=DBL_MAX; ddi.v=ddi.v-1.0;
ddj = ddi+ 3.0;
if( !ddj.overf() ) P("of32 error +\n");

ddi.v=DBL_MIN; ddi.v=ddi.v+1.0;
ddj = ddi - 3.0;
if( !ddj.overf() ) P("of32 error -\n");

P("If no print but only this, all ok!\n");

}

int main(void)
{if( sizeof(u32)!=4 || sizeof(u16)!=2 )
{P("Basic type error\n"); R 0;}
fo();
R 0;
}

Öö Tiib

unread,
Jun 1, 2015, 3:22:36 PM6/1/15
to
On Monday, 1 June 2015 11:19:51 UTC+3, asetof...@gmail.com wrote:
> Instead of speak of nothing
> I.e. Smart pointers and exceptions
> c++11 C++17 etc
>
> Why do not speak how would you
> implement a class of 32 bit
> unsigned and signed that catch
> overflow store it in itself element?

Reinventing wheel?
https://safeint.codeplex.com

> The same for double, that allow
> Something as:

Double of most platforms has NaN, +Inf and -Inf values.

> a=b*c+y+564;
> Many other operation on a
> If(ov(a)==1)
> . than a is in overflow or
> . error in a
> . due some calculation
> . where a appear as result
> return a;
>
> It should be easy and useful..

It is not easy at all with integers after Intel C++, GNU C++ and clang
started to optimize such things like 'n + 1 < n' into 'false' when
'n' is signed. Excuse is that if it is not 'false' then it is
undefined behavior.

You should look into the code of SafeInt (I gave link above) to see
how "easy" it is. It has gone so cryptic only recently thanks to
those optimizations.

> Why no one speak about a class of
> fixed float point numbers
> [float points number for me are not
> ok]
> and big numbers with not
> fixed width (width can grow using
> available memory)?
>
> These arguments are too much
> difficult? Or you consider them
> unimportant?

Very important ... just that we tend to have already some code around for
such simpler things.

Paavo Helde

unread,
Jun 1, 2015, 3:40:00 PM6/1/15
to
asetof...@gmail.com wrote in news:84f86310-f763-4227-a9cc-
6bfee3...@googlegroups.com:

> This is my first attempt ...
> ....
> /*
> In one asm file compile for result .obj code
> section _DATA use32 public class=DATA
>
> global u32omul
> global u32oadd
> global u32osub
> global i32omul
> global i32oadd
> global i32osub
>
> section _BSS use32 public class=BSS
> section _TEXT use32 public class=CODE
>
> ;u32 __stdcall u32omul(u32 a, u32 b)
> ; 0ra, 4P_a, 8P_b

This is assembler, not C++, so off-topic in this group. On top of that,
it looks like it assumes some ancient 32-bit architecture.

Current hardware provides fast 64-bit operations, so if your goal is to
detect 32-bit overflow then it is trivial to do that in standard C++:

std::int32_t a = 10000000, b == 20000000;
std::int64_t result = std::int64_t(a)*std::int64_t(b);
if (result<std::numeric_limits<std::int32_t>::min() ||
result>std::numeric_limits<std::int32_t>::max()) {
// overflow
}

There are certainly also several existing libraries doing such things,
maybe a bit more efficiently.

Note that efficiency is important only if you do zillions of operations,
and in this case you should look in the direction of SSE/AVX, there are
probably some tricks for efficient overflow detection with them.

hth
Paavo

asetof...@gmail.com

unread,
Jun 2, 2015, 4:37:05 AM6/2/15
to
/*
In one asm file compile for result .obj code
section _DATA use32 public class=DATA

global u32omul
global u32oadd
global u32osub
global i32omul
global i32oadd
global i32osub

section _BSS use32 public class=BSS
section _TEXT use32 public class=CODE

;u32 __stdcall u32omul(u32 a, u32 b)
; 0ra, 4P_a, 8P_b
#define i8 signed char
#define u16 unsigned short
#define i16 signed short
#define u32 unsigned
#define i32 int
#define d64 double

// functions for detect u32 or i32 overflow in asm
extern "C" {
u32 __stdcall u32omul(u32 a, u32 b);
u32 __stdcall u32oadd(u32 a, u32 b);
u32 __stdcall u32osub(u32 a, u32 b);
i32 __stdcall i32omul(i32 a, i32 b);
i32 __stdcall i32oadd(i32 a, i32 b);
i32 __stdcall i32osub(i32 a, i32 b);
}

// 32 bit unsigned and signed with overflow
class ou32{
public:

ou32* val(void){u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;}
u32 ErrVal(void){R -1;} // value for error

ou32() {v=0;}
ou32(u32 a){v=a; }
ou32(i32 a){v=(u32)(a<0? -1: a);}
ou32(u8 a){v=a;}
ou32(i8 a){v=(u32)(a<0? -1: a);}
ou32(u16 a){v=a;}
ou32(i16 a){v=(u32)(a<0? -1: a);}

ou32& operator=(ou32& a){v=a.v; R *this;}
ou32& operator=(u32 a){v=a; R *this;}
ou32& operator=(i32 a){v=(u32)(a<0? -1: a); R *this;}
ou32& operator=(u16 a){v=a; R *this;}
ou32& operator=(i16 a){v=(u32)(a<0? -1: a); R *this;}
ou32& operator=(u8 a){v=a; R *this;}
ou32& operator=(i8 a){v=(u32)(a<0? -1: a); R *this;}

ou32& operator*=(ou32& a){v=u32omul(v, a.v); R *this;}
ou32& operator+=(ou32& a){v=u32oadd(v, a.v); R *this;}
ou32& operator-=(ou32& a){v=u32osub(v, a.v); R *this;}
ou32& operator/=(ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1;
else v=v/a.v;
R *this;
}

ou32& operator++(){v=(v==-1? -1: ++v); R *this;}
ou32& operator++(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) ++v; R *t;}
ou32& operator--(){v=(v==-1? -1: --v); R *this;}
ou32& operator--(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) --v; R *t;}

friend ou32& operator*(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32omul(a.v, b.v); R *r;}
friend ou32& operator+(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32oadd(a.v, b.v); R *r;}
friend ou32& operator-(ou32& a, ou32& b)
{ou32 *r; r=a.val(); r->v=u32osub(a.v, b.v); R *r;}
friend ou32& operator/(ou32& a, ou32& b)
{ou32 *r;
r=a.val();
if(a.v==-1||b.v==-1||b.v==0) r->v=-1;
else r->v=a.v/b.v;
R *r;
}

friend ostream& operator<<(ostream& ostr, ou32& a)
{if( a.v==-1 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;}

friend i32 operator==(ou32& a, ou32& b){R a.v==b.v;}
friend i32 operator!=(ou32& a, ou32& b){R a.v==b.v;}
friend i32 operator<=(ou32& a, ou32& b){R a.v<=b.v;}
friend i32 operator>=(ou32& a, ou32& b){R a.v>=b.v;}
friend i32 operator<( ou32& a, ou32& b){R a.v< b.v;}
friend i32 operator>( ou32& a, ou32& b){R a.v> b.v;}

friend i32 operator==(ou32& a, u32 b){R a.v==b;}
friend i32 operator!=(ou32& a, u32 b){R a.v==b;}
friend i32 operator<=(ou32& a, u32 b){R a.v<=b;}
friend i32 operator>=(ou32& a, u32 b){R a.v>=b;}
friend i32 operator<( ou32& a, u32 b){R a.v< b;}
friend i32 operator>( ou32& a, u32 b){R a.v> b;}

u32 v;
static u32 ic;
static ou32 *maa;
};

u32 ou32::ic=0;
ou32 ma[64];
ou32* ou32::maa=ma;

void fo(void)
{u32 i, j, k;
ou32 ui, uj, uk;

// ou32
ui.v=ui.ErrVal(); // ui.v=-1
--ui.v;
uj=ui+(ou32&)3u; // overflow +
if(uj.v!=-1) P("ou32 error +\n");

ui=3u;
uj=ui-(ou32)7u; // overflow -
if(uj.v!=-1) P("ou32 error -\n");


ui=0xFFFFF;
uj=ui*(u32)0xFFFF; // overflow *
if(uj.v!=-1) P("ou32 error *\n");

ui=0xFFFFF;
uj=ui/(u32)0; // overflow /
if(uj.v!=-1) P("ou32 error / \n");
}

int main(void)
{if( sizeof(u32)!=4 || sizeof(u16)!=2 )
{P("Basic type error\n"); R 0;}
fo();

R 0;
}
/*
Error E2031 over.cpp 219: Cannot cast from 'unsigned int' to 'ou32 &' in function
fo()
Error E2093 over.cpp 223: 'operator-' not implemented in type 'ou32' for arguments
of the same type in function fo()
Error E2094 over.cpp 228: 'operator*' not implemented in type 'ou32' for arguments
of type 'unsigned int' in function fo()
Error E2094 over.cpp 232: 'operator/' not implemented in type 'ou32' for arguments
of type 'unsigned int' in function fo()
Warning W8008 over.cpp 237: Condition is always false in function main()
Warning W8066 over.cpp 238: Unreachable code in function main()
*** 4 errors in Compile ***

Why not compile? in the book say that "ou32(u32 a){v=a; }"
does the conversion from unsigned to ou32... or i read wrong?

Is it possible define a conversion from unsigned[or type]
to ou32 that use the circular array ma[64]
[possible some cast function]?

Thank you
*/

David Brown

unread,
Jun 2, 2015, 4:45:29 AM6/2/15
to
I /think/ the first error is because you asked to convert the u32 to a
ou32&, while you only have a defined conversion to ou32. It makes no
sense to cast to ou32& in fo().

However, if you try writing C++, rather than a mixture of assembly,
toolchain-specific extensions, and complete gibberish, then it would be
a lot easier to help you.



asetof...@gmail.com

unread,
Jun 2, 2015, 6:16:08 AM6/2/15
to
Just add some "const" and
All ok this doing what I thought
even if I not find where I
wrote that...
Thank you
friend ou32* val(void)
{u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;}

friend u32 ErrVal(void){R -1;} // value for error

ou32() {v=0;}
ou32(u32 a){v=a;}
ou32(i32 a){v=(u32)(a<0? -1: a);}
ou32(u8 a){v=a;}
ou32(i8 a){v=(u32)(a<0? -1: a);}
ou32(u16 a){v=a;}
ou32(i16 a){v=(u32)(a<0? -1: a);}
ou32(const ou32& a){v=a.v;}

ou32& operator=(const ou32& a){v=a.v; R *this;}
ou32& operator=(u32 a){v=a; R *this;}
ou32& operator=(i32 a){v=(u32)(a<0? -1: a); R *this;}
ou32& operator=(u16 a){v=a; R *this;}
ou32& operator=(i16 a){v=(u32)(a<0? -1: a); R *this;}
ou32& operator=(u8 a){v=a; R *this;}
ou32& operator=(i8 a){v=(u32)(a<0? -1: a); R *this;}

ou32& operator*=(const ou32& a){v=u32omul(v, a.v); R *this;}
ou32& operator+=(const ou32& a){v=u32oadd(v, a.v); R *this;}
ou32& operator-=(const ou32& a){v=u32osub(v, a.v); R *this;}
ou32& operator/=(const ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1;
else v=v/a.v;
R *this;
}

ou32& operator++(){v=(v==-1? -1: ++v); R *this;}
ou32& operator++(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) ++v; R *t;}
ou32& operator--(){v=(v==-1? -1: --v); R *this;}
ou32& operator--(int)
{ou32 *t; t=val(); *t=*this; if(v!=-1) --v; R *t;}

friend ou32& operator*(const ou32& a, const ou32& b)
{ou32 *r; r=val(); r->v=u32omul(a.v, b.v); R *r;}
friend ou32& operator+(const ou32& a, const ou32& b)
{ou32 *r; r=val(); r->v=u32oadd(a.v, b.v); R *r;}
friend ou32& operator-(const ou32& a, const ou32& b)
{ou32 *r; r=val(); r->v=u32osub(a.v, b.v); R *r;}
friend ou32& operator/(const ou32& a, const ou32& b)
{ou32 *r;
r=val();
if(a.v==-1||b.v==-1||b.v==0) r->v=-1;
else r->v=a.v/b.v;
R *r;
}

friend ostream& operator<<(ostream& ostr, ou32& a)
{if( a.v==-1 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;}

friend i32 operator==(const ou32& a, const ou32& b){R a.v==b.v;}
friend i32 operator!=(const ou32& a, const ou32& b){R a.v==b.v;}
friend i32 operator<=(const ou32& a, const ou32& b){R a.v<=b.v;}
friend i32 operator>=(const ou32& a, const ou32& b){R a.v>=b.v;}
friend i32 operator<( const ou32& a, const ou32& b){R a.v< b.v;}
friend i32 operator>( const ou32& a, const ou32& b){R a.v> b.v;}

u32 v;
static u32 ic;
static ou32 *maa;
};

u32 ou32::ic=0;
ou32 ma[64];
ou32* ou32::maa=ma;

void fo(void)
{u32 i, j, k;
ou32 ui, uj, uk;

// ou32
ui.v=ErrVal(); // ui.v=-1
--ui.v;
uj=ui+3u; // overflow +
if(uj.v!=-1) P("ou32 error +\n");

ui=3u;
uj=ui-(ou32)7u; // overflow -
if(uj.v!=-1) P("ou32 error -\n");


ui=0xFFFFF;
uj=ui*(u32)0xFFFF; // overflow *
if(uj.v!=-1) P("ou32 error *\n");

ui=0xFFFFF;
uj=ui/(u32)0; // overflow /
if(uj.v!=-1) P("ou32 error / \n");

P("If no print but only this: all ok\n");

}

int main(void)
{if( sizeof(u32)!=4 || sizeof(u16)!=2 )
{P("Basic type error\n"); R 0;}
fo();

R 0;
}
/*
; ui.v=ErrVal(); // ui.v=-1
;
mov dword ptr [ebp-4],-1
;
; --ui.v;
;
dec dword ptr [ebp-4]
;
; uj=ui+3u; // overflow +
;
mov dword ptr [ebp-16],3
mov eax,dword ptr [ebx]
inc dword ptr [ebx]
cmp dword ptr [ebx],63
jb short @2
xor edx,edx
mov dword ptr [ebx],edx

#sembra che converte 3u in ou32 utilizzando l'array tramite val()
#inline [**come dovrebbe essere**]
# ma io non ho fatto la conversione u32 a ou32 tramite val()
#tutto automatico?

@2:
@3:
mov esi,eax
shl esi,2
add esi,dword ptr [@@ou32@maa]
push dword ptr [ebp-16]
push dword ptr [ebp-4]
call @u32oadd
mov dword ptr [esi],eax
mov eax,esi
mov edx,dword ptr [eax]
mov dword ptr [edi],edx

#chiama l'operatore + (ou32 ou32) anche esso inline... ok sembra
;
; if(uj.v!=-1) P("ou32 error +\n");
;
cmp dword ptr [edi],-1
je short @4
push offset s@
call @_printf
pop ecx
;
;
; ui=3u;
;
@4:
mov dword ptr [ebp-4],3
;
; uj=ui-(ou32)7u; // overflow -
;
mov dword ptr [ebp-20],7
mov eax,dword ptr [ebx]
inc dword ptr [ebx]
cmp dword ptr [ebx],63
jb short @5
xor ecx,ecx
mov dword ptr [ebx],ecx
@5:
@6:
mov esi,eax
shl esi,2
add esi,dword ptr [@@ou32@maa]
push dword ptr [ebp-20]
push dword ptr [ebp-4]
call @u32osub
mov dword ptr [esi],eax
mov eax,esi
mov edx,dword ptr [eax]
mov dword ptr [edi],edx
;
; if(uj.v!=-1) P("ou32 error -\n");
;
cmp dword ptr [edi],-1
je short @7
push offset s@+14
call @_printf
pop ecx
;
;
;
; ui=0xFFFFF;
;
@7:
mov dword ptr [ebp-4],1048575
;
; uj=ui*(u32)0xFFFF; // overflow *
;
mov dword ptr [ebp-24],65535
mov eax,dword ptr [ebx]
inc dword ptr [ebx]
cmp dword ptr [ebx],63
jb short @8
xor ecx,ecx
mov dword ptr [ebx],ecx
@8:
@9:
mov esi,eax
shl esi,2
add esi,dword ptr [@@ou32@maa]
push dword ptr [ebp-24]
push dword ptr [ebp-4]
call @u32omul
mov dword ptr [esi],eax
mov eax,esi
mov edx,dword ptr [eax]
mov dword ptr [edi],edx
;
; if(uj.v!=-1) P("ou32 error *\n");
;
cmp dword ptr [edi],-1
je short @10
push offset s@+28
call @_printf
pop ecx
;
;
; ui=0xFFFFF;
;
@10:
mov dword ptr [ebp-4],1048575
;
; uj=ui/(u32)0; // overflow /
;
xor ecx,ecx
mov dword ptr [ebp-28],ecx
mov eax,dword ptr [ebx]
inc dword ptr [ebx]
cmp dword ptr [ebx],63
jb short @11
xor edx,edx
mov dword ptr [ebx],edx
@11:
@12:
mov ecx,eax
shl ecx,2
add ecx,dword ptr [@@ou32@maa]
cmp dword ptr [ebp-4],-1
je short @15
cmp dword ptr [ebp-28],-1
je short @15
cmp dword ptr [ebp-28],0
jne short @13
@15:
mov dword ptr [ecx],-1
jmp short @14
@13:
mov eax,dword ptr [ebp-4]
xor edx,edx
div dword ptr [ebp-28]
mov dword ptr [ecx],eax
@14:
mov eax,ecx
mov ecx,dword ptr [eax]
mov dword ptr [edi],ecx
;
; if(uj.v!=-1) P("ou32 error / \n");
;
?live16387@224: ; EDI = &uj
cmp dword ptr [edi],-1
je short @16
push offset s@+42
call @_printf
pop ecx
;
;
; P("If no print but only this: all ok\n");
;
?live16387@240: ;
@16:
push offset s@+57
call @_printf
pop ecx
;
;
; }
;
*/

red floyd

unread,
Jun 2, 2015, 12:50:13 PM6/2/15
to
On 6/2/2015 3:15 AM, asetof...@gmail.com wrote:
> [redacted]

What part of "x86 Assembly Language isn't C++" are you having trouble
understanding?

Öö Tiib

unread,
Jun 2, 2015, 5:27:18 PM6/2/15
to
He is perhaps just joking. First asked why we do not discuss
classes for safe and saturated numeric computing and then replies
himself with assembler for processor of past millennia.

asetof...@gmail.com

unread,
Jun 2, 2015, 7:30:01 PM6/2/15
to
Red wrote:"
What part of "x86 Assembly Language isn't C++" are you having trouble
understanding?"

I not understand const...
For me the type& arguments
in functions are all pointers but
for my definition I
not change them
so they are as const ...

If I want change one argument
in a function I would use
funt(T* arg)
not
funt(T& arg)

Because in funt(&v)
I can see it changes v when
function is called

For the remain C++ offer good
solution to problems
sometime using some
little workaround
in a little subset of C++

all I not see or use,
and not want to see
it is too much complex for me
and perhaps for all you too

asetof...@gmail.com

unread,
Jun 3, 2015, 12:16:28 PM6/3/15
to
I wrote:"
ou32& operator*=(const ou32& a){v=u32omul(v, a.v); R *this;}
ou32& operator+=(const ou32& a){v=u32oadd(v, a.v); R *this;}
ou32& operator-=(const ou32& a){v=u32osub(v, a.v); R *this;}
ou32& operator/=(const ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1;

else v=v/a.v;
R *this;
}"

So the above would not allow this
ou32 a;
a=39; a/=a;
But the compiler compile and
the program run seems ok
with a=1
0 new messages