LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (January 2005, week 1)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
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
Comments: To: stringplayer_2@YAHOO.COM
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. =============================================================================


Back to: Top of message | Previous page | Main SAS-L page