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 15:43:49 -0800
Reply-To:   Dale McLerran <stringplayer_2@YAHOO.COM>
Sender:   "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
Comments:   DomainKeys? See http://antispam.yahoo.com/domainkeys
From:   Dale McLerran <stringplayer_2@YAHOO.COM>
Subject:   Re: retrieving 4 byte numerics with PEEK
In-Reply-To:   <s1dc0741.051@SLCM02.firsthealth.com>
Content-Type:   text/plain; charset=us-ascii

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


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