Categories
Delphi Projects News

The First Computer Program – In Delphi

Lady Ada Lovelace using a modern day laptop
Charles Babbage

Lady Ada Lovelace is generally considered the world’s first computer programmer. Born Augusta Ada Byron, in 1815, she was the daughter of Lord Byron, the English romantic poet. She took an interest in mathematics and her talents lead her to work with Charles Babbage, “the father of computers,” whom she met in 1833.

Babbage started work on his Difference Engine, as a means to automatically calculate and print the values of polynomial functions. While he never saw his Difference Engine completed, two were finished in modern times based on his original designs. One of which is in the Computer History Museum in Silicon Valley, where I saw it in operation.

In 1837 Babbage first described his Analytical Engine, as a general-purpose computer. In 1843, Lovelace translated a French paper that Italian mathematician Luigi Menabrea wrote about Charles Babbage’s Analytical Engine. While translating it she added thousands of words of her own notes to the paper. As an example she wrote of one such sequence—how to calculate Bernoulli numbers. This is regarded by computer historians as the first computer program.

Lovelace's diagram from "note G", the first published computer algorithm https://commons.wikimedia.org/wiki/File:Diagram_for_the_computation_of_Bernoulli_numbers.jpg

Two Bit History has a great write up on Lovelace’s program: What Did Ada Lovelace’s Program Actually Do? which includes a C translation and a solution for the bug it included.

Naturally I wanted to see what her code would look like in Delphi’s Object Pascal.

program LovelaceBernoulli;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

function B7: extended;
(*
 * Calculates what Lady Ada Lovelace labeled "B7", 
 * which today we would call the 8th Bernoulli number.
 * Based on  https://gist.github.com/sinclairtarget/ad18ac65d277e453da5f479d6ccfc20e
 * More info https://twobithistory.org/2018/08/18/ada-lovelace-note-g.html
 * Bernoulli Numbers: https://en.wikipedia.org/wiki/Bernoulli_number
 *)
begin
    // ------------------------------------------------------------------------
    // Data
    // ------------------------------------------------------------------------
    var v1: Single := 1; // 1
    var v2: Single := 2; // 2
    var v3: Single := 4; // n

    // ------------------------------------------------------------------------
    // Working Variables
    // ------------------------------------------------------------------------
    var v4: Single := 0;
    var v5: Single := 0;
    var v6: Single := 0;                        // Factors in the numerator
    var v7: Single := 0;                        // Factors in the denominator
    var v8: Single := 0;
    var v10: Single := 0;                       // Terms remaining count, basically
    var v11: Single := 0;                       // Accumulates v6 / v7
    var v12: Single := 0;                       // Stores most recent calculated term
    var v13: Single := 0;                       // Accumulates the whole result

    // ------------------------------------------------------------------------
    // Result Variables
    // ------------------------------------------------------------------------
    var v21: Single := 1.0 / 6.0;             // B1
    var v22: Single := -1.0 / 30.0;           // B3
    var v23: Single := 1.0 / 42.0;            // B5
    var v24: Single := 0;                     // B7, not yet calculated

    // ------------------------------------------------------------------------
    // Calculation
    // ------------------------------------------------------------------------
    // ------- A0 -------
    (* 01 *) v6 := v2 * v3;                // 2n
    (* 02 *) v4 := v6 - v1;                // 2n - 1
    (* 03 *) v5 := v6 + v1;                // 2n + 1

    // In Lovelace's diagram, the below appears as v5 / v4, which is incorrect.
    (* 04 *) v11 := v4 / v5;               // (2n - 1) / (2n + 1)

    (* 05 *) v11 := v11 / v2;              // (1 / 2) * ((2n - 1) / (2n + 1))
    (* 06 *) v13 := v13 - v11;             // -(1 / 2) * ((2n - 1) / (2n + 1))
    (* 07 *) v10 := v3 - v1;               // (n - 1), set counter?

    // A0 = -(1 / 2) * ((2n - 1) / (2n + 1))

    // ------- B1A1 -------
    (* 08 *) v7 := v2 + v7;                // 2 + 0, basically a MOV instruction
    (* 09 *) v11 := v6 / v7;               // 2n / 2
    (* 10 *) v12 := v21 * v11;             // B1 * (2n / 2)

    // A1 = (2n / 2)
    // B1A1 = B1 * (2n / 2)

    // ------- A0 + B1A1 -------
    (* 11 *) v13 := v12 + v13;            // A0 + B1A1
    (* 12 *) v10 := v10 - v1;             // (n - 2)

    // On the first loop this calculates B3A3 and adds it on to v13.
    // On the second loop this calculates B5A5 and adds it on.
    while (v10 > 0) do
    begin
        // ------- B3A3, B5A5 -------
        while (v6 > 2 * v3 - (2 * (v3 - v10) - 2)) do
        begin                                // First Loop:
            (* 13 *) v6 := v6 - v1;           // 2n - 1
            (* 14 *) v7 := v1 + v7;           // 2 + 1
            (* 15 *) v8 := v6 / v7;           // (2n - 1) / 3
            (* 16 *) v11 := v8 * v11;         // (2n / 2) * ((2n - 1) / 3)

                                             // Second Loop:
            // 17    v6 := v6 - v1;              2n - 2
            // 18    v7 := v1 + v7;              3 + 1
            // 19    v8 := v6 / v7;              (2n - 2) / 4
            // 20    v11 := v8 * v11;            (2n / 2) * ((2n - 1) / 3) * ((2n - 2) / 4)
        end;

        // A better way to do this might be to use an array for all of the
        // "Working Variables" and then index into it based on some calculated
        // index. Lovelace might have intended v14-v20 to be used on the
        // second iteration of this loop.
        //
        // Lovelace's program only has the version of the below line using v22
        // in the multiplication.
        if (v10 = 2) then
        (* 21 *) v12 := v22 * v11             // B3 * A3
        else
        (* 21 *) v12 := v23 * v11;            // B5 * A5

        // B3A3 = B3 * (2n / 2) * ((2n - 1) / 3) * ((2n - 2) / 4)

        // ------- A0 + B1A1 + B3A3, A0 + B1A1 + B3A3 + B5A5 -------
        (* 22 *) v13 := v12 + v13;            // A0 + B1A1 + B3A3 (+ B5A5)
        (* 23 *) v10 := v10 - v1;             // (n - 3), (n - 4)
    end;

    (* 24 *) v24 := v13 + v24; // Store the final result in v24
    (* 25 *) v3 := v1 + v3;    // Move on to the next Bernoulli number!

    // This outputs a positive number, but really the answer should be
    // negative. There is some hand-waving in Lovelace's notes about the
    // Analytical Engine sorting out the proper sign.
    Result := v24;
end;

begin
  try
    Writeln('Calculates what Ada Lovelace labeled "B7", which today we would call the 8th Bernoulli number.');
    Writeln('--------------');
    Writeln('This outputs a positive number, but really the answer should be negative.');
    Writeln('There is some hand-waving in Lovelace''s notes about the Analytical Engine sorting out the proper sign.');
    Writeln('==============');
    Writeln(Format('A0 + B1A1 + B3A3 + B5A5: %.4f',[B7]));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Writeln('--------------');
  Writeln('Press [enter] to close');
  readln;
end.

While this is one way to calculate the 8th Bernoulli number, what would a modern implementation look like? Using Rudy’s Big Numbers library I created a sample application to calculate any Bernoulli number.

function Bernoulli(n: Uint64): BigRational;
begin
  var a: TArray<BigRational>;
  SetLength(a, n + 1);
  for var m := 0 to High(a) do
  begin
    a[m] := BigRational.Create(1, m + 1);
    for var j := m downto 1 do
    begin
      a[j - 1] := (a[j - 1] - a[j]) * j;
    end;
  end;
  Result := a[0];
end;

You can install the BigNumbers library via GetIt and this sample application is included.

Categories
Brain Computer Interface Delphi Projects gadgets

Thought Controlled Quadcopter

Last night I “controlled” my Parrot AR.Drone Quadcopter with my thoughts through my Emotiv EPOC Brain Computer Interface via an app written in Delphi XE5. I qualify “controlled” in that my flight pattern was a little irregular and short before I crashed it. It was a “look mom, no hands” moment though as the drone was clearly responding to my thoughts for the few seconds before it crashed. I’ve got a lot of work to do in improving the process, so I will be posting code and videos soon. If you want to get a start on it though, it is based on my work from the Devices and Gadgets webinar.

I’m presenting tomorrow at Boise Code Camp on “Is Thought the Future of Wearable Input?” and if all goes well I’ll have a brief demonstration of the tech in action. If you are in the area my presentation is at 11 AM in the Special Events Center at Boise State University.

Categories
Android Delphi Projects iOS Mobile

Learning from Digifort

You’ve probably seen Éric Fleming Bonilha videos showing off his Digifort mobile applications developed with Delphi XE5. The videos don’t mention it, but the back end server and client applications are all written in Delphi too. Just in case you haven’t see the videos, here they are again:

Earlier version, but on a lot of different devices:

Embarcadero just completed a case study with him too, which is really informative. I spoke with him down in Brazil and he said they previously developed mobile clients with both Java and Objective-C, and found Delphi let them develop their projects much faster, and they get both Android and iOS from one project. Also, and perhaps more importantly he said the performance of the Delphi client was just as good, plus they found it more flexible for building a user interface that looks great and is easy to use.

Digifort Mobile Client

Digifort may be based in Brazil, but their clients are all over the world and are a mix of government agencies and business of various sizes. Eric arranged a trip to meet me in Scotts Valley this last week. He showed me some pictures of some of the walls of monitors his clients have, all powered by Digifort. Some really impressive installations.

A big part of his trip was to pick up a his very own Google Glass to start developing a Digifort mobile app for Google Glass. In just a couple short sessions he was capturing images from the built in camera, connecting to his remote server, and streaming live video from Brazil to the glass display. The use case for security personal to view cameras while on patrol, while sharing what they see with everyone else is a great one.

David, Eric and Jim

Eric also had a chance to visit with some people from R&D and product management and share his experiences working with Delphi XE5 and FireMonkey. Here are some best practices he found for making a really smooth user interface.

  • FireMonkey handles PNG images really well. He makes a lot of use of transparent and semitransparent PNG images in TImage components. Layering, animating and zooming those images is what he uses to create some of those really great effects, like the joystick control for camera control.
  • The TFloatAnimation and other animation effects are really powerful. He uses those extensively for smooth animations.
  • He created the drawer interface using TFrames (he uses a lot of frames). The main (center screen) has a Pan Interactive Gesture on it. He looks at the gesture to see if it is horizontal (comparing the gesture start to a later gestsure event) and has traveled at least 10 pixels in that direction. Once that happens then he moves the edge of it with the current finger position from the gesture. He also tracks the speed of the movement, so if you let go then he uses another TFloatAnimation to smoothly finish the movement at the same speed.
  • When the drawer starts to open he pauses all the video and other animations. This really increases the performance of the drawer animation.
  • Anything that is not currently shown on the screen has its visibility set to false. So if the drawer is closed, then everything in the drawer is invisible (since it is in a frame he just sets the frame to invisible). This keeps it from rendering and gives what is visible all the processing power. This is a common suggested optimization with many mobile development tools.
  • It is important to think about a mobile app’s interface as a mobile app. Don’t try to squeeze a desktop app onto a mobile device. That will only frustrate you and your users.
  • In his lists of cameras he uses a TVertScrollBox and fills it with a custom component that contains TImages and TLabels. That gives him maximum flexibility for the drag to reorder (again a Pan Interactive Gesture). He did find that the TLabel has better performance than drawing the text manually inside his custom control.

There were a lot of things he shared where he spent a little extra time to get things just right, and that is what makes the difference for a really smooth user interface. When asked about the learning curve to move from Desktop VCL to FireMonkey Mobile he said there was just a little learning curve, but now he really likes FireMonkey better than VCL. There was talk about having him collaborate for a user interface webinar, which I’m sure will be very informative.

You can catch Eric’s appearance in our Devices and Gadgets webinar on the webinar replay (posting any day now). And download his sample code (along with the rest of the code from the webinar).

What are some tips and best practices you’ve found in your FireMonkey mobile development?

Categories
Android Delphi Projects Mobile News REST

Hello Google Glass from Delphi XE5

Google’s new Glass platform is a very revolutionary Android device, but the question I really wanted to know is if I could develop for it with Delphi XE5. Turns out the answer is Yes.

There are actually two different options for developing Glassware: Mirror API and GDK.

The first is the Google Mirror API, which allows you to build services, called Glassware, that interact with Google Glass. It provides this functionality over a cloud-based API and does not require running code on Glass. This is accomplished through a REST and JSON based API. Thanks to the new TRESTClient components in Delphi XE5 this should be easy enough to do.

The GDK on the other hand is the avenue where you build an actual APK that runs on the Google Glass device itself. This gives you the most access to the device, its sensors and features. Turns out this is also easy enough to do with Delphi XE5.

The actual GDK builds on top of the Android SDK. You can develop apps to run on Glass with either the Android SDK or GDK, but the GDK is necessary to take advantage of some of the Glass specific features.

If you run SysCheck on Glass (which takes some effort) you discover it has an ARMv7 PRocessor rev 3 (v71) with Android OS Version 4.0.4 and NEON support. Those meet the main requirements for Delphi XE5 development. So I created a simple Hello World app and ran it.

This first screenshot shows Glass appearing in the Project Manager as a valid target (once the required USB drivers were installed, which was tricky for glass).

HelloGlassProjectManager

Here is a screenshot of the app running on Glass

Delphi XE5 App running on Google Glass

I didn’t hide the status bar, which most Glassware does, and it does nothing other than serve the purpose of showing a Delphi XE5 app running on Google Glass. There were no special settings (other than the dark theme, which is a matter of taste) to make the app run on Glass. It just works.

And lastly a quick selfie of me and Glass, taken through glass.

JimWithGlass

I was hoping it would look more red than orange, but should have known Tangerine would be orange.

Rest assured, there will be more coverage of Delphi and Glass. We are just getting warmed up. This app was not using the GDK (which is still in Beta) but it is an actual Delphi app running on Glass. What an exciting day!

Categories
Delphi Projects REST Source Code

Delphi XE5 Mobile REST Client Demo Source

With the release of Delphi XE5 I’ve made the source of the Mobile REST Client Demo available. This is a really super simple demo of the Mobile REST Client in XE5. It is designed to show up how you can consume a JSON REST Service and adapt it into a DataSet and then bind that to the UI. If you change the data source you will probably need to change the live binding.

I’ve changed the demo from the one I used in the video to consume an OData data source. OData is a new standard backed by Microsoft for sharing data over the web. You can think of it as SQL for the web. It is a combination of other technologies, including REST, AtomPub, and JSON. Sybase supports OData on all of their databases now, as does Microsoft and others.

The change was simply a matter of pointing it to the Northwind OData endpoint provided on Odata.org. The binding is setup to show the company name in the listview. I added the ability to specify a Root Element, but that isn’t necessary for the demo.

This new technology works in both desktop and mobile, FireMonkey and VCL. It should also work in C++ Builder.

[Download the demo] (MobileRestXE5.7z 8 KB – Requires Delphi XE5 – Builds for iOS, Android or Win32)

Categories
Delphi Projects News Source Code

Android Screen View

Android Screen View UI

People have asked for a copy of the utility I wrote to view the attached Android device on the screen. It uses the built in screencap functionality of Android and the ADB (Android Debug Bridge) to grab and display a series of screenshots. It requires the Android SDK installed and does not require a rooted device.

The speed of update has to do with the screen resolution and image complexity. Simple screens (text and controls) update about twice a second. More complex screens (pictures, graphics, etc.) are slower than that.

For best results, turn on “Show Touches” under debug options.

It also supports saving a PNG to file.

Get the source: https://code.google.com/p/android-screenview/

Download the build: http://delphi.org/downloads/AndroidScreenView.7z

There are a few pending features that I just haven’t gotten to. If you’d like to contribute let me know. Thanks to Stephen Ball for all his contributions already!

Categories
Audio podCast Delphi Projects

27 – Nick Hodges – R&D Manager

Welcome to Episode 27 of the Podcast at Delphi.org for Monday the 20th of April, 2009.

This episode was recorded with Nick Hodges on Thursday, the 17th of April, 2009.  Nick discusses his new role as an R&D manager and some of the other changes going on at CodeGear.  Also discuss the upcoming release of Delphi, the DelphiLive! conference, and some of the suggestions on Delphi.UserVoice.com.

The episodes with Nick are always great ones, so I hope you enjoy it!  If there are other links I missed please add those in the comments.

Categories
Audio podCast Delphi Projects

24 – Delphi Projects

In this episode I talk with Jamie Ingilby, Steven Kamradt and  marc hoffman.  We introduce the Delphi Projects series which focuses on simple useful projects written in Delphi.  Our first project is a Twitter client written in Delphi Win32.

This episode is the start of a series of podcasts.  I thought it would be more interesting if there was something more to this podcast then just interviewing people and discussing Delphi news.  So what we have done is started a series of Delphi projects that a small group of volunteers will work on and then discuss how the project goes via the podcast.  Our first projects is a Twitter client written in Delphi.

Leave suggestions for names for the client in the comments.  Allen Bauer is already using the Delphitter name.  I am kind of leaning towards something that combines both Delphi and Twitter, but it needs to not contain the whole word “Twitter,” but you can be creative too.  I’ll set up a poll with all the suggestions so everyone can vote.  I have a name in mind already, but I am not attached to it.

If you are excited about this then please spread the word!