Jump to content
IGNORED

So, what about strings?


Recommended Posts

There's been much discussion over the years about the floating point system in Atari BASIC, but one topic that doesn't get so much attention is strings.

 

AB had pre-defined string lengths, like HP BASIC. These sat in the heap and were pointed to from the variable table. Upsides and downsides are well defined.

 

MS used a linked list of strings (IIRC) and did GC when required. BBC used a similar system, but just coughed a out-of-memory instead of any sort of GC.

 

Are these the only approaches that have been used in BASICs?

  • Like 1
Link to comment
Share on other sites

Well, MS BASIC on PC is a bit different.  It has one large heap for strings just under the stack, a scalar variable space just after the program, and an array variable space just after that.

Both temporarily created strings and assigned ones go into the string heap.  This heap is contiguous.  In the scalar and array variable space, the data for a string variable element is a 3-byte buffer.  First byte is the length and the other two bytes point to the location of the string.

 

Note that if the string is a literal from the program, the descriptor points to the string within the program instead of copying the string to the string heap.  So that saves you some room as long as you don't modify the string.

 

If BASIC needs to add an array or string variable and finds that the two buffers have butted up against each other, it goes through string GC, where it searches for any unreferenced strings in the heap and copies still-referenced string data over it, and shrinks the string buffer down to what's left.

 

One interesting note:  Every reference to chr$() consumes a spot in the string table.  So if you are going to use the same single-chars, like in line-drawing applications, assign them once to a string variable and then always use the string variable.  Don't litter your program with "print chr$(219)" or whatever.

  • Like 1
Link to comment
Share on other sites

Atari Basic has the very powerful function in that you can easily do moves and insertions where other Basics require the entire string to be reconstructed.  Also, most traditional Basics only support 256 character strings - though for normal string functions that's usually plenty.

 

The useful functions of LEFT$ MID$ and RIGHT$ aren't there but can be simulated with a little bit of work.

 

The big weakness though is INSTR which performs a search for a substring.  Without resorting to assembly you'd have to perform a walkthrough loop to see if the second string exists which is a lot slower.

 

The other "weakness" is that porting programs becomes harder - most other Basics do strings the same and need no change to their operations.

Link to comment
Share on other sites

Hi!

5 hours ago, Maury Markowitz said:

There's been much discussion over the years about the floating point system in Atari BASIC, but one topic that doesn't get so much attention is strings.

 

AB had pre-defined string lengths, like HP BASIC. These sat in the heap and were pointed to from the variable table. Upsides and downsides are well defined.

 

MS used a linked list of strings (IIRC) and did GC when required. BBC used a similar system, but just coughed a out-of-memory instead of any sort of GC.

 

Are these the only approaches that have been used in BASICs?

FastBasic uses a different approach (the "turbo pascal string" approach), string *variables* are allocated with 256 bytes on first assignment, and never de-allocated. All string functions take a pointer to the string as argument, a null pointer is treated as a zero-length string. Constant strings are not allocated, and functions that return a string have a buffer for each function.

String assignment and concatenation receive the pointer to the variable, and allocate a new string if needed or modify the already allocated string.

 

This scheme allows having string arrays that are the same as integer arrays, it is fast for short strings and the code is simple and small.

 

I tried implementing garbage-collected strings, but it was much slower as it needed to store a table of "used" strings that should be updated on each string operation, this means that the string operations were a lot more complicated. And as garbage-collected strings are of fixed length, any concatenation means allocating a new string and copying both.

 

Link to comment
Share on other sites

String handling is one of the things that may have hurt Atari 8 bit sales.
There seemed to be a perception in magazines that Atari BASIC was more suited for games than business.
While BCD math was cited as being better suited for business programs, that's about where the pros of Atari BASIC seemed to end.
The slow speed was the most often cited problem with Atari BASIC, but string handling is definitely something that was brought up in magazines. 
PRINT USING was the other thing that was commonly referred to as a business oriented feature, and that takes up a lot of ROM real estate.
I'm not sure PRINT USING even made an appearance on a 6502 BASIC until Atari MS BASIC came out, so it's not as big of a deal.
If you wanted those features, you bought a TRS-80, but you sacrificed other things by doing that.  
When you try to squeeze a lot of stuff in a small ROM, something has to give.
String functions, and PRINT USING seems to have been what was left out.

A couple of the modifications I made to the MC-10 ROM, were changing from 8 bit, to 16 bit memory copies, and string compare functions.
Using a lot of 1 byte strings might be slightly slower, but that's more than made up for by the faster speed of the rest of the interpreter. 
The change is very noticeable when manipulating, or comparing long strings.  
Sadly, you can't make those optimizations on the 6502, and the penalty for mode switching on the 65816 would probably mean string compares would be slower on strings under 4, or more, bytes in length. 
The memory moves should be faster on the 65816 due to the memory move instructions, but not by a large amount due to the setup time, and number of clock cycles required per byte moved.  

As for how MS BASIC stores strings vs Fast BASIC... it may not be the fastest approach, but MS BASIC was designed to run with as little as 4K of RAM.  When you start allocating 256 bytes for every string, you are going to run out of RAM in a hurry in certain cases.  My test program to compare string, and memory move changes, reads 891 of the most popular sir names, and related info from DATA statements, then arranges them in alphabetical order.  Unless I misunderstood what Fast BASIC does, that would require 228,096 bytes, or almost 223K of RAM just for the string variable portion of the data. 
As long as you aren't dealing with a lot of strings, the Fast BASIC approach may be superior, but it sounds like it's a memory hog. 
For strings that will ALWAYS be a shorter length, and are rarely if ever manipulated, some form of packed or compact string might be in order.
Or did I miss something?
 

  • Like 1
Link to comment
Share on other sites

9 minutes ago, _The Doctor__ said:

5 years later, different processor, different ram constraints and costs for the MC-10... but I'm glad you are working to make some changes they should have made at it's inception. Good stuff.

The MC-10 is pretty much 1977 technology with newer SRAMs and ROM.  

Link to comment
Share on other sites

exactly, lower costs, newer rams and rom... and a few other things. There was a good deal of 1970's tech that put all home computers to shame, of course some couldn't be brought for cost others for size. It became easy to bring things home a few years later as well cheaper smaller and more available with patents applied. Simply a good thing you are making the changes that should have been made at the mc-10's release which was some 5 years later. Glad to see you working on it. Are you working towards releasing the modifications as rom and software, or is this basically a private experiment.

 

At the time Atari was delivering 400's and 800's the processor used later in the MC-10 was around $185.00 -$200.00 dollars at cost, and hard to get, where as the 6502 was about $22. easy to get and had much better volume discounts.

Edited by _The Doctor__
  • Like 1
Link to comment
Share on other sites

57 minutes ago, _The Doctor__ said:

exactly, lower costs, newer rams and rom... and a few other things. There was a good deal of 1970's tech that put all home computers to shame, of course some couldn't be brought for cost others for size. It became easy to bring things home a few years later as well cheaper smaller and more available with patents applied. Simply a good thing you are making the changes that should have been made at the mc-10's release which was some 5 years later. Glad to see you working on it. Are you working towards releasing the modifications as rom and software, or is this basically a private experiment.

 

At the time Atari was delivering 400's and 800's the processor used later in the MC-10 was around $185.00 -$200.00 dollars at cost, and hard to get, where as the 6502 was about $22. easy to get and had much better volume discounts.

By 1977/78, electronics distributors had magazine ads listing the 6800 at $25 for one.  I looked it up in an issue of Kilobaud magazine.  Quantity from Motorola would obviously be less.  The problem is, you won't find the 6803 or 6847 at electronics distributors at that time, you'd have to go to Motorola to even know they existed. 

Based on the prices I've found, in 1977 you should have been able to build a one-of prototype MC-10 ish system using parts ordered from magazine ads, along with sample 6803, and 6847s, (no quantity discount) for under $400.  Most of that is the RAM, and EPROMs.  The magazine price for a 1K EPROM was $45!  You could probably build a production model for half that.

Link to comment
Share on other sites

As I spoke to (or about) the processors in mc-10 and the Atari machines- to be sure, we could go on forever about all the other offerings of this or that.

 

Exactly and certainly correct at that time you won't find a 6803, as I said 'hard to come by' and expensive... You might be able to build, probably, or should have been able to build this or that doesn't enter into it. No one built it because at the time it wasn't feasible. Five years later, No problem. I was thinking on looking for the old price out sheets on this stuff, but realized there isn't a point to it really, if I recall getting a 'sample' as you put it took almost 2 years for our request. They just weren't handing them out like that. I did however find via google that my price quote is exactly in line with what was. Surprisingly my failing memory still wasn't all that bad at that moment.

Edited by _The Doctor__
Link to comment
Share on other sites

I did not have to dig up my old price out sheets, ..  I can't imagine you couldn't pull up a reference to any price. I really must be into wasting time... this might take a minute.... wiki has some prices listed though, I can't speak to accuracy since they list 20 or 25 for for our 6502 class bargains chips.

 

Since even wiki lists a later price of a single MC6800 microprocessor at $175.00.... I suspect my 6803 quote will be found accurate as you scrub around. I know at first search between when I posted and your post I saw info on one wiki or wiki like site or another with similar info including specific mc6803 pricing and versions, there were a few it would seem.

Edited by _The Doctor__
Link to comment
Share on other sites

Wiki?  The wiki doesn't have the price of the 6801 any of it's variations.  That's the 6800 price. 
This video goes into details on 6800 pricing among other things:
https://archive.org/details/VCFE7_SWTP

Here is where you can find a 6800 MPU for under $25 in 1977 on the top right page, and you can find that ad in issue after issue. 
The 6800L is $35 in a later issue, and that's the ceramic version with gold pins. 
https://archive.org/details/Kilobaud197711/page/n131

FWIW, I used the price of the 6800L in my estimate just in case.

*edit*
I didn't see your change about 6803 pricing until after I posted this.
If the wiki says the 6800 is $175 but the magazine has it for $25, what does that tell you about the $185 6803 pricing?
 

Edited by JamesD
  • Like 1
Link to comment
Share on other sites

I just know what it was then and how long it took, how old was the 6800 and what was it replaced with in 1978? it's a matter of time the seller in the  magazine is showing sale ending in November and it appears to be from a place that clears out stuff. Incidentally carrying your namesake. JAMES electronics.

 

It doesn't surprise me in another year you might have bought them for 11 dollars if the price is correct. Since new chips come out faster and cheaper at a ridiculous pace early on. See some of the prices for memory and processor cards. It's the same deal, a card one year could be 499.00 and the next 128.00

It is what it is, I just went through a good portion of the kilobaud archive and haven't found an mc6803 in the magazine, perhaps kilbaud says they were non existent but we know they are real.... so what to do...  The magazine was around for 7 years... Mr.Green was a crazy guy who wasn't exactly accurate in a number of his published pages. It's quite an interesting story about his ex wife, kiloByte, kilobaud, and Byte magazine. Incredible drama, and I don't know why it all made news.... perhaps because of his political ambitions and what the ex wife and new her husband did... it didn't help his employees chimed in either. There's a book the about mr green. but don't put 100 percent stock in what the pages contain, it was written by the ex wife's new husband!

 

see what you did, we have more trivia crammed into our failing grey matter. I knew I'd end up wasting time.... I should have been mashing keys or mauling a joystick.

 

Thanks for the rabbit hole, I think it's bedtime.

 

Edited by _The Doctor__
Link to comment
Share on other sites

for a laugh, check out this kit...

jump to page 50 or page 20 depending on your pdf reader... they'll stack the deck for you at new incredibly low prices!

http://www.thecomputerarchive.com/Catalogs and Price Lists/Mail Order/Advanced Computer Products (1978) Catalog pages 031-060.pdf

these are some serious bargains!

:)

 

I wander what some of the younger folks think of these prices

Link to comment
Share on other sites

Based on the video, and the pricing discrepancy... if you were a big company someone thought they would make a lot of money, you'd get it cheap, or possibly even free.  If you were a small company they never heard of, you'd pay through the nose for one, or have to buy from a reseller that is buying in quantity.  My estimate is probably correct for a reseller... if you can't find someone that carries it you are paying $185-$200.   
Motorola didn't even try to market it until 1979 according to one article, even though it was in the Cadillac Seville starting in 1977, so you probably wont find anyone selling them until 79 as it supposedly wasn't in their sales literature before that.  Unless the sales person can be smooth talked with promises of 20,000 units, my estimate is off by $150 for the prototype, but probably close for production... if they will sell you the chips.

I still can't see it taking 2 years to get a part.  Let's face it, there were probably less than 15,000 of those Cadilacs sold, and the digital trip meter that used the 6801 was a $920 option.  Surely the chips could be produced faster than demand for that. But then two years works out to about when the 6805 came out... which was a cheaper design, and it was very popular with auto makers.  Coincidence?  But then, that's also when they switched from NMOS to CMOS and the die yield went up.

Those prices is crazy.  You can buy a full keyboard for $33, but a keyboard encoder chip costs another $15.
A 6800 kit was $145, which is cheaper than the KIM 1, but the KIM 1 is assembled, and might have included more stuff.
A computerized Backgammon game is $130
$2345 for a 48K Apple II, with integer BASIC.  Any wonder why Atari thought they could make money selling computers?
Anyway, this hijack of the thread has run it's course.  Back to Atari and string handling... I hope.

  • Like 1
Link to comment
Share on other sites

7 hours ago, _The Doctor__ said:

I always found the method used for Atari in manipulation and concatenation of strings very efficient in it's use of memory.

I don't think it's a memory efficiency issue with Atari BASIC, it was more about functions, and maybe how easy it is to do something.
LEFT$, RIGHT$, MID$, INSTR$ are the typical BASIC string functions that were mentioned to compare string handling features.
Even if the parser is slow on the Atari, those should be pretty fast.
I know Atari BASIC strings are an array of characters, but what about an array of strings?  

Fast BASIC may not be efficient memory wise with strings, but it's efficient speed wise. 
It limits what you can do with it, but I'm not sure anyone is writing business software for the Atari these days.
It's probably more of an issue of whether you could use it for a BASIC adventure game or something like that.

Here is the quick n dirty data/string/sort test I use.  This is really easy in MS BASIC, but how do you do it in Atari BASIC?

Spoiler

' Scan through the data to decide how large the array needs to be (this lets me easily add/delete data, and doubles the amount of data reads)
' dimension the arrays based on the amount of data
' load the arrays
' sort the array alphabetically
' read through the sorted data making sure I didn't screw up the sort routine
' print the sorted list of names. 
' The DATA is the max number the MC-10 can use for this test, it still includes some data I'm not using, and it's in order of frequency of use. 
' It's not quite how I'd do it outside of a benchmark. 
' I'd probably load the data from a file instead of DATA statements, and let you sort based on the different fields using the memory that would free up.


0 I=0:N=1000:C=0:D=0:E=0:NW=0
'initialize the index array, and read in the names.  Skip the other data.
1 N=0
2 CLS:PRINT"READ, LIST, AND SORT MOST POPULAR SIR NAMES"
3 PRINT"SCANNING FOR END OF DATA"
4 READ K$,C,D,E:IF K$<>"" THEN N=N+1:GOTO4
5 RESTORE

6 PRINT N" NAMES IN DATA, INITIALIZING ARRAYS"
7 DIM A$(N),B(N)
8 FORI=1TON:READ A$(I),C,D,E:B(I)=I:NEXT

'9 PRINT"UNSORTED DATA":PRINT
'10 GOSUB 23

11 PRINT:PRINT "SORTING"N"NAMES BY ALPHABETICAL ORDER"
12 PRINT"#S ARE CURRENT GAP FOR EACH SORT PASS":GOSUB 18

13 PRINT:PRINT "VERIFYING THE ORDER IS SORTED"
14 GOSUB 21:IFR=1THENSTOP

15 GOSUB 23
16 PRINT:PRINT"DONE"
17 END


'comb sort.  
'p = what we divide the array size by to get the gap
'G = the gap
'using nested for loops avoids having to perform a line search that would
'happen using GOTO. The address is simply pulled off of the stack.
'using STEP 0 keeps FOR NEXT from changing the variable and the endless loop
'exits once the exit condition is achieved
18 P=1:F=1.3:FORG=1TO0STEP0:P=P*F:G=INT(N/P):NW=N-G:PRINTG;
19 R=0:FORI=1TONW:IFA$(B(I))>A$(B(I+G))THENT=B(I):B(I)=B(I+G):B(I+G)=T
20 NEXT:NEXT:RETURN


'check to see if names are in order
21 R=0:FOR I=1 TO N-1:IFA$(B(I))>A$(B(I+1))THENPRINT"OUT OF ORDER "A$(B(I)):R-1
22 NEXT:RETURN
 

'print out the names based on the array index
23 FOR I=1 TO N:PRINT A$(B(I))" ";:NEXT:RETURN


'1000 MOST POPULAR SIR NAMES FROM MOST TO LEAST POPULAR

100 DATA SMITH,2501922,1.006,1,JOHNSON,2014470,.81,2,WILLIAMS,1738413,.699,3
101 DATA JONES,1544427,.621,4,BROWN,1544427,.621,5,DAVIS,1193760,.48,6
102 DATA MILLER,1054488,.424,7,WILSON,843093,.339,8,MOORE,775944,.312,9
103 DATA TAYLOR,773457,.311,10,ANDERSON,773457,.311,11,THOMAS,773457,.311,12
104 DATA JACKSON,770970,.31,13,WHITE,693873,.279,14,HARRIS,683925,.275,15
105 DATA MARTIN,678951,.273,16,THOMPSON,669003,.269,17,GARCIA,631698,.254,18
106 DATA MARTINEZ,581958,.234,19,ROBINSON,579471,.233,20,CLARK,574497,.231,21
107 DATA RODRIGUEZ,569523,.229,22,LEWIS,562062,.226,23,LEE,547140,.22,24
108 DATA WALKER,544653,.219,25,HALL,497400,.2,26,ALLEN,494913,.199,27
109 DATA YOUNG,479991,.193,28,HERNANDEZ,477504,.192,29,KING,472530,.19,30
110 DATA WRIGHT,470043,.189,31,LOPEZ,465069,.187,32,HILL,465069,.187,33
111 DATA SCOTT,460095,.185,34,GREEN,455121,.183,35,ADAMS,432738,.174,36
112 DATA BAKER,425277,.171,37,GONZALEZ,412842,.166,38,NELSON,402894,.162,39
113 DATA CARTER,402894,.162,40,MITCHELL,397920,.16,41,PEREZ,385485,.155,42
114 DATA ROBERTS,380511,.153,43,TURNER,378024,.152,44,PHILLIPS,370563,.149,45
115 DATA CAMPBELL,370563,.149,46,PARKER,363102,.146,47,EVANS,350667,.141,48
116 DATA EDWARDS,340719,.137,49,COLLINS,333258,.134,50,STEWART,330771,.133,51
117 DATA SANCHEZ,323310,.13,52,MORRIS,310875,.125,53,ROGERS,305901,.123,54
118 DATA REED,303414,.122,55,COOK,298440,.12,56,MORGAN,293466,.118,57
119 DATA BELL,290979,.117,58,MURPHY,290979,.117,59,BAILEY,286005,.115,60
120 DATA RIVERA,281031,.113,61,COOPER,281031,.113,62,RICHARDSON,278544,.112,63
121 DATA COX,273570,.11,64,HOWARD,273570,.11,65,WARD,268596,.108,66
122 DATA TORRES,268596,.108,67,PETERSON,266109,.107,68,GRAY,263622,.106,69
123 DATA RAMIREZ,261135,.105,70,JAMES,261135,.105,71,WATSON,256161,.103,72
124 DATA BROOKS,256161,.103,73,KELLY,253674,.102,74,SANDERS,248700,.1,75
125 DATA PRICE,246213,.099,76,BENNETT,246213,.099,77,WOOD,243726,.098,78
126 DATA BARNES,241239,.097,79,ROSS,238752,.096,80,HENDERSON,236265,.095,81
127 DATA COLEMAN,236265,.095,82,JENKINS,236265,.095,83,PERRY,233778,.094,84
128 DATA POWELL,231291,.093,85,LONG,228804,.092,86,PATTERSON,228804,.092,87
129 DATA HUGHES,228804,.092,88,FLORES,228804,.092,89,WASHINGTON,228804,.092,90
130 DATA BUTLER,226317,.091,91,SIMMONS,226317,.091,92,FOSTER,226317,.091,93
131 DATA GONZALES,216369,.087,94,BRYANT,216369,.087,95,ALEXANDER,211395,.085,96
132 DATA RUSSELL,211395,.085,97,GRIFFIN,208908,.084,98,DIAZ,208908,.084,99
133 DATA HAYES,206421,.083,100,MYERS,206421,.083,101,FORD,203934,.082,102
134 DATA HAMILTON,203934,.082,103,GRAHAM,203934,.082,104,SULLIVAN,201447,.081,105
135 DATA WALLACE,201447,.081,106,WOODS,198960,.08,107,COLE,198960,.08,108
136 DATA WEST,198960,.08,109,JORDAN,193986,.078,110,OWENS,193986,.078,111
137 DATA REYNOLDS,193986,.078,112,FISHER,191499,.077,113,ELLIS,191499,.077,114
138 DATA HARRISON,189012,.076,115,GIBSON,186525,.075,116,MCDONALD,186525,.075,117
139 DATA CRUZ,186525,.075,118,MARSHALL,186525,.075,119,ORTIZ,186525,.075,120
140 DATA GOMEZ,186525,.075,121,MURRAY,184038,.074,122,FREEMAN,184038,.074,123
141 DATA WELLS,181551,.073,124,WEBB,179064,.072,125,SIMPSON,174090,.07,126
142 DATA STEVENS,174090,.07,127,TUCKER,174090,.07,128,PORTER,171603,.069,129
143 DATA HUNTER,171603,.069,130,HICKS,171603,.069,131,CRAWFORD,169116,.068,132
144 DATA HENRY,169116,.068,133,BOYD,169116,.068,134,MASON,169116,.068,135
145 DATA MORALES,166629,.067,136,KENNEDY,166629,.067,137,WARREN,166629,.067,138
146 DATA DIXON,164142,.066,139,RAMOS,164142,.066,140,REYES,164142,.066,141
147 DATA BURNS,161655,.065,142,GORDON,161655,.065,143,SHAW,161655,.065,144
148 DATA HOLMES,161655,.065,145,RICE,159168,.064,146,ROBERTSON,159168,.064,147
149 DATA HUNT,156681,.063,148,BLACK,156681,.063,149,DANIELS,154194,.062,150
150 DATA PALMER,154194,.062,151,MILLS,151707,.061,152,NICHOLS,149220,.06,153
151 DATA GRANT,149220,.06,154,KNIGHT,149220,.06,155,FERGUSON,146733,.059,156
152 DATA ROSE,146733,.059,157,STONE,146733,.059,158,HAWKINS,146733,.059,159
153 DATA DUNN,144246,.058,160,PERKINS,144246,.058,161,HUDSON,144246,.058,162
154 DATA SPENCER,141759,.057,163,GARDNER,141759,.057,164,STEPHENS,141759,.057,165
155 DATA PAYNE,141759,.057,166,PIERCE,139272,.056,167,BERRY,139272,.056,168
156 DATA MATTHEWS,139272,.056,169,ARNOLD,139272,.056,170,WAGNER,136785,.055,171
157 DATA WILLIS,136785,.055,172,RAY,136785,.055,173,WATKINS,136785,.055,174
158 DATA OLSON,136785,.055,175,CARROLL,136785,.055,176,DUNCAN,136785,.055,177
159 DATA SNYDER,136785,.055,178,HART,134298,.054,179,CUNNINGHAM,134298,.054,180
160 DATA BRADLEY,134298,.054,181,LANE,134298,.054,182,ANDREWS,134298,.054,183
161 DATA RUIZ,134298,.054,184,HARPER,134298,.054,185,FOX,131811,.053,186
162 DATA RILEY,131811,.053,187,ARMSTRONG,131811,.053,188,CARPENTER,131811,.053,189
163 DATA WEAVER,131811,.053,190,GREENE,131811,.053,191,LAWRENCE,129324,.052,192
164 DATA ELLIOTT,129324,.052,193,CHAVEZ,129324,.052,194,SIMS,129324,.052,195
165 DATA AUSTIN,129324,.052,196,PETERS,129324,.052,197,KELLEY,129324,.052,198
166 DATA FRANKLIN,126837,.051,199,LAWSON,126837,.051,200,FIELDS,126837,.051,201
167 DATA GUTIERREZ,126837,.051,202,RYAN,126837,.051,203,SCHMIDT,126837,.051,204
168 DATA CARR,126837,.051,205,VASQUEZ,126837,.051,206,CASTILLO,126837,.051,207
169 DATA WHEELER,126837,.051,208,CHAPMAN,124350,.05,209,OLIVER,124350,.05,210
170 DATA MONTGOMERY,121863,.049,211,RICHARDS,121863,.049,212,WILLIAMSON,121863,.049,213
171 DATA JOHNSTON,121863,.049,214,BANKS,119376,.048,215,MEYER,119376,.048,216
172 DATA BISHOP,119376,.048,217,MCCOY,119376,.048,218,HOWELL,119376,.048,219
173 DATA ALVAREZ,119376,.048,220,MORRISON,119376,.048,221,HANSEN,116889,.047,222
174 DATA FERNANDEZ,116889,.047,223,GARZA,116889,.047,224,HARVEY,116889,.047,225
175 DATA LITTLE,114402,.046,226,BURTON,114402,.046,227,STANLEY,114402,.046,228
176 DATA NGUYEN,114402,.046,229,GEORGE,114402,.046,230,JACOBS,114402,.046,231
177 DATA REID,114402,.046,232,KIM,111915,.045,233,FULLER,111915,.045,234
178 DATA LYNCH,111915,.045,235,DEAN,111915,.045,236,GILBERT,111915,.045,237
179 DATA GARRETT,111915,.045,238,ROMERO,111915,.045,239,WELCH,109428,.044,240
180 DATA LARSON,109428,.044,241,FRAZIER,109428,.044,242,BURKE,109428,.044,243
181 DATA HANSON,106941,.043,244,DAY,106941,.043,245,MENDOZA,106941,.043,246
182 DATA MORENO,106941,.043,247,BOWMAN,106941,.043,248,MEDINA,104454,.042,249
183 DATA FOWLER,104454,.042,250,BREWER,104454,.042,251,HOFFMAN,104454,.042,252
184 DATA CARLSON,104454,.042,253,SILVA,104454,.042,254,PEARSON,104454,.042,255
185 DATA HOLLAND,104454,.042,256,DOUGLAS,101967,.041,257,FLEMING,101967,.041,258
186 DATA JENSEN,101967,.041,259,VARGAS,101967,.041,260,BYRD,101967,.041,261
187 DATA DAVIDSON,101967,.041,262,HOPKINS,101967,.041,263,MAY,99480,.04,264
188 DATA TERRY,99480,.04,265,HERRERA,99480,.04,266,WADE,99480,.04,267
189 DATA SOTO,99480,.04,268,WALTERS,99480,.04,269,CURTIS,99480,.04,270
190 DATA NEAL,96993,.039,271,CALDWELL,96993,.039,272,LOWE,96993,.039,273
191 DATA JENNINGS,96993,.039,274,BARNETT,96993,.039,275,GRAVES,96993,.039,276
192 DATA JIMENEZ,96993,.039,277,HORTON,96993,.039,278,SHELTON,96993,.039,279
193 DATA BARRETT,96993,.039,280,OBRIEN,96993,.039,281,CASTRO,96993,.039,282
194 DATA SUTTON,94506,.038,283,GREGORY,94506,.038,284,MCKINNEY,94506,.038,285
195 DATA LUCAS,94506,.038,286,MILES,94506,.038,287,CRAIG,94506,.038,288
196 DATA RODRIQUEZ,92019,.037,289,CHAMBERS,92019,.037,290,HOLT,92019,.037,291
197 DATA LAMBERT,92019,.037,292,FLETCHER,92019,.037,293,WATTS,92019,.037,294
198 DATA BATES,92019,.037,295,HALE,92019,.037,296,RHODES,92019,.037,297
199 DATA PENA,92019,.037,298,BECK,92019,.037,299,NEWMAN,89532,.036,300
200 DATA HAYNES,89532,.036,301,MCDANIEL,89532,.036,302,MENDEZ,89532,.036,303
201 DATA BUSH,89532,.036,304,VAUGHN,89532,.036,305,PARKS,87045,.035,306
202 DATA DAWSON,87045,.035,307,SANTIAGO,87045,.035,308,NORRIS,87045,.035,309
203 DATA HARDY,87045,.035,310,LOVE,87045,.035,311,STEELE,87045,.035,312
204 DATA CURRY,87045,.035,313,POWERS,87045,.035,314,SCHULTZ,87045,.035,315
205 DATA BARKER,87045,.035,316,GUZMAN,84558,.034,317,PAGE,84558,.034,318
206 DATA MUNOZ,84558,.034,319,BALL,84558,.034,320,KELLER,84558,.034,321
207 DATA CHANDLER,84558,.034,322,WEBER,84558,.034,323,LEONARD,84558,.034,324
208 DATA WALSH,82071,.033,325,LYONS,82071,.033,326,RAMSEY,82071,.033,327
209 DATA WOLFE,82071,.033,328,SCHNEIDER,82071,.033,329,MULLINS,82071,.033,330
210 DATA BENSON,82071,.033,331,SHARP,82071,.033,332,BOWEN,82071,.033,333
211 DATA DANIEL,82071,.033,334,BARBER,79584,.032,335,CUMMINGS,79584,.032,336
212 DATA HINES,79584,.032,337,BALDWIN,79584,.032,338,GRIFFITH,79584,.032,339
213 DATA VALDEZ,79584,.032,340,HUBBARD,79584,.032,341,SALAZAR,79584,.032,342
214 DATA REEVES,79584,.032,343,WARNER,77097,.031,344,STEVENSON,77097,.031,345
215 DATA BURGESS,77097,.031,346,SANTOS,77097,.031,347,TATE,77097,.031,348
216 DATA CROSS,77097,.031,349,GARNER,77097,.031,350,MANN,77097,.031,351
217 DATA MACK,77097,.031,352,MOSS,77097,.031,353,THORNTON,77097,.031,354
218 DATA DENNIS,77097,.031,355,MCGEE,77097,.031,356,FARMER,74610,.03,357
219 DATA DELGADO,74610,.03,358,AGUILAR,74610,.03,359,VEGA,74610,.03,360
220 DATA GLOVER,74610,.03,361,MANNING,74610,.03,362,COHEN,74610,.03,363
221 DATA HARMON,74610,.03,364,RODGERS,74610,.03,365,ROBBINS,74610,.03,366
222 DATA NEWTON,74610,.03,367,TODD,74610,.03,368,BLAIR,74610,.03,369
223 DATA HIGGINS,74610,.03,370,INGRAM,74610,.03,371,REESE,74610,.03,372
224 DATA CANNON,74610,.03,373,STRICKLAND,74610,.03,374,TOWNSEND,74610,.03,375
225 DATA POTTER,74610,.03,376,GOODWIN,74610,.03,377,WALTON,74610,.03,378
226 DATA ROWE,72123,.029,379,HAMPTON,72123,.029,380,ORTEGA,72123,.029,381
227 DATA PATTON,72123,.029,382,SWANSON,72123,.029,383,JOSEPH,72123,.029,384
228 DATA FRANCIS,72123,.029,385,GOODMAN,72123,.029,386,MALDONADO,72123,.029,387
229 DATA YATES,72123,.029,388,BECKER,72123,.029,389,ERICKSON,72123,.029,390
230 DATA HODGES,72123,.029,391,RIOS,72123,.029,392,CONNER,72123,.029,393
231 DATA ADKINS,72123,.029,394,WEBSTER,69636,.028,395,NORMAN,69636,.028,396
232 DATA MALONE,69636,.028,397,HAMMOND,69636,.028,398,FLOWERS,69636,.028,399
233 DATA COBB,69636,.028,400,MOODY,69636,.028,401,QUINN,69636,.028,402
234 DATA BLAKE,69636,.028,403,MAXWELL,69636,.028,404,POPE,69636,.028,405
235 DATA FLOYD,67149,.027,406,OSBORNE,67149,.027,407,PAUL,67149,.027,408
236 DATA MCCARTHY,67149,.027,409,GUERRERO,67149,.027,410,LINDSEY,67149,.027,411
237 DATA ESTRADA,67149,.027,412,SANDOVAL,67149,.027,413,GIBBS,67149,.027,414
238 DATA TYLER,67149,.027,415,GROSS,67149,.027,416,FITZGERALD,67149,.027,417
239 DATA STOKES,67149,.027,418,DOYLE,67149,.027,419,SHERMAN,67149,.027,420
240 DATA SAUNDERS,67149,.027,421,WISE,67149,.027,422,COLON,67149,.027,423
241 DATA GILL,67149,.027,424,ALVARADO,67149,.027,425,GREER,64662,.026,426
242 DATA PADILLA,64662,.026,427,SIMON,64662,.026,428,WATERS,64662,.026,429
243 DATA NUNEZ,64662,.026,430,BALLARD,64662,.026,431,SCHWARTZ,64662,.026,432
244 DATA MCBRIDE,64662,.026,433,HOUSTON,64662,.026,434,CHRISTENSEN,64662,.026,435
245 DATA KLEIN,64662,.026,436,PRATT,64662,.026,437,BRIGGS,64662,.026,438
246 DATA PARSONS,64662,.026,439,MCLAUGHLIN,64662,.026,440,ZIMMERMAN,64662,.026,441
247 DATA FRENCH,64662,.026,442,BUCHANAN,64662,.026,443,MORAN,64662,.026,444
248 DATA COPELAND,62175,.025,445,ROY,62175,.025,446,PITTMAN,62175,.025,447
249 DATA BRADY,62175,.025,448,MCCORMICK,62175,.025,449,HOLLOWAY,62175,.025,450
250 DATA BROCK,62175,.025,451,POOLE,62175,.025,452,FRANK,62175,.025,453
251 DATA LOGAN,62175,.025,454,OWEN,62175,.025,455,BASS,62175,.025,456
252 DATA MARSH,62175,.025,457,DRAKE,62175,.025,458,WONG,62175,.025,459
253 DATA JEFFERSON,62175,.025,460,PARK,62175,.025,461,MORTON,62175,.025,462
254 DATA ABBOTT,62175,.025,463,SPARKS,62175,.025,464,PATRICK,59688,.024,465
255 DATA NORTON,59688,.024,466,HUFF,59688,.024,467,CLAYTON,59688,.024,468
256 DATA MASSEY,59688,.024,469,LLOYD,59688,.024,470,FIGUEROA,59688,.024,471
257 DATA CARSON,59688,.024,472,BOWERS,59688,.024,473,ROBERSON,59688,.024,474
258 DATA BARTON,59688,.024,475,TRAN,59688,.024,476,LAMB,59688,.024,477
259 DATA HARRINGTON,59688,.024,478,CASEY,59688,.024,479,BOONE,59688,.024,480
260 DATA CORTEZ,59688,.024,481,CLARKE,59688,.024,482,MATHIS,59688,.024,483
261 DATA SINGLETON,59688,.024,484,WILKINS,59688,.024,485,CAIN,59688,.024,486
262 DATA BRYAN,59688,.024,487,UNDERWOOD,59688,.024,488,HOGAN,59688,.024,489
263 DATA MCKENZIE,57201,.023,490,COLLIER,57201,.023,491,LUNA,57201,.023,492
264 DATA PHELPS,57201,.023,493,MCGUIRE,57201,.023,494,ALLISON,57201,.023,495
265 DATA BRIDGES,57201,.023,496,WILKERSON,57201,.023,497,NASH,57201,.023,498
266 DATA SUMMERS,57201,.023,499,ATKINS,57201,.023,500,WILCOX,57201,.023,501
267 DATA PITTS,57201,.023,502,CONLEY,57201,.023,503,MARQUEZ,57201,.023,504
268 DATA BURNETT,57201,.023,505,RICHARD,57201,.023,506,COCHRAN,57201,.023,507
269 DATA CHASE,57201,.023,508,DAVENPORT,57201,.023,509,HOOD,57201,.023,510
270 DATA GATES,57201,.023,511,CLAY,57201,.023,512,AYALA,57201,.023,513
271 DATA SAWYER,57201,.023,514,ROMAN,57201,.023,515,VAZQUEZ,57201,.023,516
272 DATA DICKERSON,57201,.023,517,HODGE,54714,.022,518,ACOSTA,54714,.022,519
273 DATA FLYNN,54714,.022,520,ESPINOZA,54714,.022,521,NICHOLSON,54714,.022,522
274 DATA MONROE,54714,.022,523,WOLF,54714,.022,524,MORROW,54714,.022,525
275 DATA KIRK,54714,.022,526,RANDALL,54714,.022,527,ANTHONY,54714,.022,528
276 DATA WHITAKER,54714,.022,529,OCONNOR,54714,.022,530,SKINNER,54714,.022,531
277 DATA WARE,54714,.022,532,MOLINA,54714,.022,533,KIRBY,54714,.022,534
278 DATA HUFFMAN,54714,.022,535,BRADFORD,54714,.022,536,CHARLES,54714,.022,537
279 DATA GILMORE,54714,.022,538,DOMINGUEZ,54714,.022,539,ONEAL,54714,.022,540
280 DATA BRUCE,54714,.022,541,LANG,52227,.021,542,COMBS,52227,.021,543
281 DATA KRAMER,52227,.021,544,HEATH,52227,.021,545,HANCOCK,52227,.021,546
282 DATA GALLAGHER,52227,.021,547,GAINES,52227,.021,548,SHAFFER,52227,.021,549
283 DATA SHORT,52227,.021,550,WIGGINS,52227,.021,551,MATHEWS,52227,.021,552
284 DATA MCCLAIN,52227,.021,553,FISCHER,52227,.021,554,WALL,52227,.021,555
285 DATA SMALL,52227,.021,556,MELTON,52227,.021,557,HENSLEY,52227,.021,558
286 DATA BOND,52227,.021,559,DYER,52227,.021,560,CAMERON,52227,.021,561
287 DATA GRIMES,52227,.021,562,CONTRERAS,52227,.021,563,CHRISTIAN,52227,.021,564
288 DATA WYATT,52227,.021,565,BAXTER,52227,.021,566,SNOW,52227,.021,567
289 DATA MOSLEY,52227,.021,568,SHEPHERD,52227,.021,569,LARSEN,52227,.021,570
290 DATA HOOVER,52227,.021,571,BEASLEY,49740,.02,572,GLENN,49740,.02,573
291 DATA PETERSEN,49740,.02,574,WHITEHEAD,49740,.02,575,MEYERS,49740,.02,576
292 DATA KEITH,49740,.02,577,GARRISON,49740,.02,578,VINCENT,49740,.02,579
293 DATA SHIELDS,49740,.02,580,HORN,49740,.02,581,SAVAGE,49740,.02,582
294 DATA OLSEN,49740,.02,583,SCHROEDER,49740,.02,584,HARTMAN,49740,.02,585
295 DATA WOODARD,49740,.02,586,MUELLER,49740,.02,587,KEMP,49740,.02,588
296 DATA DELEON,49740,.02,589,BOOTH,49740,.02,590,PATEL,49740,.02,591
297 DATA CALHOUN,49740,.02,592,WILEY,49740,.02,593,EATON,49740,.02,594
298 DATA CLINE,49740,.02,595,NAVARRO,49740,.02,596,HARRELL,49740,.02,597
299 DATA LESTER,49740,.02,598,HUMPHREY,49740,.02,599,PARRISH,49740,.02,600
300 DATA DURAN,49740,.02,601,HUTCHINSON,49740,.02,602,HESS,49740,.02,603
301 DATA DORSEY,49740,.02,604,BULLOCK,49740,.02,605,ROBLES,49740,.02,606
302 DATA BEARD,47253,.019,607,DALTON,47253,.019,608,AVILA,47253,.019,609
303 DATA VANCE,47253,.019,610,RICH,47253,.019,611,BLACKWELL,47253,.019,612
304 DATA YORK,47253,.019,613,JOHNS,47253,.019,614,BLANKENSHIP,47253,.019,615
305 DATA TREVINO,47253,.019,616,SALINAS,47253,.019,617,CAMPOS,47253,.019,618
306 DATA PRUITT,47253,.019,619,MOSES,47253,.019,620,CALLAHAN,47253,.019,621
307 DATA GOLDEN,47253,.019,622,MONTOYA,47253,.019,623,HARDIN,47253,.019,624
308 DATA GUERRA,47253,.019,625,MCDOWELL,47253,.019,626,CAREY,47253,.019,627
309 DATA STAFFORD,47253,.019,628,GALLEGOS,47253,.019,629,HENSON,47253,.019,630
310 DATA WILKINSON,47253,.019,631,BOOKER,47253,.019,632,MERRITT,47253,.019,633
311 DATA MIRANDA,47253,.019,634,ATKINSON,47253,.019,635,ORR,47253,.019,636
312 DATA DECKER,47253,.019,637,HOBBS,47253,.019,638,PRESTON,47253,.019,639
313 DATA TANNER,47253,.019,640,KNOX,47253,.019,641,PACHECO,47253,.019,642
314 DATA STEPHENSON,44766,.018,643,GLASS,44766,.018,644,ROJAS,44766,.018,645
315 DATA SERRANO,44766,.018,646,MARKS,44766,.018,647,HICKMAN,44766,.018,648
316 DATA ENGLISH,44766,.018,649,SWEENEY,44766,.018,650,STRONG,44766,.018,651
317 DATA PRINCE,44766,.018,652,MCCLURE,44766,.018,653,CONWAY,44766,.018,654
318 DATA WALTER,44766,.018,655,ROTH,44766,.018,656,MAYNARD,44766,.018,657
319 DATA FARRELL,44766,.018,658,LOWERY,44766,.018,659,HURST,44766,.018,660
320 DATA NIXON,44766,.018,661,WEISS,44766,.018,662,TRUJILLO,44766,.018,663
321 DATA ELLISON,44766,.018,664,SLOAN,44766,.018,665,JUAREZ,44766,.018,666
322 DATA WINTERS,44766,.018,667,MCLEAN,44766,.018,668,RANDOLPH,44766,.018,669
323 DATA LEON,44766,.018,670,BOYER,44766,.018,671,VILLARREAL,44766,.018,672
324 DATA MCCALL,44766,.018,673,GENTRY,44766,.018,674,CARRILLO,42279,.017,675
325 DATA KENT,42279,.017,676,AYERS,42279,.017,677,LARA,42279,.017,678
326 DATA SHANNON,42279,.017,679,SEXTON,42279,.017,680,PACE,42279,.017,681
327 DATA HULL,42279,.017,682,LEBLANC,42279,.017,683,BROWNING,42279,.017,684
328 DATA VELASQUEZ,42279,.017,685,LEACH,42279,.017,686,CHANG,42279,.017,687
329 DATA HOUSE,42279,.017,688,SELLERS,42279,.017,689,HERRING,42279,.017,690
330 DATA NOBLE,42279,.017,691,FOLEY,42279,.017,692,BARTLETT,42279,.017,693
331 DATA MERCADO,42279,.017,694,LANDRY,42279,.017,695,DURHAM,42279,.017,696
332 DATA WALLS,42279,.017,697,BARR,42279,.017,698,MCKEE,42279,.017,699
333 DATA BAUER,42279,.017,700,RIVERS,42279,.017,701,EVERETT,42279,.017,702
334 DATA BRADSHAW,42279,.017,703,PUGH,42279,.017,704,VELEZ,42279,.017,705
335 DATA RUSH,42279,.017,706,ESTES,42279,.017,707,DODSON,42279,.017,708
336 DATA MORSE,42279,.017,709,SHEPPARD,42279,.017,710,WEEKS,42279,.017,711
337 DATA CAMACHO,42279,.017,712,BEAN,42279,.017,713,BARRON,42279,.017,714
338 DATA LIVINGSTON,42279,.017,715,MIDDLETON,39792,.016,716,SPEARS,39792,.016,717
339 DATA BRANCH,39792,.016,718,BLEVINS,39792,.016,719,CHEN,39792,.016,720
340 DATA KERR,39792,.016,721,MCCONNELL,39792,.016,722,HATFIELD,39792,.016,723
341 DATA HARDING,39792,.016,724,ASHLEY,39792,.016,725,SOLIS,39792,.016,726
342 DATA HERMAN,39792,.016,727,FROST,39792,.016,728,GILES,39792,.016,729
343 DATA BLACKBURN,39792,.016,730,WILLIAM,39792,.016,731,PENNINGTON,39792,.016,732
344 DATA WOODWARD,39792,.016,733,FINLEY,39792,.016,734,MCINTOSH,39792,.016,735
345 DATA KOCH,39792,.016,736,BEST,39792,.016,737,SOLOMON,39792,.016,738
346 DATA MCCULLOUGH,39792,.016,739,DUDLEY,39792,.016,740,NOLAN,39792,.016,741
347 DATA BLANCHARD,39792,.016,742,RIVAS,39792,.016,743,BRENNAN,39792,.016,744
348 DATA MEJIA,39792,.016,745,KANE,39792,.016,746,BENTON,39792,.016,747
349 DATA JOYCE,39792,.016,748,BUCKLEY,39792,.016,749,HALEY,39792,.016,750
350 DATA VALENTINE,39792,.016,751,MADDOX,39792,.016,752,RUSSO,39792,.016,753
351 DATA MCKNIGHT,39792,.016,754,BUCK,39792,.016,755,MOON,39792,.016,756
352 DATA MCMILLAN,39792,.016,757,CROSBY,39792,.016,758,BERG,39792,.016,759
353 DATA DOTSON,39792,.016,760,MAYS,39792,.016,761,ROACH,39792,.016,762
354 DATA CHURCH,39792,.016,763,CHAN,39792,.016,764,RICHMOND,39792,.016,765
355 DATA MEADOWS,39792,.016,766,FAULKNER,39792,.016,767,ONEILL,39792,.016,768
356 DATA KNAPP,39792,.016,769,KLINE,37305,.015,770,BARRY,37305,.015,771
357 DATA OCHOA,37305,.015,772,JACOBSON,37305,.015,773,GAY,37305,.015,774
358 DATA AVERY,37305,.015,775,HENDRICKS,37305,.015,776,HORNE,37305,.015,777
359 DATA SHEPARD,37305,.015,778,HEBERT,37305,.015,779,CHERRY,37305,.015,780
360 DATA CARDENAS,37305,.015,781,MCINTYRE,37305,.015,782,WHITNEY,37305,.015,783
361 DATA WALLER,37305,.015,784,HOLMAN,37305,.015,785,DONALDSON,37305,.015,786
362 DATA CANTU,37305,.015,787,TERRELL,37305,.015,788,MORIN,37305,.015,789
363 DATA GILLESPIE,37305,.015,790,FUENTES,37305,.015,791,TILLMAN,37305,.015,792
364 DATA SANFORD,37305,.015,793,BENTLEY,37305,.015,794,PECK,37305,.015,795
365 DATA KEY,37305,.015,796,SALAS,37305,.015,797,ROLLINS,37305,.015,798
366 DATA GAMBLE,37305,.015,799,DICKSON,37305,.015,800,BATTLE,37305,.015,801
367 DATA SANTANA,37305,.015,802,CABRERA,37305,.015,803,CERVANTES,37305,.015,804
368 DATA HOWE,37305,.015,805,HINTON,37305,.015,806,HURLEY,37305,.015,807
369 DATA SPENCE,37305,.015,808,ZAMORA,37305,.015,809,YANG,37305,.015,810
370 DATA MCNEIL,37305,.015,811,SUAREZ,37305,.015,812,CASE,37305,.015,813
371 DATA PETTY,37305,.015,814,GOULD,37305,.015,815,MCFARLAND,37305,.015,816
372 DATA SAMPSON,37305,.015,817,CARVER,37305,.015,818,BRAY,37305,.015,819
373 DATA ROSARIO,37305,.015,820,MACDONALD,37305,.015,821,STOUT,37305,.015,822
374 DATA HESTER,37305,.015,823,MELENDEZ,37305,.015,824,DILLON,37305,.015,825
375 DATA FARLEY,37305,.015,826,HOPPER,37305,.015,827,GALLOWAY,37305,.015,828
376 DATA POTTS,37305,.015,829,BERNARD,37305,.015,830,JOYNER,34818,.014,831
377 DATA STEIN,34818,.014,832,AGUIRRE,34818,.014,833,OSBORN,34818,.014,834
378 DATA MERCER,34818,.014,835,BENDER,34818,.014,836,FRANCO,34818,.014,837
379 DATA ROWLAND,34818,.014,838,SYKES,34818,.014,839,BENJAMIN,34818,.014,840
380 DATA TRAVIS,34818,.014,841,PICKETT,34818,.014,842,CRANE,34818,.014,843
381 DATA SEARS,34818,.014,844,MAYO,34818,.014,845,DUNLAP,34818,.014,846
382 DATA HAYDEN,34818,.014,847,WILDER,34818,.014,848,MCKAY,34818,.014,849
383 DATA COFFEY,34818,.014,850,MCCARTY,34818,.014,851,EWING,34818,.014,852
384 DATA COOLEY,34818,.014,853,VAUGHAN,34818,.014,854,BONNER,34818,.014,855
385 DATA COTTON,34818,.014,856,HOLDER,34818,.014,857,STARK,34818,.014,858
386 DATA FERRELL,34818,.014,859,CANTRELL,34818,.014,860,FULTON,34818,.014,861
387 DATA LYNN,34818,.014,862,LOTT,34818,.014,863,CALDERON,34818,.014,864
388 DATA ROSA,34818,.014,865,POLLARD,34818,.014,866,HOOPER,34818,.014,867
389 DATA BURCH,34818,.014,868,MULLEN,34818,.014,869,FRY,34818,.014,870
390 DATA RIDDLE,34818,.014,871,LEVY,34818,.014,872,DAVID,34818,.014,873
391 DATA DUKE,34818,.014,874,ODONNELL,34818,.014,875,GUY,34818,.014,876
392 DATA MICHAEL,34818,.014,877,BRITT,34818,.014,878,FREDERICK,34818,.014,879
393 DATA DAUGHERTY,34818,.014,880,BERGER,34818,.014,881,DILLARD,34818,.014,882
394 DATA ALSTON,34818,.014,883,JARVIS,34818,.014,884,FRYE,34818,.014,885
395 DATA RIGGS,34818,.014,886,CHANEY,34818,.014,887,ODOM,32331,.013,888
396 DATA DUFFY,32331,.013,889,FITZPATRICK,32331,.013,890,VALENZUELA,32331,.013,891


1000 DATA "",0,0,0 :REM END OF DATA MARKER
 

 

Link to comment
Share on other sites

IIRC Atari BASIC doesn't have string arrays, so you needed to implement them 'by hand' by using an index into a single very long string.

 

e.g. instead of DIM A$(10) to dimension an array of e.g. 10 x 256 character strings, you would DIM A$(2560) and reference the array as substrings:

 

A$(0) (MS BASIC) being then sort of equivalent to A$(1,256) (ATARI BASIC)

A$(X) (MS BASIC) being sort of equivalent to A$(X*256+1,(X+1)*256)

 

You would also need to dimension a separate numeric array e.g. DIM A(10) to hold the lengths of the substrings if that were important:

 

Assuming that the maximum length required for a substring is MAXLEN and the required size of the array is SIZE:

 

after

 

DIM A$(SIZE*MAXLEN)

DIM A(SIZE)

 

A$(X)  will then be given by A$(X*MAXLEN+1,X*MAXLEN+A(X))

 

 

ATARI BASIC suffered from lack of an INSTR function, which required either a very slow BASIC search routine or a USR function.

 

LEFT$(A$,X) is given by A$(1,X)

MID$ (A$,Y,X) is given by A$(Y,Y+X-1)

RIGHT$ (A$,X) is given by A$(LEN(A$)-X+1,LEN(A$))

 

WRT writing adventure games in ATARI BASIC , I ported the first ever published source for a BASIC adventure game, 'Dog Star Adventure', from TRS-80 BASIC (which had string arrays) to ATARI BASIC back in 1982, when the source was published in Computer & Video Games magazine. So yes, it's definitely possible!

 

Edited by drpeter
  • Like 3
  • Thanks 1
Link to comment
Share on other sites

 

31 minutes ago, drpeter said:

IIRC Atari BASIC doesn't have string arrays, so you needed to implement them 'by hand' by using an index into a single very long string.

 

e.g. instead of DIM A$(10) to dimension an array of e.g. 10 x 256 character strings, you would DIM A$(2560) and reference the array as substrings:


A$(0) (MS BASIC) being then sort of equivalent to A$(1,256) (ATARI BASIC)

A$(X) (MS BASIC) being sort of equivalent to A$(X*256+1,(X+1)*256)

 

You would also need to dimension a separate numeric array e.g. DIM A(10) to hold the lengths of the substrings if that were important:

 

Assuming that the maximum length required for a substring is MAXLEN and the required size of the array is SIZE:

 

after

 

DIM A$(SIZE*MAXLEN)

DIM A(SIZE)

 

A$(X)  will then be given by A$(X*MAXLEN+1,X*MAXLEN+A(X))

 

 

ATARI BASIC suffered from lack of an INSTR function, which required either a very slow BASIC search routine or a USR function.

 

LEFT$(A$,X) is given by A$(1,X)

MID$ (A$,Y,X) is given by A$(Y,Y+X-1)

RIGHT$ (A$,X) is given by A$(LEN(A$)-X+1,LEN(A$))

 

WRT writing adventure games in ATARI BASIC , I ported the first ever published source for a BASIC adventure game, 'Dog Star Adventure', from TRS-80 BASIC (which had string arrays) to ATARI BASIC back in 1982, when the source was published in Computer & Video Games magazine. So yes, it's definitely possible!

 

After looking at your code comments, you'd probably want to keep arrays with string locations, and length of the strings to pack the data in as small of space as possible.   It's not as easy as indexed arrays, but doable.

Something like this (logically) would be needed to extract the strings, not claiming it's optimal.
It's worse than an array of strings but not a logical nightmare by any means... though I might lie down till the headache passes.  :P  

Spoiler

'ARRAY$ contains all the name strings
'INDEX is the numeric index we sort rather than moving the strings within ARRAY$
'PNTR contains pointers (index within ARRAY$) to the start of the strings
'LENGTH contains the length of each string.  It would be faster to store the last location, but this might be easier to follow
S1=INDEX(X)               'index for first string
S2=INDEX(X+GAP)       'index for second string
FIRST$=ARRAY$(PNTR(S1), PNTR(S1)+LENGTH(S1))   'get first string
SECOND$=ARRAY$(PNTR(S2), PNTR(S2)+LENGTH(S2))   'get second string
IF FIRST$>SECOND$ THEN TEMP=INDEX(X):INDEX(X)=INDEX(X+GAP):INDEX(X+GAP)=TEMP   'compare strings and swap INDEX if needed

So this sort:
18 P=1:F=1.3:FORG=1TO0STEP0:P=P*F:G=INT(N/P):NW=N-G:PRINTG;
19 R=0:FORI=1TONW:IFA$(B(I))>A$(B(I+G))THENT=B(I):B(I)=B(I+G):B(I+G)=T
20 NEXT:NEXT:RETURN

Requires this change, or close to it:
19 R=0:FORI=1TONW:S1=INDEX(B(I)):S2=(INDEX(B(I+G)):FIRST$=ARRAY$(PNTR(S1), PNTR(S1)+LENGTH(S1)):SECOND$=ARRAY$(PNTR(S2), PNTR(S2)+LENGTH(S2)):IF FIRST$>SECOND$ THEN T=B(I):B(I)=B(I+G):B(I+G)=T


Atari BASIC isn't the only one without INSTR$.  I have to add it to the MC-10.

The adventure game comment was about Fast BASIC, which is different than Atari BASIC.

It's a question of whether or not it can load the data even then, so it would be program specific.

  • Like 1
Link to comment
Share on other sites

Yes, your scheme works well to pack string constants into less memory, which works nicely for the sort function you give as an example.

 

I was thinking of the more general programming case where members of the string array are potentially string variables (of variable length up to a fixed limit) rather than string constants. Keeping string variable array data efficiently packed within BASIC code probably isn't a viable proposition.

 

Taking memory efficiency for strings one step further, some implementations in the days of very-low-memory systems implemented two types of string- constants, which were compressed and held in immutable memory, and string variables which were held as character arrays in mutable memory.  Infocom's Z-machine implementation was one such.

Edited by drpeter
Link to comment
Share on other sites

1 hour ago, drpeter said:

Yes, your scheme works well to pack string constants into less memory, which works nicely for the sort function you give as an example.

 

I was thinking of the more general programming case where members of the string array are potentially string variables (of variable length up to a fixed limit) rather than string constants. Keeping string variable array data efficiently packed within BASIC code probably isn't a viable proposition.

 

Taking memory efficiency for strings one step further, some implementations in the days of very-low-memory systems implemented two types of string- constants, which were compressed and held in immutable memory, and string variables which were held as character arrays in mutable memory.  Infocom's Z-machine implementation was one such.

The drawback to the packed strings I used is clearly speed, and as you indicate, it's for data that doesn't change.
You could mix the two string array approaches in the same program for different uses.

While my approach works, I really wonder about the speed hit on the index sort.  It requires extracting the strings from the data, and then comparing them rather than comparing strings in place.  The faster clock speed of the Atari should help a lot vs 1MHz machines but that's a lot of string copies.
I think the 891 names I'm using (the most that will fit in MC-10 memory) requires 26 passes through the data.
Algorithm choice might also be critical.  Comb sort is relatively easy to implement, works well in BASIC, and it's one of the faster sorts, but if another sort required fewer comparisons, it might make a bid difference in speed due to the string copies.   A bubble sort would take all day. 
A machine language subroutine that compares strings in place would probably make the most difference.

Link to comment
Share on other sites

Although interestingly, benchmarking extracting 2 strings into e.g. B$ & C$ for comparison and comparing them in situ makes no significant difference, i.e.

 

IF A$(1,10) = A$(11,20) THEN...

 

performs the same as

 

B$=A$(1,10):C$=A$(11,20):IF B$=C$ THEN....

 

perhaps ATARI BASIC makes temporary copies of substrings before performing a comparison...

 

 

Link to comment
Share on other sites

PS Infocom's Z-machine specification not only packed string constants end-to-end, it also applied a compression algorithm to the text, reducing memory requirements by a further ~33% but naturally at the expense of speed due to the need to decompress the text when referenced. In fact it did the same for all string literals in the source, e.g. the text in PRINT "INFOCOM Z-MACHINE"

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...