[comp.sys.amiga] C Help

carpent@coltrane.SRC.Honeywell.COM (Todd Carpenter) (04/04/89)

Greetings, oh great and mighty C wizards!  I beg of you to aid a poor and
distraught traveller through the wide and turbulent C!

I have 2 arrays.  One describes the current state of a system, the next
describes a possible future state.  The arrays are unsigned shorts.  The future
state may be as simple as changing 1 of the values.  I calculate the future
state often, and rarely actually accept it.  Therefore, each time I must obtain
a copy of the current state, and make a change to it.  This is time consuming.
BTW, I am using Lattice 5.0.   This boils down to:

void moo(state,new_state) 
  ushort state[NUM_STATES], new_state[NUM_STATES];

{
  ushort i;

  for (i = 0; i != NUM_STATES; i++)
    new_state[i] = state[i];

  ...
}

Anyone have any significantly faster ideas?  Blitter?  Number of states may be
up to 256.



In other news, I also do lots of math with this, but can do it in integer space
(i.e., for some of this I don't need floating point).  However, if I remember
right, all divides in C are, by definition, done in double floating point.  I
have the A2620, but an integer divide is *still* faster than a double float on
the 68881.  So, if I have something like:

unsigned moo()
  unsigned i,j,k;

{
  return(i*j/k);    /* or any other obscure equation where I can afford */
                    /* operations                                       */
}

How do I constrain it to integer ops?  Remember, I have Lattice 5.0.

email is fine.

Thanks, oh wise and mighty ones!  I have sacrificed a pizza to thine eternal
glory!

w-colinp@microsoft.UUCP (Colin Plumb) (04/04/89)

For your state array, you might try wrapping it up in a structure and doing
structure assignment.  This gives the compiler lots of room to optimise.

You can also get tricky with fancy data structures, like storing a delta
from the base state, and only copying the full state if you accept.

In C, all float operations are done in double precision, but all integer
ops, including divide, are pure integer.  Don't worry about it too much.
-- 
	-Colin (uunet!microsoft!w-colinp)

"Don't listen to me.  I never do." - The Doctor

usenet@cps3xx.UUCP (Usenet file owner) (04/04/89)

In article <1222@microsoft.UUCP> w-colinp@microsoft.uucp (Colin Plumb) writes:

Try AllocMem() for the amount of memory yuou need.
Then use the Exec.library CopyMemQuick(). 
This should be the fastest way to move longwords around.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In Real Life: Joe Porkka
porkka@frith.egr.msu
jap@syssun.cl.msu.edu  (35.8.1.1)

ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (04/05/89)

In article <19888@srcsip.UUCP> carpent@coltrane.SRC.Honeywell.COM (Todd Carpenter) writes:
>void moo(state,new_state) 
>  ushort state[NUM_STATES], new_state[NUM_STATES];
>{
>  ushort i;
>
>  for (i = 0; i != NUM_STATES; i++)
>    new_state[i] = state[i];
>
>  ...
>}
>
>Anyone have any significantly faster ideas?  Blitter?  Number of states may be
>up to 256.
>
	CopyMem (new_state, state, (LONG) NUM_STATES * sizeof (ushort));

	Is there any particular reason why you have to undo the whole table?
If you were to re-write the algorithm to undo only those elements that
needed undoing, you'd save a lot of time.

>However, if I remember right, all divides in C are, by definition, done in
>double floating point.  [ ... ]

	A zillion other people are going to say this, too, and will probably
quote K&R or DpANS chapter and verse.

	If all the operands in an expression are integers, then the
evaluation of the expression is done using integer arithmetic.  If you stick
any floats or doubles in there, then floating point arithmetic will be used
(though not necessarily throughout the expression (watch me get toasted for
that one)).

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape	INET: well!ewhac@ucbvax.Berkeley.EDU
 \_ -_		Recumbent Bikes:	UUCP: pacbell > !{well,unicom}!ewhac
O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
"Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

carpent@coltrane.SRC.Honeywell.COM (Todd Carpenter) (04/05/89)

  A short time back I asked for help on doing a fast array copy.  The jury
  agrees that the best way to do it is (some approximation to):

  CopyMem (new_state, state, (LONG) NUM_STATES * sizeof (ushort));

  Some people wondered *why* I wanted to do this.  Seemed it was a messy way to
  do it.  I could keep track of the modifications, and undo all changes later.
  Well, I've tried both ways.  It is a stochastic modification of the
  current state, and a non determinitic number of values will be changed.  So
  there is a break even point somewhere.

  And yes, roughly a zillion and a half people told me that integer expressions
  are done in integer arithmetic.  See what happens when you never actually
  bought K&R but just borrowed it from people?

  Thanks for all your help!

dmg@ssc-vax.UUCP (David Geary) (04/06/89)

Subject: Re: C Help
Newsgroups: comp.sys.amiga


Todd Carpenter writes:

|Greetings, oh great and mighty C wizards!  I beg of you to aid a poor and
|distraught traveller through the wide and turbulent C!

  With a plea like that, who could resist ;-)

|I have 2 arrays.  One describes the current state of a system, the next
|describes a possible future state.  The arrays are unsigned shorts.  The future
|state may be as simple as changing 1 of the values.  I calculate the future
|state often, and rarely actually accept it.  Therefore, each time I must obtain
|a copy of the current state, and make a change to it.  This is time consuming.
|BTW, I am using Lattice 5.0.   This boils down to:

|void moo(state,new_state) 
|  ushort state[NUM_STATES], new_state[NUM_STATES];
|
|{
|  ushort i;
|
|  for (i = 0; i != NUM_STATES; i++)
|    new_state[i] = state[i];
|
|  ...
|}
|
|Anyone have any significantly faster ideas?  Blitter?  Number of states may be
|up to 256.

  Well, whenever you are looping and are concerned with speed, use a
  register variable for the counter.  IOW, instead of ushort i, use
  register ushort i.  That may help somewhat, but, if you have a good
  compiler, it may optomize that in for you anyway. (I don't know if
  Lattice 5.0 would or not).

  Depending upon what you're doing with the two arrays between calls
  to moo() (thank goodness it's not foo()!), you could use pointers
  to each of the arrays, and simply switch pointers.  This would
  be much faster.
    
|In other news, I also do lots of math with this, but can do it in integer space
|(i.e., for some of this I don't need floating point).  However, if I remember
|right, all divides in C are, by definition, done in double floating point.  I

  Oh, no!  Sheesh, that would be a mess.  All floating point division is
  done using doubles, however, with the advent of ANSI C, that is not always
  true. (ANSI allows for single precision floating point division).

|have the A2620, but an integer divide is *still* faster than a double float on
|the 68881.  So, if I have something like:
|
|unsigned moo()
|  unsigned i,j,k;
|
|{
|  return(i*j/k);    /* or any other obscure equation where I can afford */
|                    /* operations                                       */

  This is simply integer division.

|}

|Thanks, oh wise and mighty ones!  I have sacrificed a pizza to thine eternal
|glory!

I'll take a pizza too ;-)
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace, Seattle                 ~ 
~ "I wish I lived where it *only* rains 364 days a year" ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

carpent@coltrane.SRC.Honeywell.COM (Todd Carpenter) (06/06/89)

Hello, oh great and mighty C wizards of the net!  I beg of thee guidance...
 
  Okay, these are not *pure* amiga questions.  But I am writing (what I think
  will a be useful and impressive) program on my amiga, and have encountered a
  few stumbling blocks.   Please *email* me replies.
 
  1) Speed is the prime consideration.  This will *not* be a small program by
  any means, but it has to be fast.

  2) But, it is also big.  The data arrays for small systems are over 256K.
  and I have multiple arrays.  SO I can't waste too much space.

Question 1)  People have been talking about residentable programs, and
generally good (for the Amiga) programming techniques.  One of the points is to
avoid global variables.  But I cannot think of any way to avoid global
variables, without suffering a hit in performance.
 
  unsigned moo(param1,param2,iteration)
     unsigned param1,param2
  {
     return( (param1 - param2 < 0) ||
               (iteration & MASK == MASK) )
  }

Now, moo is one of many functions which return true or false.  Which function
is chosen (and initialized) at the begining.  A pointer to moo is returned (so
I oont have to go through a SWITCH statement).   So I want a generic interface
to those functions, and the above interface *should* be sufficient.  However,
some of the routines require a few items (MASK in the above) initialized by the
user.  These values are set once, at the beginning, or may actually change
through events other than that within moo.  So, how do I get MASK to moo
without using globals?  I *don't* want to pass it in (since it would be a non
uniform interface), and I don't want to have a test to see if it is an
initialization phase.
 
  related - what about static variables inside moo?  Will they cause troubles?


Question 2:  This is another embarrassing one.  I can't afford to waste space,
so I'd like to declare my arrays to be only as large as necessary.  These
two dimensional arrays are indexed very frequenty.
  
    How do I allocated from the heap the following:

unsigned short MOO [Xdimension] [YDimension];

    Where X and Y are determined at runtime (256x256 would be considered
    reasonable values)?

    if I pass MOO to a procedure, how do I reference element MOO[x][y]?  Do I
    start building pointer offsets and other ickies, or are there nice ways?


Thanks in advance! 

Todd P. Carpenter          Honeywell Systems and Research Center
voice:  (612)782-7229      paper:  3660 Technology Drive, Minneapolis, MN 55418
UUCP: carpent@srcsip.uucp  bang-style: {umn-cs,ems,bthpyd}!srcsip!carpent
Internet: carpent@src.honeywell.com or carpent@altura.honeywell.com

morris-ng@cup.portal.com (Yuklung Morris Ng) (06/08/89)

re: Dynamical array:
 
try this:
 
struct link
{	int data; /* or whatever datatype */
	struct link *next;
};

struct doub_link
{	struct link *linkp;
	struct doub_link *next_link;
};



when you know how many record you need:
 
	var = (struct doub_link *) calloc({how many}, sizeof(struct doub_link))

when you know how much element in size of the record:
 
	var1 = (struct link *) calloc({how much}, sizeof(struct link));

You have to develop the function for insertion, deletion, etc.

It would be better if you try to link each node to its parent node, and the end
point will point to the first node, as it will speed up you algorithm of the
functions.
 
If you prefer speed for searching and searching, try Binary search tree. The
algorithm is in most data structure books.
If you want utimate speed, and doesn't care of portability, try to you amiga
specific function instead of calloc().

The above struct I provided looks like that:

top_ptr -> ptr1	  -> ptr2   -> ptr3    -> ... -> null <- very important!
	    |	      |		|	.....
	    V	      V		V       .....
	  data	    data      data
	    |         |		|
	    V	      V		V
	  data	    data      NULL
	    |	      |
	    V	      V
	  NULL	    NULL

+------------------------------+------------------------------------+
|  Morris Y. L. Ng             |  Usenet: morris-ng@cup.portal.com  |
|  Computer Science & Finance  |  Portal: Yuklung Morris Ng         |
|  San Jose State University   |  Home  : (###)###-#### (Guess?!)   |
+------------------------------+------------------------------------+
|           "Be my Amiga!  And I will be your Amigo!"               |
+-------------------------------------------------------------------+

news@crash.cts.com (Usenet News) (07/03/89)

Ok, this is my first post to the net.....Lesse if this works...



Oh, and this is a ----PROGRAMMING PROBLEM---- abort if you aren't interested





Following is a short program I wrote that supposedly will send stuff to

the modem.  Kind of a Very Dumb Terminal program.  Everything seems to work

fine (the Modem Ready light comes on and when I type something the Send

light flashes).  But if I were to send ATZ or ATDT5551212, nothing happens.

The modem doesn't reset or dial or nutin'.



                    H E L P!!!!!!







/*** Modem.C       Modem Control Program  */

#include <stdio.h>

#include <exec/types.h>

#include <exec/nodes.h>

#include <exec/lists.h>

#include <exec/ports.h>

#include <exec/libraries.h>

#include <exec/devices.h>

#include <devices/serial.h>

#include <exec/io.h>



extern struct MsgPort *CreatePort();

struct IOExtSer *mySerReq, *mySerWriteReq;




main()

  {

  LONG error, i;

  struct MsgPort *mySerPort, *mySerWritePort;

  BYTE *b, *c;

  char GetData[100], SendData[100];



  mySerPort = CreatePort("mySerial",0);

  if(mySerPort==NULL) exit(100);

  mySerReq = (struct IOExtSer *)CreateExtIO(mySerPort,sizeof(struct IOExtSer));

  if(mySerReq==NULL) goto cleanup1;

  mySerReq->io_SerFlags = 0;

  error = OpenDevice("serial.device",0,mySerReq,0);

  if(error !=0) goto cleanup2;



  mySerWritePort = CreatePort("mySerialWrite",0);

  mySerWriteReq  = (struct IOExtSer *)CreateExtIO(mySerWritePort,sizeof(struct IOExtSer));

  b=(BYTE *)mySerReq;

  c=(BYTE *)mySerWriteReq;

  for(i=0;i<sizeof(struct IOExtSer);i++)

    *c++=*b++;

  mySerWriteReq->IOSer.io_Message.mn_ReplyPort = mySerWritePort;



  GetData[0] = '\0';

  while(GetData[0] != '*')

    {

    printf("Enter Text to Send to Modem...\"*\" to end\n");

    scanf("%s",&GetData);

    sprintf(SendData,"%s\n\000",GetData);

    WriteSer(SendData);

    }



  cleanup2:

    CloseDevice(mySerReq);

    CloseDevice(mySerWriteReq);

  cleanup1:

    DeletePort(mySerWritePort);

    DeletePort(mySerPort);

  }



WriteSer(modemdata)

  char *modemdata;

  {

  int error;



  mySerReq->io_Baud = 1200;

  mySerReq->io_StopBits = 1;

  mySerReq->io_ReadLen = 7;

  mySerReq->io_WriteLen = 7;

  mySerReq->IOSer.io_Data  = (APTR)modemdata;

  mySerReq->IOSer.io_Length = -1;

  mySerReq->IOSer.io_Command = CMD_WRITE;

  if((error = DoIO(mySerReq)) != 0)

    {

    printf("Serial.Device write error &ld \n",error);

    }

  return(error);

  }





Please, bear with me.  I am one of those "Teach yourself C" guys.  If it's a

stupid answer, please send it to me anyway!  All this is from the

oh-so-accurate CA books (first edition).  And I'm using a 1000 with a 2400

baud hayes-compat modem and 2 floppies (just in case anyone cares).





SORRY THIS IS SUCH A LONG POST!!!!







(modified) ====================================[+][-]

|     UUCP: crash!pro-graphics!RogerG           |  <cool text graphics>      |

| InterNet: crash!RogerG@pro-graphics.cts.com   |      <witty quote>         |

| ARPA/DDN: crash!pro-graphics!RogerG@nosc.mil  |  <standard disclaimer>     |

|___________________________________________________________________________X|

matthew@sunpix.UUCP ( Sun Visualization Products) (07/07/89)

In article <4552@crash.cts.com>, news@crash.cts.com (Usenet News) writes:
> But if I were to send ATZ or ATDT5551212, nothing happens.
> 
>     sprintf(SendData,"%s\n\000",GetData);
>

  Notice the '\n' in the above line, is this being mapped to a Carriage Return
or Linefeed.  If its the latter, thats your problem.  Most Hayes modes (and
compatibles) expect commands to be carriage return terminated strings.  If
they are terminated by linefeeds, the modem is still waiting for more.  I know 
that a few people in the MS-DOS field got nabbed because MS-DOS termiantes 
strings with CRLF, and the the modem would start dialing and then suddenly 
stop. (While waiting for a connection, any input to one of these modems forces
it back to the "Wait for Command state").


-- 
Matthew Lee Stier                         |
Sun Microsystems ---  RTP, NC  27709-3447 |        "Wisconsin   Escapee"
uucp: { sun, mcnc!rti }!sunpix!matthew    |
phone: (919) 469-8300 fax: (919) 460-8355 |