Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C/C++

The Power in Powerbasic


JUL90: THE POWER IN POWERBASIC

Bruce develops and sells software for TRS-80 and MS-DOS/PC-DOS computers. He can be reached at T.N.T. Software Inc., 34069 Hainesville Road, Round Lake, IL 60073.


Earlier this year, Borland granted to Bob Zale, creator of Turbo Basic, rights to sell future versions of his compiler, which is now being marketed by Spectra Publishing as PowerBasic (PB). PowerBasic's designer has paid primary attention to the needs of the programmer while providing a Basic that is upwardly compatible with Turbo Basic 1.0 and Microsoft's GWBasic.

There are compromises in some areas, but there are very few when it comes to making programming easier and more productive. The result is a worthwhile and unusual version of Basic -- but by no means non-standard.

Compromise of a Sort

Regardless of language, most programmers hate reinventing and rewriting the known. With languages such as C and Pascal, quite a lot of money goes into programmer's toolkits. Still, many common routines fall through the cracks: They're too short and too easy to be worth putting in a toolkit. Worse, some parts of the language itself make the programmer do more work -- with no offsetting gain in clarity.

Consider a simple sort routine. If you were sorting many items, you'd dig out a routine from your favorite toolkit. Alas, the routine might be too general -- requiring that you specify a sort order, a comparison function, data types, and so on. Modifying to sort a half dozen strings might be more trouble than it's worth. So you rewrite a bubble sort for the thousandth time. Sure, it's only a few lines of code, but it can be irritating (especially if you make a mistake in something that elementary).

Or suppose you need a large text array of variable-length strings. I've read quite a few articles about managing such things in C and Pascal, and I've reinvented many of the algorithms in Knuth's books for managing garbage collection. Lately, dynamic string libraries have begun to appear. I suppose they're useful, but I think the need for those libraries begs the question, "Why isn't the requisite functionality built into the language or the standard libraries already?"

QuickBasic and Microsoft's excellent Basic 7.0 still don't permit dynamic strings of more than 64K at one time. Basic 7.0 dodges the question somewhat by allowing the user to have several arrays of as much as 64K at one time. Still, no single array may have more than 64K of dynamic strings.

Fixed-length strings are standard for C and Pascal. There's no question that fixed-length strings are quite useful and even preferable to dynamic strings in many applications. It was an improvement when such strings were added to Basic. However, it's less useful if the length must be specified at compile-time rather than at run time. There are far too many instances (file utilities, sort programs, and so on) where the string length simply cannot be known in advance.

PB doesn't pretend to be an entirely new language, nor does it claim to solve all problems. It's not so much a paradigm shift as an exercise in pragmatism. To the question, "What should Basic be?" Bob Zale has answered: "Whatever Basic programmers want." He didn't implement everything I would like to see, but then, that may be impossible.

Yes, PB includes a sort. The command will sort all or parts of arrays of all data types (the default is plain ASCII), using any collating order you specify, either directly or using a tag array, in ascending or descending order. The sorted arrays may have many dimensions. The options are not mandatory parts of the command, so you can sort a whole array in ascending ASCII order simply as: ARRAY SORT A$( )

That's useful enough, but there's more. You can also scan all or part of an array for the first element that matches a relation you specify (<, >, =, etc.), based (for string arrays) on any collating order you specify -- including case-insensitive scans.

You can also insert or delete an array element with a single command. No more loops or swaps are needed. It seems an enormous understatement to say that all this is just "useful" -- it's been needed for years!

Language Enhancements

These and other enhancements are discussed in the two manuals (User's Manual and Reference Guide) supplied with PB. The documentation is thorough (more than 700 pages), clear, and well indexed and organized, and seems to be free from any obvious typos. I found no errors in the manuals while doing the review, but I'd suggest that later versions of the manuals devote an appendix to the differences between PB and QB. There are appendices detailing the differences between PB and GWBasic, and between Turbo Basic and PB.

Among other things, PB has new data types: Floating-point BCD, fixed-point BCD, 8-byte integer, and 10-byte extended precision floating-point (native coprocessor format numbers). 8-byte integers can have as many as 18 digits, so PRINT USING was revamped.

The expanded string space carries several penalties. Because strings can be spread over more memory, there's more overhead involved. That means string operations tend to be slower in PB than in Microsoft products. But if you need the space, the small penalty is well worth it.

In addition, the FRE(" ") function returns the amount of space remaining in the current string allocation block. Once you've been running the program for a while, there's no easy way for you to tell how much total memory is left for strings, or how much you've used so far. You must calculate the amount of available memory when the program first starts and use that number as the baseline for future calculations.

Those are problems to be noted, but they aren't serious, especially for those of us who find the unlimited string space to be a big advantage.

As with Turbo Basic, PB permits the programmer to specify where segment boundaries lie. From that, you can avoid the problems created by programs too large to fit into a single-user code segment. However, the PB editor and compiler limit source code to 64K bytes. This is less of a problem than before because PB can link with OBJ files and units (resembling Turbo Pascal's units). It can, however, be somewhat of a bother.

Options

Compilation options allow you to generate code for 80286 and 80386 processors; use/emulate a math coprocessor (or ignore the coprocessor and go for maximum speed with a procedural math library); turn on or off various checks; and reduce code size by eliminating support for unnecessary library modules. What you get seems very similar to the options provided in Microsoft's Basic 7.0, though PB's EXE files are usually larger than those of Basic 7.0.

PB permits linking OBJ modules in what seems to me a more natural way than with the Microsoft compilers: PB asks that you include the names of the OBJ modules within the source code of your program. That decreases the length of the command line and the possibility of errors. The compilation options can also be included as meta-commands in the source code. Those enhancements make it much easier to compile PB programs.

There is a drawback, though. PB cannot link with libraries, as QuickBasic can. This can be a big problem if you need many OBJ files.

Benchmarks

While doing this review, I churned out my usual quantitative comparisons. BENCHOLD.BAS (Listing One, page 116) benchmarks features of the language that are common to QuickBasic 3.0 and earlier, while BENCHNEW.BAS (Listing Two , page 119) tests the newer features of the language. The results are shown in Tables 1 and Table 2. Those numbers are not completely irrelevant, but they are of less worth than usual: Power Basic breaks new ground in unexpected ways, and the overall utility of this compiler cannot be judged by noting the relative time it takes to perform a string concatenation or a double precision add.

Table 1: Size of EXEs generated from Listings One and Two

  COMPILER      PROGRAM   SOURCE SIZE  EXE SIZE
  ---------------------------------------------

  POWER BASIC   BENCHNEW      3400     39296
     QB 4.5     BENCHNEW      3022     34276*
    BASIC 7.0   BENCHNEW      3418     24848
  POWER BASIC   BENCHOLD      8721     46384
     QB 4.5     BENCHOLD      7746     37722*
    BASIC 7.0   BENCHOLD      8720     32684

*Supports fewer tests; size is not strictly comparable, but is provided for reference.


Table 2: Timings were generated using a Tandy 4000 (16-MHz 80386) with an MDA video adapter card, a Casper amber monochrome monitor, and no math coprocessor. For each compiler, all possible stub libraries were used, all error checks were removed, and all speed optimizations employed.

  Time, in seconds, per 1,000,000 operations

                         QB 3.0     QB 4.0    BASIC 6    BASIC 7         PB
---------------------------------------------------------------------------
  Integers:
  Empty loop               1.21       1.21       1.21       1.20       2.09
  assignment:              1.15       1.13       1.13       1.10       1.02
  add:                      .30        .49        .50        .27        .47
  subtract:                 .33        .46        .49        .16        .77
  multiply:                1.92       2.45       2.27       2.25       2.77
  divide:                  3.36       3.43       3.44       3.90       5.41
  comparison:              2.58       3.20       2.58       2.53       2.91
  Conditional
   assignment:             4.51       4.77       4.67       2.37       2.31
  Conditional
   assignment*:            4.72       4.88       4.34       1.70       2.47

  Long integers:
  Empty loop              -----      14.45      14.28      12.59      10.49
  assignment:             -----       1.62       1.71       1.53       1.67
  add:                    -----      15.47      15.26      13.23      11.73
  subtract:               -----      15.41      15.21      13.57      12.22
  multiply:               -----      26.11      25.82      24.34      25.35
  divide:                 -----      33.76      33.66      31.70      25.68
  comparison:             -----      10.81      10.98      10.48       8.57

  Single-precision:
  assignment:              5.71     201.23      20.40       2.20       1.98
  add:                    23.97     128.83      24.41      42.45      24.66
  subtract:               24.80     129.36      25.87      43.72      26.34
  multiply:               34.30     -16.19      35.50      52.54      36.02
  divide:                 35.98       7.48      47.68      64.80      47.02
  Error, 100K
   mult/div:          -1.06E-05  -1.19E-07  -1.19E-07  -1.19E-07   -1.96E-5
  exponential:           766.80    3061.84    1296.36    1309.90    3373.80
  comparison:             19.72     402.00      42.68      42.58       4.55

  Double-precision:
  assignment:              6.26     211.41      23.06       3.49      49.10
  add:                    45.75     143.28      49.99      68.80      69.48
  subtract:               47.19     143.87      51.52      70.39      69.43
  multiply:               83.13     199.49      91.66     109.60      86.13
  divide:                 84.22     226.45     121.82     142.57     130.08
  Error, 100K
   mult/div:          -4.82E-13  -2.22E-16   2.22E-16   2.22E-16  -4.22E-15
  exponential:          2491.80    6377.23    3046.33    3240.62    3326.56
  comparison:             20.37     412.89      46.30      46.37     100.68

  Strings:
  assignment:             77.09      78.50      79.04      77.72      72.56
  MID$ operation:         20.78      24.61      25.20      24.11      81.93
  concatenation:        1657.81     954.84    1661.15    1662.48     875.16

  Print 1K 70-byte
   strings**:             26.47      10.00      10.05       9.55       9.61
  Fixed string
   assignment:            -----      52.38      51.92      51.68     101.86
  Fixed string MID$
   operation:             -----      23.44      24.12      23.74     147.13
  Fixed string
   concatenation:         -----      24.61      24.78      21.01     170.85
  Pr 1K 70-b static
   strings**:             -----      10.16      10.10       9.65       9.60


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.