Date: Wed, 5 Jan 2005 17:46:28 -0700
Reply-To: Jack Hamilton <JackHamilton@FIRSTHEALTH.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Jack Hamilton <JackHamilton@FIRSTHEALTH.COM>
Subject: Re: retrieving 4 byte numerics with PEEK
Content-Type: text/plain; charset=us-ascii
I'm not sure whether the code below actually produces the correct
results or whether something gets flipped, but your code might be
simplified by writing the variables into a string, and then reading the
string. That eliminates all the peeks and pokes.
=====
filename buffer catalog 'work.io.buffer.source' lrecl=80 recfm=f;
data _null_;
file buffer lrecl=80 recfm=f;
put '@';
run;
/* Sample data */
data test;
do i = 1 to 2;
array vars var1-var6;
do over vars;
*vars = ranuni(0)*100;
vars = i * _i_;
charreph = put(peek(addr(vars)+4, 4), hex8.);
charrepb = put(peek(addr(vars)+4, 4), binary32.);
put vars=z2. vars=hex16. charreph= charrepb;
end;
output;
end;
drop i;
run;
/* Write 4-byte chunks */
data _null_;
length mydatastring $24.;
infile buffer sharebuffers lrecl=80 recfm=f;
file buffer;
input @@; /* Make sure buffer exists */
set test;
put @1 (var1-var6) (ieee4.) @@;
mydatastring = _infile_;
file log;
put mydatastring=$hex48.;
run;
=====
That code doesn't handle the conversion of mydatastring to base 64.
The technique of writing to a shared buffer with the PUT statement and
then reading _INFILE_ has other applications.
--
JackHamilton@FirstHealth.com
Manager, Technical Development
Metrics Department, First Health
West Sacramento, California USA
Coelum, non animum mutant, qui trans mare currunt.
>>> "Dale McLerran" <stringplayer_2@YAHOO.COM> 01/05/2005 3:43 PM >>>
Thanks to Harry and Jack, I believe that I have a solution to
my base64 encoding problem. Harry provided the base64 encoder.
Jack has shown how to recover the single precision float value
from the double precision float which SAS writes to memory
during a datastep. The last 4 bytes of the double float read
employing rb4 format yield the single precision float values.
I can POKE the single precision values into the correct slot
of a character variable of length N where N is the number of
MZ/Intensity pairs that I need to write. The base64 encoder
from Harry can be employed to write the output value. Below
is some code to illustrate.
/* Start of base64 encoder from Harry Droogendyk */
data exceptn;
label = '=';
hlo = 'O';
run;
data base64 (keep=fmtname start label hlo type);
retain fmtname "base64f"
type "N"
;
/*******************************
/* letters A-Z
/*******************************/
do start = 0 to 25;
label = byte(start+65);
output;
end;
/*******************************
/* letters a-z
/*******************************/
do start = 26 to 51;
label = byte(start+71);
output;
end;
/*******************************
/* numerals 0-9
/*******************************/
do start = 52 to 61;
label = byte(start-4);
output;
end;
/*******************************
/* special characters + /
/*******************************/
label = '+'; start = 62; output;
label = '/'; start = 63; output;
set exceptn ;
stop;
run;
proc format cntlin=base64;
run;
/* End of base64 encoder from Harry Droogendyk */
/* Use encoder to write base64 representation */
/* for 3 MZ/Intensity pairs */
data test;
/* Construct character variable Z of length 3 and */
/* return address for start of the character variable */
length z $3;
MemStart_z = addr(z);
/* Construct three MZ/Intensity paired values and */
/* write last 4 bytes of each value to incremented */
/* bins of character variable Z. */
put "Original 8 byte mz and intensity values";
do mz=427.338, 1096.701, 39374.893;
intensity=rannor(1234579);
put mz= intensity=; /* Show original values */
point+1;
MemStart_mz=addr(mz);
/* Put single precision mz value into appropriate bin of Z */
call poke(peekc(MemStart_mz+4,4),MemStart_z+4*(point-1));
point+1;
MemStart_Int = addr(intensity);
/* Put single precision intensity value into appropriate bin of Z
*/
call poke(peekc(MemStart_Int+4,4),MemStart_z+4*(point-1));
end;
/* See if I can recover mz and intensity values */
put / "Recovered 4 byte mz and intensity values";
do i=1 to point-1 by 2;
j=i+1;
mz = input(peekc(MemStart_z+4*(i-1)), rb4.);
intensity = input(peekc(MemStart_z+4*(j-1)), rb4.);
put mz= intensity=;
end;
/* Base64 encode character variable Z */
do i = 1 to length(Z) by 3;
do x = 1 to 4;
frmt = compress('bits6.' || (x-1)*6 );
chunk = inputn(substr(Z,i,3),frmt);
put chunk base64f. @;
end;
end;
run;
We certainly see some roundoff errors in the returned MZ/Intensity
values when they are recovered from just the last four bytes of
the double precision variables. However, that is something for
the mzXML standard to be concerned with. For my purpose of
being able to write a mzXML file as base64 encoded single precision
values all strung together in memory, I believe my problem is
solved.
Thanks!
Dale
--- Jack Hamilton <JackHamilton@FIRSTHEALTH.COM> wrote:
> Perhaps it's a byte-order problem? Compare with
>
> =====
> 409 data _null_;
> 410 length orig four char4 4
> 411 eight char8 8;
> 412 orig = 25;
> 413 z = addr(orig);
> 414 four = peek(z+4,4);
> 415 eight = peek(z,8);
> 416 char4 = input(peekc(z+4,4),rb4.);
> 417 char8 = input(peekc(z,8),rb8.);
> 418 put orig= four= eight= char4= char8=;
> 419 run;
>
> orig=25 four=1077477376 eight=25 char4=25 char8=25
> =====
>
>
>
>
> --
> JackHamilton@FirstHealth.com
> Manager, Technical Development
> Metrics Department, First Health
> West Sacramento, California USA
>
> Coelum, non animum mutant, qui trans mare currunt.
>
>
> >>> "Harry Droogendyk" <harry.droogendyk@RBC.COM> 01/05/2005 1:48 PM
> >>>
> Listers:
>
> In the quest to provide a fuller solution to Dale's base64 query, I
> encountered this. I'd surely appreciate the wisdom of y'all.
>
> Dale informed us that his data was stored in "single precision
> (4-byte) floats". Why doesn't PEEKing 4 bytes from the ADDRess of a
> 4 byte numeric variable ( i.e. a 4-byte float ) work? I'd expect
> variables FOUR and CHAR4 to have the correct values, they don't.
>
> 2359 data _null_;
> 2360 length orig four char4 4
> 2361 eight char8 8;
> 2362 orig = 25;
> 2363 z = addr(orig);
> 2364 four = peek(z,4);
> 2365 eight = peek(z,8);
> 2366 char4 = input(peekc(z,4),rb4.);
> 2367 char8 = input(peekc(z,8),rb8.);
> 2368 put orig= four= eight= char4= char8=;
> 2369 run;
>
> orig=25 four=0 eight=25 char4=0 char8=25
>
> TIA
=====
---------------------------------------
Dale McLerran
Fred Hutchinson Cancer Research Center
mailto: dmclerra@NO_SPAMfhcrc.org
Ph: (206) 667-2926
Fax: (206) 667-5977
---------------------------------------
__________________________________
Do you Yahoo!?
Read only the mail you want - Yahoo! Mail SpamGuard.
http://promotions.yahoo.com/new_mail
"MMS <firsthealth.com>" made the following annotations.
------------------------------------------------------------------------------
This message, including any attachments, is intended solely for the use
of the named recipient(s) and may contain confidential and/or
privileged information. Any unauthorized review, use, disclosure or
distribution of this communication(s) is expressly prohibited.
If you are not the intended recipient, please contact the sender by
reply e-mail and destroy any and all copies of the original message.
Thank you.
=============================================================================