Maker Pro
Maker Pro

Larkin, Power BASIC cannot be THAT good:

J

Jan Panteltje

Without the dynamic allocation, the rest of the errors figure...


Say, what's the "3D" in this showing up for? Did you copy&paste
wrong, or did my message get encoded stupid, or did yours?


Yes, copy and paste, but I left it as it had not enough stack space anyways,,,
I use it fairly regularly. Despite being DOS, an exorbitantly
inefficient environment, it still runs on XP, and does things that (in
lieu of a similarly powerful scripting language) are satisfactory for
my purposes. I could do C, but I don't know it nearly as well as I
know QuickBasic.

Tim

BASIC is so simple to use, but I have so much C code and apps written now that
complicated things like networking would take me a hard time in BASIC.
But this one is nice to have around for doing some quick calculations I think.
There are so many of those high level languages with powerful networking
around these days,,,
C is for me some universal thing that does it all without me having to learn
yet an other language.
 
A

Anssi Saari

Tim Williams said:
In other languages--

Compiled in FreeBASIC version 0.17b.

-=-=-
'$DYNAMIC
DIM a(64000000) AS SHORT
DIM s(64000000) AS INTEGER
DIM i AS INTEGER

Start! = TIMER
FOR i = 0 TO 63999999
s(i) += a(i)
NEXT

PRINT USING "One pass in ##.### seconds."; TIMER - Start!;
-=-=-

Typical output:

E:\PROGRA~1\FreeBASIC>test
One pass in 1.439 seconds.
E:\PROGRA~1\FreeBASIC>test
One pass in 1.818 seconds.

I get really weird time printouts with that. Using FreeBasic 0.18.

time ./test
One pass in 19.935 seconds.
../test 0.26s user 0.18s system 95% cpu 0.453 total
 
X

xray

The run time in C is 13 seconds here on a 1GHz processor.
Can you specify your 'old HP computer' ?

I can win maybe 1 second by writing the code a bit different.
And a 3GHz would do it in 12 / 4 = 4 seconds...
A bigger cache would help a bit perhaps.

A Cray would be even better.


What does you C code look like? Mine is in the other posting.

Else you goofed a factor 10.

Seems to me anyways :)


Here's my PowerBasic code:

===================================================
#COMPILE EXE

' SUM.BAS
' TRY SUMMING A LOT OF INTS INTO AN ARRAY OF LONGS...

' JL MAY 14, 2009 PBCC4

FUNCTION PBMAIN () AS LONG

COLOR 15,9
CLS

DIM A(64000000) AS INTEGER ' INPUT ADC SAMPLES
DIM S(64000000) AS LONG ' SUMMING ARRAY
DIM X AS LONG
DIM Y AS LONG
DIM Z AS LONG

' INIT INPUT ARRAY TO RANDOM-ISH VALUES...

FOR X = 1 TO 64000000 ' THIS IS MUCH FASTER
A(X) = X AND 32767 ' THAN CALLING RND()!
NEXT

T! = TIMER

PRINT "Start... ";

FOR Y = 1 TO 10

FOR X = 1 TO 64000000
S(X) = S(X) + A(X)
NEXT

NEXT

PRINT "Done"

E! = TIMER - T!
PRINT USING$("Time per loop ##.### sec ##.## ns/add", E!/10, 1E9*E!/(10*64E6))
PRINT

' DISPLAY SOME RESULTS TO MAKE SURE IT REALLY WORKED...

FOR X = 1 TO 10
PRINT X, A(X), S(X)
NEXT

PRINT

FOR X = 63999001 TO 63999010
PRINT X, A(X), S(X)
NEXT

INPUT A$


END FUNCTION


===================================================

On my computer, a 1.9 GHz Xeon with 2G ram, winXP, I get this
result...

Start... Done
Time per loop 0.231 sec 3.61 ns/add

1 1 10
2 2 20
3 3 30
4 4 40
5 5 50
6 6 60
7 7 70
8 8 80
9 9 90
10 10 100

63999001 3097 30970
63999002 3098 30980
63999003 3099 30990
63999004 3100 31000
63999005 3101 31010
63999006 3102 31020
63999007 3103 31030
63999008 3104 31040
63999009 3105 31050
63999010 3106 31060

===================================================

One of my guys did a C version (I refuse to program in C) to run on
the Kontron under Linux, a slightly slower CPU, 2G ram. I asked him
for his source code, and he spent about a half hour cleaning it up to
be presentable... which I asked him NOT to do. Anyhow, here it is:

* mathsmash.c - a VERY crude benchmark
*
* time the sum of 64-million 16-bit integers into 64-million 32-integer sums.
*
* gcc -O3 mathsmash.c -o mathsmash.o
*
* NOTE: The loop is performed 10 times to make the measurement duration more reasonable.
*
* Timing is done by observation or including the system("date") functions.
*
*
*/

#define SIXTYFOURMILLION (0x100000 * 64)
#define DATA_ARRAY_SIZE SIXTYFOURMILLION

#include <stdio.h>

int main()
{
unsigned short *inbound_data;

unsigned int *sum_data;


int multiply;

unsigned long index = 0;

#if 0
/* Initialize data */
printf ("Zeroing data\n");
#endif

inbound_data = (unsigned short *) malloc (sizeof ( short ) *
DATA_ARRAY_SIZE);
sum_data = (unsigned *) malloc ((sizeof ( int )) *
DATA_ARRAY_SIZE);

printf ("inb_ptr = 0x%08x, sum_ptr= 0x%08x\n", inbound_data,
sum_data);

printf ("\n START sum operation...\n");


// system ("date");

for (multiply = 0; multiply < 10; multiply ++) // 10 x
{
for ( index = 0; index < DATA_ARRAY_SIZE; ++index )
sum_data[index] += inbound_data[index];
}

printf ("\n END sum operation...\n");

// system ("date");


}

===================================================

He commented out the system date things because they're buggy or
something, and timed it with his wristwatch at about 0.25 seconds per
64M add, about the same as the PowerBasic.

He used subscripts, not pointers, as I did. The inner loop compiles to
five instructions.

My program is prettier.

John

Re: My program is prettier.

I don't think so. For one thing your program is shouting.
 
F

FatBytestard

I get really weird time printouts with that. Using FreeBasic 0.18.

time ./test
One pass in 19.935 seconds.
./test 0.26s user 0.18s system 95% cpu 0.453 total


That would be (I guess is) weird.
 
T

Tim Williams

On Fri, 15 May 2009 11:27:55 -0700, John Larkin
On Fri, 15 May 2009 14:34:51 GMT, Jan Panteltje
The run time in C is 13 seconds here on a 1GHz processor.
Can you specify your 'old HP computer' ?
I can win maybe 1 second by writing the code a bit different.
And a 3GHz would do it in 12 / 4 = 4 seconds...
A bigger cache would help a bit perhaps.
A Cray would be even better.
What does you C code look like? Mine is in the other posting.
Else you goofed a factor 10.
Seems to me anyways :)
Here's my PowerBasic code:
===================================================
#COMPILE EXE
   ' SUM.BAS
   ' TRY SUMMING A LOT OF INTS INTO AN ARRAY OF LONGS...
   ' JL  MAY 14, 2009   PBCC4
FUNCTION PBMAIN () AS LONG
   COLOR 15,9
   CLS
   DIM A(64000000) AS INTEGER      ' INPUT ADC SAMPLES
   DIM S(64000000) AS LONG         ' SUMMING ARRAY
   DIM X AS LONG
   DIM Y AS LONG
   DIM Z AS LONG
   ' INIT INPUT ARRAY TO RANDOM-ISH VALUES...
   FOR X = 1 TO 64000000           ' THIS IS MUCH FASTER
       A(X) = X AND 32767          ' THAN CALLING RND()!
   NEXT
   T! = TIMER
   PRINT "Start... ";
   FOR Y = 1 TO 10
       FOR X = 1 TO 64000000
           S(X) = S(X) + A(X)
       NEXT
   NEXT
   PRINT "Done"
   E! = TIMER - T!
   PRINT USING$("Time per loop ##.### sec   ##.## ns/add", E!/10, 1E9*E!/(10*64E6))
   PRINT
   ' DISPLAY SOME RESULTS TO MAKE SURE IT REALLY WORKED...
   FOR X = 1 TO 10
       PRINT X, A(X), S(X)
   NEXT
   PRINT
   FOR X = 63999001 TO 63999010
       PRINT X, A(X), S(X)
   NEXT
   INPUT A$
END FUNCTION
===================================================
On my computer, a 1.9 GHz Xeon with 2G ram, winXP, I get this
result...
Start... Done
Time per loop  0.231 sec    3.61 ns/add
1             1             10
2             2             20
3             3             30
4             4             40
5             5             50
6             6             60
7             7             70
8             8             80
9             9             90
10            10            100
63999001      3097          30970
63999002      3098          30980
63999003      3099          30990
63999004      3100          31000
63999005      3101          31010
63999006      3102          31020
63999007      3103          31030
63999008      3104          31040
63999009      3105          31050
63999010      3106          31060
===================================================
One of my guys did a C version (I refuse to program in C) to run on
the Kontron under Linux, a slightly slower CPU, 2G ram. I asked him
for his source code, and he spent about a half hour cleaning it up to
be presentable... which I asked him NOT to do. Anyhow, here it is:
* mathsmash.c - a VERY crude benchmark
*
*             time the sum of 64-million 16-bit integers into 64-million 32-integer sums.
*
*             gcc -O3 mathsmash.c -o mathsmash.o
*
*             NOTE:  The loop is performed 10 times to make the measurement duration more reasonable.
*
*             Timing is done by observation or including the system("date") functions.
*
*
*/
#define SIXTYFOURMILLION   (0x100000 * 64)
#define DATA_ARRAY_SIZE   SIXTYFOURMILLION
#include <stdio.h>
int main()
{
       unsigned short *inbound_data;
       unsigned int   *sum_data;
       int multiply;
       unsigned long index = 0;
#if 0
       /* Initialize data */
       printf ("Zeroing data\n");
#endif
       inbound_data = (unsigned short *) malloc (sizeof ( short ) *
DATA_ARRAY_SIZE);
       sum_data = (unsigned *) malloc ((sizeof ( int )) *
DATA_ARRAY_SIZE);
       printf ("inb_ptr = 0x%08x, sum_ptr= 0x%08x\n", inbound_data,
sum_data);
       printf ("\n START sum operation...\n");
//      system ("date");
       for (multiply = 0; multiply < 10; multiply ++)        // 10 x
       {
               for ( index = 0; index < DATA_ARRAY_SIZE; ++index )
                       sum_data[index] += inbound_data[index];
       }
       printf ("\n END sum operation...\n");
//      system ("date");
}
===================================================
He commented out the system date things because they're buggy or
something, and timed it with his wristwatch at about 0.25 seconds per
64M add, about the same as the PowerBasic.
He used subscripts, not pointers, as I did. The inner loop compiles to
five instructions.
My program is prettier.
John
Re: My program is prettier.
I don't think so. For one thing your program is shouting.

Real programmers don't use lower case.

John

Nah. Real Programmers don't use anything with 'case' at all. (Which
I guess includes binary, octal and decimal, as well as any entry
method, especially panel switches.)

Tim
 
J

Jan Panteltje

The impressive thing about C and C++, as languages and as a culture,
is that as programmers become more experienced and "skilled", the
readability of their code drops and the bug rate remains high.

Well, you should state : "I think that", as
it is clearly an opinion not supported by any real data.

The bug rate is normally very low, for C programs (dunno about C+++,
I do not consider that a language, so you could well be right about that),
there a 2 very basic sort of errors in C programs.
One is the program flow itself: does it actually do what you want it to do,
that is probably the same for all languages and is the essence of programming,
the other is out of range pointers and that includes not checking return values
like somebody did here in his C example, but that is bad practice.

That you cannot read C does not make it less readable by a C programmer.
I cannot read Japanese, so I cannot give an opinion on Japanese writings,
you cannot read C, so how can you give an opinion on C writings?
 
J

Jan Panteltje

PS, some remark about *your* C programmer, not to piss him / her off,
but something I consider very important,
he /she uses 'short' and 'int' and 'unsiged short' etc...
One should always specify the size of the variables, as those may be different on
different machines:


This is from libc.info, the reference for C programming with gcc:
Integers
========

The C language defines several integer data types: integer, short
integer, long integer, and character, all in both signed and unsigned
varieties. The GNU C compiler extends the language to contain long
long integers as well.

The C integer types were intended to allow code to be portable among
machines with different inherent data sizes (word sizes), so each type
may have different ranges on different machines. The problem with this
is that a program often needs to be written for a particular range of
integers, and sometimes must be written for a particular size of
storage, regardless of what machine the program runs on.

To address this problem, the GNU C library contains C type
definitions you can use to declare integers that meet your exact needs.
Because the GNU C library header files are customized to a specific
machine, your program source code doesn't have to be.

These `typedef's are in `stdint.h'.

If you require that an integer be represented in exactly N bits, use
one of the following types, with the obvious mapping to bit size and
signedness:

* int8_t

* int16_t

* int32_t

* int64_t

* uint8_t

* uint16_t

* uint32_t

* uint64_t

If your C compiler and target machine do not allow integers of a
certain size, the corresponding above type does not exist.

If you don't need a specific storage size, but want the smallest data
structure with _at least_ N bits, use one of these:

* int8_least_t

* int16_least_t

* int32_least_t

* int64_least_t

* uint8_least_t

* uint16_least_t

* uint32_least_t

* uint64_least_t

If you don't need a specific storage size, but want the data
structure that allows the fastest access while having at least N bits
(and among data structures with the same access speed, the smallest
one), use one of these:

* int8_fast_t

* int16_fast_t

* int32_fast_t

* int64_fast_t

* uint8_fast_t

* uint16_fast_t

* uint32_fast_t

* uint64_fast_t

If you want an integer with the widest range possible on the
platform on which it is being used, use one of the following. If you
use these, you should write code that takes into account the variable
size and range of the integer.

* intmax_t

* uintmax_t

The GNU C library also provides macros that tell you the maximum and
minimum possible values for each integer data type. The macro names
follow these examples: `INT32_MAX', `UINT8_MAX', `INT_FAST32_MIN',
`INT_LEAST64_MIN', `UINTMAX_MAX', `INTMAX_MAX', `INTMAX_MIN'. Note
that there are no macros for unsigned integer minima. These are always
zero.

There are similar macros for use with C's built in integer types
which should come with your C compiler. These are described in *Note
Data Type Measurements::.

Don't forget you can use the C `sizeof' function with any of these
data types to get the number of bytes of storage each uses.


File: libc.info, Node: Integer Division, Next: Floating Point Numbers, Prev: Integers, Up: Arithmetic
 
N

Nobody

PS, some remark about *your* C programmer, not to piss him / her off,
but something I consider very important,
he /she uses 'short' and 'int' and 'unsiged short' etc...
One should always specify the size of the variables, as those may be different on
different machines:

If you have a specific number of bits in mind, use the <stdint.h> types.

OTOH, if you need compatibility with library functions, use the
appropriate types (which are usually platform-specific). E.g. printf("%d")
needs int not int32_t, malloc() wants size_t, etc.

This is more of an issue for pointers. The compiler will cast numeric
values as needed, but it won't convert pointer targets, so don't pass a
pointer to an int32_t to a function which expects an int* (casting the
pointer won't help; you need to convert the data).

You also need to remember C's implicit casting rules, which can produce
some fairly awkward interactions if you mix platform-specific types (int,
long, ...) with fixed-width types from <stdint.h>.
 
N

Nico Coesel

John Larkin said:
The impressive thing about C and C++, as languages and as a culture,
is that as programmers become more experienced and "skilled", the
readability of their code drops and the bug rate remains high.

In my experience bugs have more to do with being sloppy (typos),
misunderstanding multi-threading and bad design (or no design at all).
 
J

Jan Panteltje

' EPORT : OPEN TCP/IP PORT AS # 8

EPORT:

TCP CLOSE # 8 ' NUKE ANY OPEN ETHERNET
COMM CLOSE # 1 ' OR SERIAL PORT

CPORT% = 0

LOCATE 18, 1

PRINT " Default IP address = "; IP1$
PRINT
PRINT " Enter IP address, D for Default : ";

LINE INPUT IP$
IF UCASE$(IP$) = "D" THEN IP$ = IP1$

IF IP$ = "" THEN GOTO TOP

ERRCLEAR

TCP OPEN PORT 2000 AT IP$ AS # 8 TIMEOUT 50
CPORT% = 8

IF ERR THEN

LOCATE 22, 10: PRINT "TCP OPEN ERROR"
SLEEP 2000
CPORT% = 0

END IF

TCP RECV #8, 2000, B$ ' FLUSH THE TCP BUFFER!

GOTO TOP



and then later, you can...


' CHECK FOR INCOMING TRAFFIC FROM T344...

TANK:

RPLY$ = ""

IF CPORT% = 8 THEN
TCP RECV #8, 1, RPLY$ ' GET ONE (!) ETHERNET BYTE
ELSE
N& = COMM (#1, RXQUE) ' SERIAL: CHECK BUFFER CONTENTS
IF N& THEN COMM RECV #1, 1, RPLY$ ' GET ONE BYTE FROM BUFFER
END IF



This is insanely easy.

PB can also, easily, do UDP, SMPT, all that stuff. And all the tools
are inherent to the language, not external libraries. Which means
everything is clearly documented, both in manuals and in the built-in
Help thing. All it does is work.


John

That is very nice, never knew a BASIC could do that.
 
J

Jan Panteltje

Do C programmers ever read code? They seem to seldom read their own,
except when forced to look for a bug.

I have seen scads of "professionally" written C that was an
uncommented, buggy mess, with code commented out all over the place
without explanation. It's a bummer to spend time trying to understand
a hunk of code only to discover a little /* thing somewhere above.

/*
LOL, no that did not happen to me, yes I am the one who writes
comments that way.
*/

#define ONE 1
int small = 2;
int i;
for(i = 0; i < small; i += ONE)
{
/*
I guess it is like using an editor with coloring, if freaked me out,
I like black on white, cannot read green on a white background
(I always use white background in the editor because the light level is
then more constant), such things as 'if' 'for(' and other keywords read,
at least to me, and that includes '/*' and '*/', as normal words in a text.
Imagine a novel with all nouns in a different color, Oh, should
not have mentioned it, somebody is gonna read this and try.
As to comments, if you use sane variable names, and no 'a' 'b' 'c' only, then
the code is very much self explaining.
*/
fprintf(stderr, "Hello.\n");
}
 
J

Jan Panteltje

You can't argue that C (and its culture) generally results in good or
secure executables, because it so obviously doesn't.

Obviously does, as Linux is written in C (the kernel, the drivers, and many if
not most applications).

C++ OTOH is not something I consider a language, and you may be right
about that.

But C is like having the soldering iron on the hardware so to speak.
You can do anything right, and anything wrong.
While other languages (except for asm) have some more distance,
Like you on the bench with the remote control.

For real design C is a must :)
For user work BASIC will do.

;-)

To be a bit more serious, the old BASIC had those gotos and line numbers,
you got stuck with no space between line numbers, and needed a renumber routine.
I found asm much more easy than that BASIC because the assembler allowed me nice
long labels.
BASIC has come a long way since then.
 
N

Nico Coesel

John Larkin said:
Bugs have mostly to do with typing fast, not reading and checking, and
running the code to find some of the bugs. Languages like C encourage
dense, risky, tricky code. Languages like Ada do everything they can
to discourage it. Most programmers hate languages like Ada and Basic
because they slow them down and make them think.

That depends on what they need to think about. Usually it is a
workaround for a crappy language. Look at the amount of extensions
Borland put into Delphi. Its almost like C.
C also allows all sorts of memory-management and variable type/range
errors that no modern language should allow to happen. Malloc, memcpy,
wild pointers, things like that. It's barbaric.

Most of this stuff is deprecated. IIRC most modern compilers have an
option that will start to complain when insecure functions are being
used. The C++ STL library contains a huge amount of memory management,
string handling, linked list, etc functions that make it totally
unnecessary to deal with memory yourself.
Extreme Programming makes the case that two programmers writing a
piece of code on one shared screen is more efficient, on average, than
one programmer. That's pitiful.

You can't argue that C (and its culture) generally results in good or
secure executables, because it so obviously doesn't.

That is like saying more people are killed by people driving a
Corvette than a Ford.

You can argue this either way. Languages like C# and Java catch all
kinds of errors. This means the programmers have to worry even less
about cleaning up. On the other side C/C++ don't allow to let a
pointer slip away. The program will crash. Anyway, good programmers
that have an eye for security, resillience / recovery, timing /
deterministic behaviour and multi-threading are very scarce.

I still believe that a good piece of software starts with a good
design. No matter what language is being used.
 
N

Nico Coesel

John Larkin said:
Do C programmers ever read code? They seem to seldom read their own,
except when forced to look for a bug.

I have seen scads of "professionally" written C that was an
uncommented, buggy mess, with code commented out all over the place
without explanation. It's a bummer to spend time trying to understand
a hunk of code only to discover a little /* thing somewhere above.

That is why I import projects from others into Eclipse (with CDT).
Eclipse gives me a nice list with classes/functions. And Eclipse has
an excellent text search function. Very easy while digging into a
C/C++ project.
 
J

Jan Panteltje

Absolutely. PB has all the modern constructs, WHILE, CASE, TRY/CATCH,
graphics, all that. But I still think in state machines, and GOTO is a
perfectly good way to structure state machines. Nothing flow-charts as
nicely as a program based on GOTOs. The anti-GOTO nonsense was started
by Dijkstra, who didn't program much himself and didn't have regular
access to a computer.

Well, in C I avoid goto, in fact there is no need for it.
I often even avoid for loops, if I need this:
for(i = 0; i < something; i++) {}
Then I will likely write:

count = 0;
while(1)
{
if(conditon1) {do_this;}
if(condition2) {do_that;}
if(it_rains) {wear_hat;}

if(count > then_what_I_want) break;
count++;
}

The other thing I always try is return if possible.
while(1)
{
if(condition1) {do_this;return OK;}
//etc
}

This is a bit harder to explain but avoids errors and keeps the code clean.
Lemme give a real example, this is from xste subtitle editor that I wrote.
It allows you to add text subtitles to a video stream, does
automatic text formatting etc.
Had to figure out things, code has been around for many years now, many downloads.
It is, as far as I know, the only subtitle editor available for Linux.
It uses a lot of global vars too... you like that if you like BASIC.
Also note the parameter checks ever so often, and the debug print
statement that can be activated with a command line flag.
That means if it ever crashes (it does not) and you run it with debug request,
it will print the last variables before the crash, plus where it is, which function,
and where in that function, so you can fix it immediately.


int create_bitmap_file(struct frame *pa)
{
int a, c, i, j;
int l, h, hh;
char *tptr, *cptr;
int x, y;
char temp[4096];
FILE *fptr;
int text_start, max_width, line_len;
uint8_t *py;
int color;
int file_size;
int image_size;
int bitmap_byte = 0; // -Wall
int odd_byte;
int error;
int padding;
int bits;

if(debug_flag)
{
printf("create_bitmap_file(): arg pa=%p\n", pa);
}

/* argument check */
if(! pa) return 0;

/* set all of drawing area to background */
for(i = 0; i < (720 * 576 * 3); i += 3)
{
image_buffer = pa -> background;
}

/* some defaults */
pa -> width = 0;
pa -> height = 0;
pa -> xpos = 0;
pa -> ypos = 0;
/* end defaults */

line_h_start = h_factor * (double)h_size;
line_h_end = (double)h_size - (double)line_h_start;

window_bottom = v_size - (v_factor * (double)v_size);

/*
Set hor_position for start text in all lines to zero,
center_text() may overrule this if center_flag.
*/
for(i = 0; i < MAX_SCREEN_LINES; i++)
{
screen_text[0] = 0;
screen_start = 0; // pixels from left used to center text
}

/* reformat text inserting (multiple) '/n' if too long */
tptr = p_reformat_text(pa, line_h_end - line_h_start);
if(! tptr)
{
printf("create_bitmap_file(): could not reformat text=%s\n", pa -> text);

/* return error */
return 0;
} /* end if reformat text failed */

/* center text */
if(pa -> status & CENTER_TEXT) p_center_text(tptr, pa);

/* text to array screen_text[] */
cptr = tptr;
screen_lines = 1; /* at least one */
while(1) /* all chars in tptr */
{
i = 0;
while(1) /* all chars in a line */
{
if(*cptr == '\n')
{
/* scip the '\n' */
cptr++;

/* force string termination */
screen_text[screen_lines - 1] = 0;

/* point to next screen line */
screen_lines++;
break;
}

/* copy character */
screen_text[screen_lines - 1] = *cptr;

/* test for end of string tptr */
if(*cptr == 0) break;

/* point to next char in screen_lines[][] */
i++;

/* point to next char in tptr */
cptr++;
} /* end while all characters in line terminated with LF */

/* ready if end of tptr */
if(*cptr == 0) break;

} /* end while all lines in tptr */
free(tptr);

/* some limit */
if(screen_lines > MAX_SCREEN_LINES) screen_lines = MAX_SCREEN_LINES;

line_height = pa -> pfd -> height + pa -> vespace;
window_top = window_bottom - (screen_lines * line_height) + pa -> vespace;

if(debug_flag)
{
printf("line_height=%d\n", line_height);
printf("screen_lines=%d\n", screen_lines);
printf("line_h_start=%d line_h_end=%d\n",\
line_h_start, line_h_end);
printf("window_bottom=%d window_top=%d\n",\
window_bottom, window_top);
}

// Maybe no warn / scip here, input test was already done, this is fuzzy?
if(window_top < 0 - line_height)
{
fl_show_alert("Image for frame", pa -> name, "does not fit.\nSkipped.", 0);

return 0;
}

/* print lines of text on screen in right position */
text_start = INT_MAX;
max_width = 0;
for(i = 0; i < screen_lines; i++)
{
/* convert any special characters */
/*
j = 0;
while(1)
{
c = screen_text[j];
character_lookup(c, &b);
screen_text[j] = b;

if(c == 0) break;
j++;
}
*/

/* get text length */
line_len = 0;
j = 0;
while(1)
{
c = screen_text[j];
line_len += get_h_pixels(c, pa);

if(c == 0) break;
j++;
}

x = screen_start;

if(x < text_start) text_start = x;

if(line_len > max_width) max_width = line_len;

y = window_top + (i * line_height);

if(debug_flag)
{
printf(\
"screen_start[%d]=%d window_bottom=%d window_top=%d\n\
line_height=%d x=%d y=%d\n\
text=%s\n",\
i, screen_start, window_bottom, window_top,\
line_height, x, y,\
screen_text);
}
/*
int add_text_x(\
int x, int y, char *text, struct frame *pa, int u, int v, double contrast, double transparency)
*/
add_text(x, y, screen_text, pa, 0, 0, 100.0, 0.0);

} /* end for all screen_lines */

pa -> ypos = window_top;

/*
text_start is the start of the most left character start in a (multiline)
text.
max_width is the length of the text in pixels.
*/

pa -> height = screen_lines * line_height - pa -> vespace; // + 9;
pa -> xpos = text_start;

/* add some space for outline */
pa -> width = max_width + 6;

/* CVD needs even width */
/* if width is not multiple of 8, make it */
a = pa -> width % 8;
if(a) pa -> width += 8 - a;

/* CVD needs even height, if height is not multiple of 4, make it */
a = pa -> height % 4;
if(a) pa -> height += 4 - a;

if(debug_flag)
{
printf("create_bitmap_file():\n\
frame=%s\n\
text_start=%d max_width=%d\n\
pa>xpos=%d pa->ypos=%d\n\
pa->width=%d pa->height=%d\n\
pa->text=%s\n",\
pa -> name,\
text_start, max_width,\
pa -> xpos, pa -> ypos,\
pa -> width, pa -> height,\
pa -> text);
}

/* return error if not usable overlay */
error = 0;

/* no pointer to text */
if(! pa -> text) error = 1;

/* no text */
if(pa -> text[0] == 0) error = 1;

/* no width */
if(pa -> width <= 0) error = 1;

/* no height */
if(pa -> height <= 0) error = 1;

/* negative xpos */
if(pa -> xpos < 0) error = 1;

/* negatve ypos */
if(pa -> ypos < 0) error = 1;

/* reformatter failed */
if(max_width == 0) error = 1;

/* no space left to print, reformatter failed margin? */
if(pa -> xpos >= (h_size / 2) ) error = 1;

/* falls of right hand side of screen */
if( (pa -> width + pa -> xpos) >= h_size) error = 1;

/* falls of bottom of screen */
if(pa -> height >= v_size ) error = 1;
if(error)
{
if(debug_flag)
{
printf("create_bitmap_file(): ERROR\n");
}

/* return error */
return 0;
} /* end if error */

/*
lets write our own bitmap, ppmtobmp does not fill in the complete colormap,
the h and v size, the ColorsImportant field, and the bitmap size.
*/

/* open the bmp file for write */
if(pa -> status & TEST_BITMAP)
{
sprintf(temp, "%s/%s/%s/test.bmp",\
home_dir, selected_data_directory, selected_project);
}
else
{
sprintf(temp, "%s/%s/%s/frame%04d.bmp",\
home_dir, selected_data_directory, selected_project, atoi(pa -> name) );
}

fptr = fopen(temp, "w");
if(! fptr)
{
printf(\
"create_bitmap_file(): could not open file %s for write, aborting\n",\
temp);

exit(1);
}

/*
600 x 120 origial .bmp from iauthor.
0000:0000 42 4d 16 8d 00 00 00 00 00 00 76 00 00 00 28 00 BM........v...(.
0000:0010 00 00 58 02 00 00 78 00 00 00 01 00 04 00 00 00 ..X...x.........
0000:0020 00 00 a0 8c 00 00 00 00 00 00 00 00 00 00 10 00 .. .............
0000:0030 00 00 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 ..........ÿÿÿ...
0000:0040 80 00 00 80 00 00 00 00 48 0a e6 3c f5 bf 00 00 ........H.æ<õ¿..
0000:0050 7f 10 84 c2 64 7a ff ff c7 3d 98 c2 f7 3e d7 16 ...ÂdzÿÿÇ=.Â÷>×.
0000:0060 ff ff c7 3d 00 00 b0 80 02 00 6f 00 b2 c2 d0 10 ÿÿÇ=..°...o.²ÂÐ.
0000:0070 af 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ¯...............
0000:0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
*/

/* print header, all low byte first! */

/* type */
fprintf(fptr, "%c%c", 0x42, 0x4d);

/* file_size */
file_size = (pa -> width * pa -> height / 2) + 118;
h = file_size / 256;
l = file_size - (256 * h);
fprintf(fptr, "%c%c", l, h);

if(debug_flag)
{
printf("file_size=%d l=%d h=%d to file=%02x %02x\n",\
file_size, l, h, l, h);
}

/* 2 x reserved */
fprintf(fptr, "%c%c%c%c%c%c", 0, 0, 0, 0, 0, 0);

/* offset to bitmap data */
fprintf(fptr, "%c%c%c%c", 0x76, 0, 0, 0); // 118

/* BitmapInfoHeader starts here, its size */
fprintf(fptr, "%c%c%c%c", 0x28, 0, 0, 0);

/*
picture width, always < 65535 here (SVHS standard), so highest byte is zero.
*/
h = pa -> width / 256;
l = pa -> width - (h * 256);
fprintf(fptr, "%c%c%c%c", l, h, 0, 0);

if(debug_flag)
{
printf("pa->width=%d l=%d h=%d to file=%02x %02x %02x %02x\n",\
pa -> width, l, h, l, h, 0, 0);
}

/* picture height, always < 65535! so highest byte is zero */
h = pa -> height / 256;
l = pa -> height - (h * 256);
fprintf(fptr, "%c%c%c%c", l, h, 0, 0);

if(debug_flag)
{
printf("pa->height=%d l=%d h=%d to file=%02x %02x %02x %02x\n",\
pa -> height, l, h, l, h, 0, 0);
}

/* planes , one plane */
fprintf(fptr, "%c%c", 1, 0);

/* bit count, 4 bpp */
fprintf(fptr, "%c%c", 4, 0);

/* compression, no compression */
fprintf(fptr, "%c%c%c%c", 0, 0, 0, 0);

/* size image */
image_size = pa -> width * pa -> height / 2;
hh = image_size / 65536;
h = (image_size - (65536 * hh) ) / 256;
l = image_size - (65536 * hh) - (256 * h);
fprintf(fptr, "%c%c%c%c", l, h, hh, 0);

if(debug_flag)
{
printf("image_size=%d l=%d h=%d hh=%d to file=%02x %02x %02x %02x\n",\
image_size, l, h, hh, l, h, hh, 0);
}

/* XPelsPerMeter */
fprintf(fptr, "%c%c%c%c", 0, 0, 0, 0);

/* YPelsPerMeter */
fprintf(fptr, "%c%c%c%c", 0, 0, 0, 0);

/* ColorsUsed */
fprintf(fptr, "%c%c%c%c", 0x10, 0, 0, 0);

/* ColorsImportant */
fprintf(fptr, "%c%c%c%c", 0x00, 0, 0, 0);

for(i = 0; i < 16; i++)
{
/* bgr to rgb */
fprintf(fptr, "%c%c%c%c", xste_rgb_palette[2], xste_rgb_palette[1], xste_rgb_palette[0], 0);
}

/* write bitmap data */
for(y = pa -> height; y > 0; y--)
{
/* start line of pixels in main screen */
py = \
image_buffer + \
(3 * \
( ( (pa -> ypos - 1 + y) * h_size ) + \
pa -> xpos\
)\
);

/* get a line from buffer start, to file in RGB */
/*
from BMP.txt from the www:
If necessary, a scan line must be zero-padded to end on a 32-bit
boundary.
However, segment boundaries can appear anywhere in the bitmap.

So, 32 bits is 4 bytes!!! zero padding.
*/

odd_byte = 0;
bits = 0;
for(x = 0; x < pa -> width ; x++)
{
/*
We have 3 bytes per pixel in the buffer,
we want to send 4 bits per pixel, so 2 pixels is one byte.

For every 6 bytes in the buffer we write one byte!
*/

color = *py;

/* always start line on byte boundary */
/* does win bmp have low byte first in the bitmap ????? */

/* if low nibble, remember */
if(! odd_byte)
{
/* data to upper 4 bits */
bitmap_byte = color << 4;
}
else
{
/* combine */
bitmap_byte |= color;

/* to bmp file */

fprintf(fptr, "%c", bitmap_byte);

bits += 8;
}

/* point to next pixel in source */
py += 3;

/* reverse odd byte */
odd_byte = 1 - odd_byte;

} /* end for all x */

/* Test if we need to pad, need to be at 32 bits boundary. */
padding = bits % 32;

if(! padding) continue;

/* output an extra nibble */
a = 32 - padding;
for(i = 0; i < a / 8; i++)
{
fprintf(fptr, "%c", 0);
}

} /* end for y (all lines) */

fclose(fptr);

return 1;
} /* end function create_bitmap_file*/




Software should be like hardware: do it the cleanest way, take your
time, document it thoroughly, get it right the first pass.

It rarely is. If you consider all the components of a complex system,
software is the least reliable, the hardest to manage, the hardest to
maintain, the most likely to destroy the company, and usually the most
expensive.

Well, I dunno, I have very little problems with very complicated software.
Some have thousands of downloads, and most zero error reports.

Lately there has been a run on some programs again, clearly somebody wrote about
it or linked to it :)

Indeed if you publish open source, it better be good, or you will drawn in email.
xste has 33222 lines of C code, not counting the 14 header files....
Bugs? What bugs?
Oh, and it does audio + video too of course, has its own players build in.
Apart from libforms it interfaces directly with the system.... no SDL stuff or such.
Half a megabyte executable or so, no need for bloat.
 
N

Nobody

The advantage of Linux is that many, many eyeballs review the code,
and the authors know that their code will be seen and criticized in
public. That probably encourages them to be more careful. Plus, the
code is debugged by many, many people.

Most programmers work on their bit of code alone. Nobody checks their
source code but themselves. They don't comment because they figure
they will remember their design intent forever, or because they were
never taught to document their own code.

Right. But this isn't C's fault. You will see more crappy code written in
C than in most other languages simply because you will see more code written in
C than in most other languages.

If you need to tackle a wide range of programming tasks, you need to know
C. There is no other language with such a wide range of applicability
(with the caveat that C++ is essentially a superset of C). You don't see
OS kernels being written in Ada or Python or BASIC.

And once you know C, you don't really *need* to know anything else. Sure,
there are lots of cases where other languages might be more suitable, but
C is usually "good enough". But there are plenty of cases where C/C++ is
the only language which is good enough.

There are a lot of half-baked programmers whose knowledge of languages
started with VB or JavaScript, maybe a couple more languages are learnt
for specific tasks, then they learn C and never need to learn another
language.
What do you mean by "real design"? I do real products in assembly.

Assembly is a non-starter if you need the code to run on multiple
architectures (or if you suspect that it may need to do so in the future).
It's also unrealistic for large applications.
Most truly mission-critical, lives-depend-on-it programming (like the
stuff that flies airplanes) is done in Ada.

That kind of software development is only feasible if you have the kind
of customer who pays $2000 for a screwdriver. IOW, the DoD, NASA, ... er
just those two, really. Most software development is rather more
price-sensitive.
Absolutely. PB has all the modern constructs, WHILE, CASE, TRY/CATCH,
graphics, all that. But I still think in state machines, and GOTO is a
perfectly good way to structure state machines. Nothing flow-charts as
nicely as a program based on GOTOs. The anti-GOTO nonsense was started
by Dijkstra, who didn't program much himself and didn't have regular
access to a computer.

Dijkstra was right, though; "goto" is the antithesis of structured
programming. It's hardly ever used in high-level languages. The main use
of "goto" in C is to clean up on errors, which is done using exception
handling, constructors, and destructors in C++.
Software should be like hardware: do it the cleanest way, take your
time, document it thoroughly, get it right the first pass.

It rarely is. If you consider all the components of a complex system,
software is the least reliable, the hardest to manage, the hardest to
maintain, the most likely to destroy the company, and usually the most
expensive.

That's because it accounts for 99% of the system. Think about implementing
a PC with a dozen substantial applications using dedicated logic rather
than a CPU and software. You would be lucky to fit it onto a silicon
wafer, and even the DoD wouldn't be able to afford one.
 
N

Nobody

That is like saying more people are killed by people driving a
Corvette than a Ford.

You can argue this either way. Languages like C# and Java catch all
kinds of errors.

Catching an error at run-time is too late. Much of the time, the biggest
difference between using Java and using C is that the former provides a
slightly more verbose error message when it terminates the program and
loses all of your work due to an out-of-bounds array access.

In that regard, code written in interpreted languages is often worse than
that written in C, as even the most obvious errors can go undetected if
the code doesn't get run (error-handling code is a prime target).
 
N

Nico Coesel

John Larkin said:
Drowning in uncontrolled complexity? Add more automation tools!

Looking for something to drive a nail in the wall? Get a hammer!
 
J

Jasen Betts

The run time in C is 13 seconds here on a 1GHz processor.
Can you specify your 'old HP computer' ?

I can win maybe 1 second by writing the code a bit different.
And a 3GHz would do it in 12 / 4 = 4 seconds...
A bigger cache would help a bit perhaps.

runtime in C on a 2.4Ghz "intel core2 duo" machine is about
3 seconds. about 2 when multithreaded.
A Cray would be even better.

dunno about that, those beasts are maninly focussed on floating point
performance, and this is an integer problem.
What does you C code look like? Mine is in the other posting.


here's the multithreaded one I used

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

static long S[64000000];
static short A[64000000];

typedef struct argstype
{
short *a_start;
long *s_start;
long count;
} argstype;

static void *thread_func(void *vptr_args)
{
argstype *arg=vptr_args;
{
long *sp=arg->s_start;
short *ap=arg->a_start;
long x=arg->count;
do
*sp++ += *ap++;
while (--x);
}
return NULL;
}

int main(int argc,char **argv)
{
long y,n;

n=10;
if(argc>1)
n=atoi(argv[1]);

for(y=0;y<n;++y)
{
argstype instance_a={A,S,32000000};
argstype instance_b={A+32000000,S+32000000,32000000};
pthread_t thread_a;

// start a thread to process half the data
if (pthread_create(&thread_a, NULL, thread_func, &instance_a) != 0)
{
perror("pthread_create");
return EXIT_FAILURE;
}
// process the other half in the foreground
thread_func(&instance_b);

// wait for the thread to finish.

if (pthread_join(thread_a, NULL) != 0)
{
perror("pthread_join");
return EXIT_FAILURE;
}
}
return 0;
}
 
J

Jasen Betts

I suspect this is all limited by the system memory bandwidth.

It looks like it, with -O4 optimisiation on dual-threaded and single-threaded
versions both run in 1.9 seconds here.
 
Top