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

No _serious programming language lacks "evil" macros ! !

77 views
Skip to first unread message

Jeff-Relf.Me

unread,
Mar 30, 2017, 4:07:08 PM3/30/17
to
2 weeks ago, you ( DFS ) showed me your "readable and maintainable" code:

int isleapyear(int yr) {
if(((yr%4==0) && (yr%100!=0)) || (yr%400==0))
{return 0;}
return -1;
} // oackac$fve$1...@dont-email.me

Then I showed you my "kooky and oddly formatted" version of it:

#define isLeapYear(y) ( !( y%400 ) || y%100 && !( y%4 ) )

No _serious programming language lacks "evil" macros ! !

Shannon Entropy ( poorly ) estimates:
the minimum number of bits needed to _encode data.

But I don't want to _encode/_decode anything; even if I did,
Shannon Entropy can't predict the algorithm I'd use.

In thermodynamics "entropy" is how uniform the heat energy is;
i.e. how _spent it is, so it can't produce "Work" ( force*distance ).
In cosmology, we call this "heat death", the end of all "life".

What does "spent energy" have to do with compression ? ! nothing.

Jeff-Relf.Me

unread,
Mar 30, 2017, 11:21:28 PM3/30/17
to
You ( DFS ) asked me:
> > What does "spent energy" have to do with compression ? ! nothing.
>
> What's all this overmedicated rambling about?

"Shannon Entropy" is misnomer, and I've no use for it.

> It's a tiny program - around 50 lines probably

Yours was 62 lines, 90 columns, not counting the #includes;
mine is 21 lines, 74 columns, no macros, Sh() is printf( L"\n" ); to wit:

int Len, _Len, Row, Cnt ; float Dist, BitsRow, Bits ;
wchar_t TheCh, Data[] = L"Abbcccdddd1223334444" ;
Row = Bits = 0, Len = sizeof Data / sizeof *Data - 1 ;
Sh( L"%d Glyphs in \" %s \".", Len, Data );
Sh();
Sh( L" # Glyph Cnt Dist D*log2(D) H(X) sum ");
Sh( L" -- ----- --- ------ --------- ---------- ");
Row: Row++, _Len = Len, TheCh = Cnt = 0 ;

while( --_Len >= 0 ) { wchar_t &aCh = Data[ _Len ];
if ( !aCh ) continue ; if ( !TheCh ) TheCh = aCh ;
if ( aCh == TheCh ) aCh = 0, Cnt++ ; }

if ( !Cnt ) goto Done ;
Dist = float( Cnt )/Len, BitsRow = Dist*log2f( Dist ), Bits += BitsRow ;
Sh( L" %d %c %d %.3f %.3f %.5f ",
Row, TheCh, Cnt, Dist, BitsRow, -1*Bits ); goto Row ;

Done: Sh();
Sh( L" Shannon Entropy: %.5f bits. ", -1*Bits );
Sh( L" Metric Entropy: %.5f bits per Glyph. ", -1*Bits / Len );

// 20 Glyphs in " Abbcccdddd1223334444 ".
//
// # Glyph Cnt Dist D*log2(D) H(X) sum
// -- ----- --- ------ --------- ----------
// 1 A 1 0.050 -0.216 0.21610
// 2 b 2 0.100 -0.332 0.54829
// 3 c 3 0.150 -0.411 0.95883
// 4 d 4 0.200 -0.464 1.42322
// 5 1 1 0.050 -0.216 1.63932
// 6 2 2 0.100 -0.332 1.97151
// 7 3 3 0.150 -0.411 2.38205
// 8 4 4 0.200 -0.464 2.84644
//
// Shannon Entropy: 2.84644 bits.
// Metric Entropy: 0.14232 bits per Glyph.

Juha Nieminen

unread,
Apr 3, 2017, 2:12:16 AM4/3/17
to
In comp.lang.c++ Jeff-Relf.Me wrote:
> Then I showed you my "kooky and oddly formatted" version of it:

Who are you talking to?

> #define isLeapYear(y) ( !( y%400 ) || y%100 && !( y%4 ) )

And you immediately show the danger of using macros. Just consider what
happens if you call it eg. like isLeapYear(a+b).

Even when you fix the macro, there's still the problem of calling it
like isLeapYear(someReallyExpensiveFunctionThatTakesAMinuteToReturn()).

Jeff-Relf.Me

unread,
Apr 3, 2017, 3:42:54 AM4/3/17
to
> > 2 weeks ago, you ( DFS ) showed me
> > your "readable and maintainable" code:
> >
> > int isleapyear(int yr) {
> > if(((yr%4==0) && (yr%100!=0)) || (yr%400==0))
> > {return 0;}
> > return -1;
> > } // oackac$fve$1...@dont-email.me
> >
> > Then I showed you my "kooky and oddly formatted" version of it:
> >
> > #define isLeapYear(y) ( !( y%400 ) || y%100 && !( y%4 ) )
>
> Who are you talking to?

Mr. DFS, see above; the thread ( oldest first ):

JeffRelf Jeff-R...@Mar.30--1.54A.Seattle.2017
PeterKöhlmann obii4i$m36$1...@dont-email.me
MrChrisV njtpdc5354qqii10m...@4ax.com
MrDFS obj166$7rj$3...@dont-email.me
JeffRelf Jeff-R...@Mar.30--1.07P.Seattle.2017
Juha_Nieminen obsp3m$11mu$1...@adenine.netfront.net

> Consider what happens if you call it eg. like isLeapYear(a+b).
> Even when you fix the macro, there's still the problem of calling it
> like isLeapYear(someReallyExpensiveFunctionThatTakesAMinuteToReturn()).

Thanks for dreaming up scary scenarios however,
like guns and knives, macros are useful too, not just dangerous.
No _serious programming language lacks "evil" macros.

Here's some more "scary" macros for you...

MicroSoft's WinMerge uses this this algorithm:
" Dynamic Programming | Set 4 (Longest Common Subsequence) "
http://www.geeksforgeeks.org/dynamic-programming-set-4-longest-common-subsequence/

My code, below, produces the same results as WinMerge:

// ScreenShot: http://Jeff-Relf.Me/Diff.PNG
// Help/Settings: http://Jeff-Relf.Me/X.HTM

// _FileCmp(), below, records thousands of matching lines ( text ),
// LeftOlder vs RightNewer, using the "LongestCommonSequence"
// ( shortest diffs ) algorithm.
//
// BB is a pointer to the start of
// a dynamic array of ( contiguous ) pointers ( lines );
// PP points to the end of the array.
//
// BB and PP are from the LeftOlder file.
// _BB and _PP are from the RightNewer file.

_FileCmp( LnA BB, LnA _BB, LnA PP, LnA _PP, LnT &Ln ) {

int Rows = PP - BB + 1, Cols = _PP - _BB + 1 ; u64 Row = Rows, Col = Cols ;

// Allocate a " LeftOlderLines * RightNewerLines " table of 32 bit integers
// to store all LongestCommonSequence Lengths.

pInt _Table = (pInt)MallocTmp( Rows * Cols * szInt );
{ LoopRow( Rows ) { LoopCol( Cols ) {

if ( !Row || !Col ) { Table( Row, Col ) = 0 ; continue ; }
if ( aMatch ) Table( Row, Col ) = Table( Row - 1, Col - 1 ) + 1 ;
else Table( Row, Col ) = ER( Table( Row, Col - 1 ), Table( Row - 1, Col ) ); } } }

// " Ln " is a dynamic array of thousands of ( contiguous ) 64 bit pointers,
// repurosed to store two 32 bit intergers ( Row and Col ) in a pointer.
// If both files are the same, with X Lines, it'll store X RowCol pairs.
//
// The first " StoreRowColumn ", below, stores the end of the files;
// the last is first, and vice versa; it's reversed.

Zero( Ln ), StoreRowColumn;
while ( Row > 0 && Col > 0 )
if ( aMatch ) StoreRowColumn ;
else Table( Row, Col - 1 ) > Table( Row - 1, Col ) ? Col-- : Row-- ; }

Near Globals:

// Access " _Table ", a One Dimensional array, as if it were Two Dimensional.
#define Table( i, j ) _Table[ ( j ) * Rows + i ]

// F[-1] is the ( 16 bit ) length of the leading whitespace.
#define aMatch ( F = BB[ Row - 1 ], _F = _BB[ Col - 1 ], F[-1] == _F[-1] && Eq( F, _F ) )

// Store the matching lines as line numbers from LeftOlder and RightNewer
#define StoreRowColumn ( Inc( Ln ) = LnP( Row - 1 << 32 | Col - 1 ), Row--, Col-- )

LnP F, _F ;

Far Globals:

#define Zero( X ) memset( & X, 0, sizeof X )
#define Eq !strCmp

#define LoopRows( N ) int Row = -1, eRow = ( N ) - 1 ; while ( ++Row <= eRow )
#define LoopCols( N ) int Col = -1, eCol = ( N ) - 1 ; while ( ++Col <= eCol )

typedef wchar_t wchar ; typedef wchar *LnP ; typedef LnP *LnA ;
typedef int *pInt ; typedef void *Void_P ; typedef unsigned __int64 u64 ;
const int szInt = sizeof( int );

struct LnT { LnA BB, PP, maxPP ; }; LnT Ln ;

// " Inc() ", below, dynamically allocates thousands of ( contiguous ) pointers.
// When diff is done, " Temp_Heap " is simply destroyed.

template < typename TyT, typename TyA, typename TyP >
TyP & Inc( TyT & Xx, int N ) { int I_PP, I_PP_New, I_maxPP, rv, Sz, Temp_Heap = N >= 0 ; if ( !Temp_Heap ) N = 1 ;
I_PP = !Xx.PP ? -1 : Xx.PP - Xx.BB, I_maxPP = !Xx.maxPP ? 0 : Xx.maxPP - Xx.BB, I_PP_New = I_PP + N ; if( I_maxPP < 0 ) exit(1);
if ( I_PP_New < I_maxPP ) { OK: return Xx.PP = Xx.BB + I_PP_New, *Xx.PP ; }
rv = ER( 1024, 3 * I_PP_New ), Sz = 16 + rv * szPtr ;
Xx.maxPP = Xx.BB = TyA( Temp_Heap ? ReAllocTmp( Xx.BB, ++I_PP * szPtr, Sz ) : realloc( Xx.BB, Sz ) ), Xx.maxPP += rv ;
if( !Xx.BB ) exit(1); goto OK ; }

LnP &Inc( LnT &Ln ) { return Inc< LnT, LnA, LnP>( Ln, 1 ) ; }

LnP ReAllocTmp( Void_P B⁰, int Sz⁰, int Sz ) { Void_P B = B⁰ ; if ( Sz > 0 && Sz > Sz⁰ ) B = MallocTmp( Sz );
if ( B⁰ && Sz⁰ > 0 ) memmove( B, B⁰, Sz⁰ ); return LnP( B ); }

Juha Nieminen

unread,
Apr 4, 2017, 2:08:46 AM4/4/17
to
In comp.lang.c++ Jeff-Relf.Me wrote:
>> > #define isLeapYear(y) ( !( y%400 ) || y%100 && !( y%4 ) )

>> Consider what happens if you call it eg. like isLeapYear(a+b).
>> Even when you fix the macro, there's still the problem of calling it
>> like isLeapYear(someReallyExpensiveFunctionThatTakesAMinuteToReturn()).
>
> Thanks for dreaming up scary scenarios however,

Dreaming up scary scenarios... Something like isLeapYear(a+b) is not
a stretch in any way. It's something that anybody would write. And your
macro would give the wrong answer.

chrisv

unread,
Apr 4, 2017, 8:24:09 AM4/4/17
to
Juha Nieminen wrote:

>In comp.lang.c++ Jeff-Relf.Me wrote:

*plonk*

Jerry Stuckle

unread,
Apr 4, 2017, 9:07:04 AM4/4/17
to
And it is easily fixed by coding the macro correctly:

#define isLeapYear(y) ( !( (y)%400 ) || (y)%100 && !( (y)%4 ) )

You can code incorrectly in *any* language.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Jerry Stuckle

unread,
Apr 4, 2017, 9:08:44 AM4/4/17
to
On 4/4/2017 9:06 AM, Jerry Stuckle wrote:
> On 4/4/2017 2:08 AM, Juha Nieminen wrote:
>> In comp.lang.c++ Jeff-Relf.Me wrote:
>>>>> #define isLeapYear(y) ( !( y%400 ) || y%100 && !( y%4 ) )
>>
>>>> Consider what happens if you call it eg. like isLeapYear(a+b).
>>>> Even when you fix the macro, there's still the problem of calling it
>>>> like isLeapYear(someReallyExpensiveFunctionThatTakesAMinuteToReturn()).
>>>
>>> Thanks for dreaming up scary scenarios however,
>>
>> Dreaming up scary scenarios... Something like isLeapYear(a+b) is not
>> a stretch in any way. It's something that anybody would write. And your
>> macro would give the wrong answer.
>>
>
> And it is easily fixed by coding the macro correctly:
>
> #define isLeapYear(y) ( !( (y)%400 ) || (y)%100 && !( (y)%4 ) )
>
> You can code incorrectly in *any* language.
>

(too fast on the send button)

That still doesn't solve the problem of isLeapYear(j++). But it doesn't
make macros any more or less evil than other statements.

Silver-Tongued Heel

unread,
Apr 4, 2017, 12:43:52 PM4/4/17
to
LOL.


--
Silver Tongued-Heel
OpenMedia & EFF Member
Gab.ai: @silverslimer

Jeff-Relf.Me

unread,
Apr 4, 2017, 1:47:58 PM4/4/17
to
Jerry Stuckle, Juha Nieminen, Mr. DFS... this would be be better:

inline int isLeapYear( int y ) { return !( y%400 ) || y%100 && !( y%4 ); }

You know it's inlined when you can't set a break point on it.

Previously ( Jeff-R...@Mar.29--1.34P.Seattle.2017 ), I asked DFS: <<

Why reinvent the "mktime()" wheel, doesn't Python have it ?

i64 aDate ; tm DayRec = {};
DayRec.tm_mon = Month ; // 0..11
DayRec.tm_mday = DayOfTheMonth ; // 1..31
DayRec.tm_year = Year - 1900, aDate = mktime( &DayRec );

You can add 200 days to DayRec.tm_mday,
and call mktime( &DayRec ) to normalize .tm_mday to 1..31,
adjusting .tm_mon and .tm_year accordingly. >>


He didn't answer.

Jerry Stuckle

unread,
Apr 4, 2017, 2:09:06 PM4/4/17
to
On 4/4/2017 1:47 PM, Jeff-Relf.Me@. wrote:
> Jerry Stuckle, Juha Nieminen, Mr. DFS... this would be be better:
>
> inline int isLeapYear( int y ) { return !( y%400 ) || y%100 && !( y%4 ); }
>
> You know it's inlined when you can't set a break point on it.
>

That isn't a macro.

Jeff-Relf.Me

unread,
Apr 24, 2017, 2:41:03 PM4/24/17
to
I see your Python code for adding dates, Mr. DFS; to wit:

start = datetime.strptime( sys.argv[2], '%Y-%m-%d' ).date()
start.weekday()

When I hit "Cal" ( on my ToolBar, X.EXE ) I get:

10 11 12 13 14 15 16
17 18 19 20 21 22 23
24* 25 26 27 28 29 30
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
Mon Tue Wed Thr Fri Sat Sun-- 11:40 A -- 15

Today, the 24th of April, is asterisked.

The code:

int DaysBack ; u64 s, nowAge ; LnP B = _B_Sh, D = B ; tm *Cal ;
s = nowAge = time(0), Cal = SecToCalendar( s ), DaysBack = 14 ;

// Go back more than 14 days, to start on a Monday.
DaysBack += !Cal->tm_wday ? 6 : Cal->tm_wday - 1 ;
s -= DaysBack * 24*60*60 ;
{ LoopJ(7*7)
Cal = SecToCalendar( s ), D += Str( D, L"%2d%c%s", Cal->tm_mday,
s == nowAge ? '*' : 32, ( J % 7 ) == 6 ? L"\n" : L" " ),
s += 24*60*60 ; }

D += Str( D, L"Mon Tue Wed Thr Fri Sat Sun" );
D += Str( D, L"-- %d:%02d %c -- %02d\n",
Hour, Min, PM ? 'P': 'A', Sec ), Sh( B );

Globals:

// <time.h>: time_t, time(), localtime(), tm, and _wasctime().
// Hour, Min, PM, and Sec came from _wasctime(); code not shown.
// Sh() is like printf().

#define Str swprintf
#define SecToCalendar( S ) localtime( ( time_t * ) &S )
#define LoopJ( N ) int J = -1, eJ = (N) - 1 ; while ( ++J <= eJ )

typedef unsigned __int64 u64 ; typedef wchar *LnP ;
LnP _B_Sh ; // 4 MegaByte scratch buffer.
0 new messages