Close
0%
0%

Does Anyone Really Know What Time It is?

If you havent noticed, the clock in the Windows Taskbar has gone missing. Will it ever return?

Similar projects worth following
Perhaps members of the open-source community need to band together and create their own open-source Desktop Accessories. Just thinking out loud here, but maybe not. For now, the expanded Windows clock with an actual second hand is missing. So how hard can it be to write an even better one from scratch? Let's get busy!

About a year or so ago, or whenever it was, I decided to ask Microsoft Co-Pilot to help me write a C++ function that would calculate the angle bisectors of an arbitrary triangle, that is, without using conditional expressions or branches.  The response that I got was, of course, completely wrong, so I put myself to the task of actually trying to write something that works, correctly, especially since if I was writing a game engine, and if I needed to compute the angle bisectors of millions of triangles, let's say CUDA style, well we all know what happens when one thread in a group of threads running concurrently causes a pipe-line stall.  That's right - all other threads in the group will stall together.  What a MESS!  Unnecessary branches also increase the risk of Meltdown and/or Spectre-type attacks on vulnerable systems.  So how much worse can it get?  

Well, in any case - I put myself to the task of writing a solution that works, that is to say - according to my own self-imposed requirements, and for the part of actually doing that part of tessellation correctly, it isn't all that hard.

int triangle::generate_bisectors ()
{
    fpoint U1,U2,U3;
    MATH_TYPE d; 
    MATH_TYPE dx1,dx2,dx3,dy1,dy2,dy3;
    MATH_TYPE L1,L2,L3;
    MATH_TYPE c1,c2,c3,s1,s2,s3;

    // first find the sines and cosines of the line
    // segments that make up the triangle

    dx1 = current[1].x-current[0].x; dx2 = current[1].x-current[2].x;
    dx3 = current[2].x-current[0].x; dy1 = current[1].y-current[0].y;
    dy2 = current[1].y-current[2].y; dy3 = current[2].y-current[0].y;

    L1 = sqrt((dx1*dx1)+(dy1*dy1));
    L2 = sqrt((dx2*dx2)+(dy2*dy2));
    L3 = sqrt((dx3*dx3)+(dy3*dy3));

    c1 = dx1*(1.0/L1); c2 = dx2*(1.0/L2); c3 = dx3*(1.0/L3);
    s1 = dy1*(1.0/L1); s2 = dy2*(1.0/L2); s3 = dy3*(1.0/L3);

    // now generate three points that represent the
    // directional unit vectors for each line segment
    // and then  generate the compass points

    fpoint C1,C2,C3,C4,C5,C6;
    d = 1.0; // compass distance!
    U1.x = d*c1; U1.y = d*s1;
    U2.x = d*c2; U2.y = d*s2;
    U3.x = d*c3; U3.y = d*s3;

    C1 = current[0]+U1; C4 = current[0]+U3;
    C2 = current[1]-U2; C5 = current[1]-U1;
    C3 = current[2]-U3; C6 = current[2]+U2;

    // the directional unit vectors can be used to find the midpint
    // of a line that besects an isosceles triangle that forms
    // from the base of the "arrow"
    
    fpoint P0,P1,P2;
    P0 = fpoint::midpoint (C1,C4);
    P1 = fpoint::midpoint (C2,C5);
    P2 = fpoint::midpoint (C3,C6);

    fline AP1,BP2,CP3;
    AP1 = fline (current[0],P0);
    BP2 = fline (current[1],P1);
    CP3 = fline (current[2],P2);

    J = fpoint::intersect (AP1,BC);
    K = fpoint::intersect (BP2,AC);
    L = fpoint::intersect (CP3,AB);
    return 0;
}

O.K., so that is one way of doing it.  More work to be done, of course, checking the time, the time-zone, drawing the background image, drawing an hour hand, a minute hand, a second hand, etc.  Then maybe redo the whole thing so that the same code base can be used for analog aviation instruments.   Yet there is something very satisfying about knowing, going out the gate - that at least one really important detail, such as possibly having a very nice, even ornate pointer, is already done. Then again ... 

Then again, of course, this is an excellent opportunity to mention Euclid, with 100's of proofs waiting to be properly rendered, all with just the right amount of rigor, naturally!

Naturally, we are going to need to do more than have an elaborate method for drawing a nice ornate pointer; we are going to need the clock face, some numbers, and so on.  Yet, how are we going to do that?  By appealing to functions like sine and cosine?  Never!  Although the law of sines might have been known during the times of Pythagoras and Euclid, there was no way to calculate sines and cosines of arbitrary numbers until after the invention of calculus.  Yet there were other constructions that were well known, i.e., during the...

Read more »

CSignalView.h

Heaster file for the CSignalView class, which is also used in the Propeller Debug terminal application. See CSignalView.cpp for implementation.

plain - 3.10 kB - 08/19/2025 at 11:45

Download

CSignalView.cpp

If you are creating an MFC application from scratch, and you want to implement some functionality such as rendering to a compatible offscreen bitmap, clipboard, or printer support, then you will need this file or something similar to help handle most of the things that go on "under the hood" with those tasks.

plain - 9.42 kB - 08/19/2025 at 11:41

Download

euclid.cpp

This is the stuff that you are probably interested in if you are serious about doing Euclidean geometry from scratch. It is easy to imagine that this could at some point, become a library for more general use inside Processing, according to the licensing model for that project. Enjoy!

plain - 39.18 kB - 08/18/2025 at 21:02

Download

euclid.h

Header file for Euclid.cpp. You will need to adapt this according to your environment, i.e., Processing, Unreal Engine, Blender, or maybe even your very own favorite DOOM wad editor, or whatever. GNU/MIT license. Enjoy!

plain - 8.12 kB - 08/18/2025 at 21:02

Download

  • 1 × Suitable Hardware, i.e. if GPS is desired. Likewise a PC or Tablet with C++

  • Time For Some News

    glgorman09/28/2025 at 18:22 0 comments

    Alright, I will explain this later.  In the meantime, images seem to be broken again.  So I will have to try to explain what I am thinking about.  I saw an article online about how someone asked GPT to demonstrate how to construct a rectangle with an area equal to twice the area of another rectangle, while presumably preserving the aspect ratio. Thus, both rectangles have the same aspect ratio.  So maybe it is time to do some more work on my Euclid.cpp source files, on the one hand, while giving some thought as to how to create some kind of proof-generating AI, on the other.

    So, to construct such a rectangle, one would need to increase the height and width of the given rectangle by multiplying those dimensions by a factor of the square root of two.  Using compass and straight edge methods alone, this could be done, that is, if provided with an already constructed rectangle, by simply constructing two squares, one with sides equal to the width of the given rectangle, and the other with sides equal to the height of the given rectangle.  Then one can make use of the fact that the length of an internal diagonal of any square is just the length of one of the sides of a square multiplied by the square root of two.

    The construction should be performed in such a fashion as to allow for the creation of the second rectangle by making use of a minimum number of steps, i.e., making the most direct application of the compass and straight edge in generating and making use of the required dimensions.  Thus, a rotated and enlarged construction of the given rectangle that overlays the given rectangle should be preferred, for reasons of rigor, that is, over a construction that transfers the dimensions to another sheet.

    Now, insofar as how one might turn this into code, so that the problem at hand, somehow, "solves itself", i.e., so that a suitable LLM-based AI might turn what I just said into code. which, herein is already available so as to be able to actually perform the construction, is another matter.

    Of course, one of the things that I want to try is to modify a calculator library that makes calls to some of its functions by using a table of function pointers, so that instead of mapping opcodes onto function calls, I want to, instead that is, map words like "bisect", "perpendicular", and so on, onto the appropriate Euclidian operations.  So here is the starting point, for how this sort of thing is typically done.

    typedef enum { add=0, sub=1, mult=2, divi=3, }; opcode1;
    typedef double (*ftable[])(const double&, const double&);
    
    class calculator
    {
    protected:
        double reg[16];
        static double (*ftab[4])(const double&, const double&);
        static double fadd(const double &, const double &);
        static double fsub(const double &, const double &);
        static double fmult(const double &, const double &);
        static double fdiv(const double &, const double &);
    
    public:
        static double exec(opcode1, const double &arg1, const double &arag2);
        static int main();
    };

    Then, in our source file, we fill in the values for our table of function pointers, as well as defining some of the functions themselves.

    ftable calculator::ftab =
    {
        &calculator::fadd,
        &calculator::fsub,
        &calculator::fmult,
        &calculator::fdiv,
    };
    
    double calculator::fadd(const double &arg1, const double &arg2)
    {
        double result;
        result = arg1+arg2;
        return result;
    }
    
    double calculator::fsub(const double &arg1, const double &arg2)
    {
        double result;
        result = arg1-arg2;
        return result;
    }
    
    double calculator::fmult(const double &arg1, const double...
    Read more »

  • Just as the previous log entry went into overtime:

    glgorman09/03/2025 at 05:07 0 comments

    So, I went ahead and decided to see how difficult it would be to convert the entire project to TypeScript, on the one hand, or else, while also considering just how difficult it might be to write a complete REACT environment from scratch.  Maybe not that hard at all.  Easy weekend project?  Maybe.  It is usually never actually that simple, but why not give it a whack?

    First, I went ahead and started working on converting my CSignalView MFC class into TypeScript, since ideally JavaScript should be deprecated and not used for new work, but as usual, your mileage may vary.

    So far, so good.  Things look even better on the WebGL side, as far as doing some of the OpenGL initialization.  That is to say, if any of this actually works.

    So, the particular tool that I used seems to have just enough know-how to give me some boilerplate WebGL code that appears to have the ability to draw a grid and even plot some "waveform" data.  So maybe if I decide to use Euclidean geometry, WebGL style, this could be adapted, while remaining faithful to the implementation details of the Euclid.cpp code.  Not surprisingly, or perhaps quite surprisingly (take your pick), when trying to convert the Euclidean stuff, the tool that I tried using pretty much fell apart.  Maybe it will work better if I ask it to convert one function at a time, which is pretty annoying. 

    As you can see, the conversion tool in question pretty much gave up on certain functions, like the pentagon construction, hexagon construction, and also the angle bisector stuff, and that is all just a bunch of straight-up function calling and simple mathematical manipulation.  Like I said, maybe it will work better if I spoon-feed it one or two functions at a time.  Yet it is kind of funny that it does so well with some really messy code like WebGL initialization, yet falls apart on the same code that Co-Pilot fell apart on a while back.

  • Two Outs. Last of the Ninth. Tying Run on Second.

    glgorman08/11/2025 at 15:08 0 comments

    Were you expecting a catchy title that hints at the whole theory of the NFL clock?  Or how about basketball time in a relativistic arena?  Rest assured, that we are not there quite yet, nor is there any plan for that sort of thing any time soon. Then again, at least I have a working clock that compiles under Visual Studio 2005 in both debug and release modes.  Even though I haven't tried adding the GPS via USB stuff to something that might actually run with just this collection of files, and maybe a little bit more, if needed, from my frame lisp library.

    Yet, things appear to simplify a great deal if I just grab the files that I need, and don't try to rely on needing to link against 14 libraries.  Still, VS 2005 is doing a pretty good job, I think, when it at least tries to get the size of the executable down to just over 400K.  Which is totally bloated by hacker standards.  Shouldn't it be possible to do something like this in something like 40K, or maybe 4K, if I were trying to run this on an Apple II or a C64?  Bloated by hacker standards, but at least it is doing something.  Very reasonable, however, by modern standards.

    At least RAM is cheap these days.  Still, it remains to be seen if it is possible to get something like this, with lots of fun libraries and other goodies added, or to be added, let's say, if it looks to be possible to compile for Web assembly, or something else even more fun, like Parallax hardware, or one of the many Arduino hacks that are possible, insofar as actually doing video generation are concerned.  I'll know more about what might be possible when I get to a minimum code set, maybe even if I try just piling all of the code into one big source file and then rewrite, most of it, if not all of it, in pure C, with Win32 API calls instead of MFC.  Then there would be no need to consider Widgets, or Qt, or whatever.

    Atari 2600, anyone? Maybe in emulation, but not anytime soon.  Still, I do like the idea of trying something like this on a Commander X16 if I ever decide to get one.  There is another platform that I haven't done anything yet either, that might be fun to putz around with - and that is, of course, the XP clone, ReactOS.

    Now that could get very interesting.  Why settle for writing your own game engine, one piece at a time, when you can have a whole OS?

    Decided to try an online code conversion tool that converts C++ to Typescript. Does it work?  I don't know.  In any case this is what the actual function that calculates the position of the sun in the sky, given the longitude, latitude, and time of day appears to look like. 

    compute_local_aspect() {
        let solar_time, ra_base, ecliptic_aspect;
    
        this.m_gmt_seconds = 3600.0 * (this.m_hour - this.m_daylight_savings - this.m_time_zone) + 60.0 * this.m_minute + this.m_second;
        solar_time = this.m_gmt_seconds * (1.0 / 3600.0);
        this.m_julian = julian_day(this.m_month, this.m_day, this.m_year) - julian_day(3, 20, 1900) + solar_time * (1.0 / 24.0);
        ecliptic_aspect = ((this.m_julian % 365.242191) * TWO_PI) / 365.242191;
        const ecliptic_aspect_vector = tensor.rotate_z(ecliptic_aspect).multiply(_vector(1, 0, 0));
        ra_base = (ecliptic_aspect * 24.0) / TWO_PI;
    
        const SIDT = tensor.rotate_z((solar_time - ra_base) * (TWO_PI / 24.0) - TO_RADIANS(this.m_longitude));
    
        let local_xyz;
        const p = new polar_orientation();
        p.m_theta = 0.0;
        p.m_phi = TO_RADIANS(this.m_latitude);
        local_xyz = p.get_xyz();
    
        const ROTL = tensor.rotator(
            _vector.normalize(local_xyz.cross(_vector(0, 0, 1))), p.m_phi - PI_OVER_TWO
        );
    
        const GLSUN = ROTL.multiply(SIDT).multiply(this.m_ROTX);
        this.m_local_solar_vector = GLSUN.multiply(ecliptic_aspect_vector);
        const q = polar_orientation.from_axis(this.m_local_solar_vector);
    
        this.m_el = TO_DEGREES(q.m_phi);
        this.m_az = ((360.0 + TO_DEGREES(q.m_theta)) % 360.0);
    }    

     Pretty much a no-brainer, once most of the real work has been...

    Read more »

  • Counting down to the home stretch

    glgorman08/10/2025 at 01:24 0 comments

    OK, this is where the project stands right now.  I have the "Teapot In the Garden Stuff running in one "application" which is OpenGL aware, and which has a whole bunch of fun stuff, like wave audio playback, multi-document support, and so on.  Here, it would be easy to implement an OpenGL clock face, so that I can perhaps have my "clock on the wall" or a clock tower in a garden scene, whether in a game-like environment, or based on GPS data.

    In another application, I have been merging the GPS with the input stream that feeds to an Eliza-style chatbot, for purposes of testing the ability to decode the live streaming data, when available, among other things.  Here is an example where I simply copied and pasted some test data from Wikipedia, so as to test GPS string parsing in "Eliza" and verify that the data can "optionally" be streamed to an MFC-style CEdit View, while diagnostic data verifying that the NMEA string parsing of the "tokenized" stream is working correctly, and that the associated azimuth and elevation of the sun for the relevant location is also being calculated.

    Likewise, the "Propeller Debug Terminal" application, which is available on Git, and will be updated at some point, also supports GDI-based graphics, in the CSignalView class, as can be seen with some of the sample plots of oscilloscope data and the plotting of something resembling a Smith Chart.  In this configuration, actual GPS data can also be streamed from a GPS module, where it is simply being displayed alongside a here-seen, partially drawn Smith-Chart.  Perhaps what I should try next, therefore, is to go ahead and see if the Propeller Debug terminal can make calls into the Euclidian geometry library via the CSignalView class, instead of simply "drawing a Smith Chart directly". 

    Then maybe add Open-GL support to the Euclidian library, so that I don't have to try to implement a full Open-GL stack in software, since I really only would need that if I were going to port the application over to another platform, like running it on a Propeller P2 board, which I have, or some other alternative platform, like a commander X16, which I do not have, or even a full ground up FPGA based system, with custom CPU operations done in Verilog.  Not quite there either.  Maybe some other time.

    Maybe a nice Win32 application with OpenGL support, but without MFC support, that could perhaps be compiled as a control panel, screen saver, DLL, or even as an Active X control so that it can be tested as a possible "browser plug-in".  What am I leaving out? Haven't ever done much with "Processing", even though it does appear to be a popular platform, and that would possibly help with MacOS, and or Android support, along the way.  Maybe I should look into whether anyone else has ever tried creating Windows Desktop accessories in Processing.

    Or maybe some other time, in some parallel universe. Then again, it is quite simple to try to create a pure standalone application without full Document-View support, but which makes use of the Euclid stuff as an externally linked library, even though that takes a whole world on its own of fiddling with settings for whether I want to render for a certain page size, or whether I want to resize for the current view, i.e. so as to fit to the current window, and so on.  Then I will need to add in the GPS over USB stuff, and create some dialogs for adjusting the settings.  Not sure how some things work in Windows 10, but it used to be possible to take a regular exe and simply change the suffix to cpl and you had a control panel, or you could change the suffix to scr to get a screen saver, provided that you also added in the needed command line parameters to tell the screen saver whether it was in preview mode or whether it should be in full screen mode.

    Now, subclassing an actual Microsoft Windows application?  Well, the old-fashioned way...

    Read more »

  • This is just too much fun to resist!

    glgorman08/07/2025 at 08:06 0 comments

    First attempt at doing a test rendering of the "calculation" for the minute marks with this code.  Ran "correctly" on the first try. Zooming out will show what is really happening.

    With this code no less:

    void euclidian::draw_clock ()
    {
        vector<fpoint> hrot;
        fpoint minute_marks [60];
        dodecagon hour_marks;
        pentagon penta;
    
        hour_marks = construct_dodecagon (false);
        penta = construct_pentagon (false);
        euclidian::bind(*m_host,hour_marks);
        hour_marks.on_draw (true,true);
        fpoint center = hour_marks.m_center;
        fpoint radial = hour_marks.m_points[0];
        m_host->draw_polygon(center,radial);
    
        int i,j;
        angle a;
        hrot.resize (12);
        for (i=0;i<5;i++) {
            a = angle(fline(penta.m_points[i],penta.m_center));
            for (j=0;j<12;j++)
            hrot[j] = hour_marks.m_points [j];
            a.angle::rotate_points (hrot,hour_marks.m_center);
            for (j=0;j<12;j++)
            minute_marks[12*i+j]=hrot[j];
        }
        SETCOLOR _(m_host->m_pdc,COLOR::magenta);
        for (i=0;i<60;i++)
        {
            m_host->draw_line (hour_marks.m_center,minute_marks[i]);
        }
    }

    Well, there is still a bit of work to do.  Like I might want to consider running quick sort on the minute marks, because they are most likely written to the vector of fpoints in a somewhat scrambled or shuffled fashion.  Even though now that I am thinking about it, that wouldn't be necessary if all that we are doing is using the point cloud to decide where to draw the actual and therefore properly determined minute marks, which should therefore be possible to draw, now, that is, in another piece of code. Hopefully, let's say, after a whole lot of this stuff gets refactored and then moved to a constructor.

    Or maybe I can actually run quicksort on the array, using a custom comparison function that compares the angles of adjacent points.  Something that is certainly worth looking into, even if that involves using trig functions, just to see what is really happening here.  Of course, if you didn't know that Gauss, I think, was the one who figured out how to do a 17-sided rigorous construction, and of course, 3 times 5 times 17 is 255, which means that a regular 255-sided polygon is also a theoretical compass and straight edge construction, which will have to wait for another time. 

    A quick screenshot of some debugging information, where I call a function to calculate the actual angle of each line, as it is being drawn, shows what is happening.

    The good news is that it is exactly what I was expecting!  That being the nature of the design, code, compile, test, debug, etc., cycle.  Wanting to see results.  Now!  And getting an interesting, fun surprise now and then.  Now, like I said, I am thinking that I can still calculate the locations for my minute marks with this stuff.  Not a problem there.  Yet, I must confess that I have some circle drawing code that elsewhere is actually pre-calculating the points of a polygon with a "large number of sides" by actually making some calls to sine and cosine.  And THAT code needs to GO, since what I want to try instead is some kind of quadratic interpolation based on sets of three or four points, depending on the required resolution, and so on, and that will require that the points be sorted.  What to do, therefore?  Quicksort the array, or figure out how to fix the issue with modular arithmetic as the array is being created?  Hmm?  What would Eratosthenes or Pythagoras do?  Or Ptolemy, for that matter?

    Well, anyway.  A little more tweaking with the drawing code, and it is starting to look like something.  Even if the array that holds the coordinates for the minute marks is still unsorted.  Then it occurred to me, that in order to actually draw the time, without using trigonometric functions, I am going to need to be able to do a table lookup of the relevant locations, so that I can use a...

    Read more »

  • Time for a Long Over Due Update.

    glgorman08/05/2025 at 20:10 0 comments

    And in other news, I now have the ability to stream GPS data via some of the functions in the Propeller Debug Terminal for that application, which is presently also being repurposed for an eventual "Teapot in the Garden Project".  Calculating the position of the sun in the sky via GPS is also working over there, so maybe I should do yet another major revision of the communications libraries that that project uses, so as to make them callable from any project.  Then I could perhaps start on the otherwise "simple" task of drawing a clock face, all without conditional logic or "need" to make use of trig functions, of course.

    Keeping things interesting, of course, I am using some library calls from an otherwise broken version of the chatbot Eliza to parse the GPS data, which is being received via USB, thus providing more than one way to get the time, i.e., so that we can obtain the time from a simple COLEDateTime object or we can get it from GPS, as described in "Teapot in the Garden"

    void solar_elements::set_time ()
    {
        COleDateTime _dt = COleDateTime::GetCurrentTime();
        m_year = _dt.GetYear ();
        m_month = _dt.GetMonth ();
        m_day = _dt.GetDay ();
        m_hour = _dt.GetHour ();
        m_minute = _dt.GetMinute ();
        m_second = _dt.GetSecond ();
        m_time_zone = -8;
        m_daylight_savings = 0;
    }
    
    void solar_elements::set_time (char *str)
    {
        COleDateTime _dt = COleDateTime::GetCurrentTime();
        m_year = _dt.GetYear ();
        m_month = _dt.GetMonth ();
        m_day = _dt.GetDay ();
    
        ASSERT (strlen(str)==6);
        char str_h [4], str_m [4], str_s [4];
        strncpy_s (str_h,4,&str[0],2);
        strncpy_s (str_m,4,&str[2],2);
        strncpy_s (str_s,4,&str[4],2);
        m_hour = atoi(str_h);
        m_minute = atoi(str_m);
        m_second = atoi(str_s);
        m_time_zone = -8;
    
        if (m_time_zone!=0)
            m_hour = (m_hour+24+m_time_zone)%24;
        m_daylight_savings = 0;
    }

    Of course, a nice bonus to using GPS is that I now also have the ability to obtain the user's actual longitude and latitude, which can therefore be passed to the solar_elements class for the purpose of finding the current azimuth and elevation of the sun, which can in turn be handed over to OpenGL for such things as determining the lighting model, that is if I ever get around to drawing the actual clock!  At that point, as wonderful as the methods of Euclid are, it is unfortunately necessary to make a few trig calls, not very many, however, from the functions that actually compute the position of the sun.  Since I haven't quite worked out the whole Ptolemy system yet, with corrections as if according to Kepler.  And we all know that infinite series methods did not exist for evaluating trig functions until much later, i.e., until Newton, Taylor, Gauss, Euler, and so on.  Yet not, to worry - just in case on some other hardware platform, if we ever get there - "where we are going - we don't need NO FPU either!"

    So maybe, if you can imagine some parallel universe where Microsoft Altair Basic never existed, or any BASIC for that matter, imagine a world where we had no floating point routines, or perhaps no math routines at all, but we could roll our own from day one with C++ operator overloading, then in a C++ "real" class, IEEE-754 (maybe) multiplication might look like this, provide that you have regular 32 bit operations defined somewhere else.

    real real::operator * (real arg)
    {
        short _sign;
        real result;
        short exp1 = this->exp()+arg.exp()-127;
        unsigned int frac1, frac2, frac3, frac4, fracr;
        unsigned short s1, s2;
        unsigned char c1, c2;
        _sign = this->s^arg.s;
        frac1 = this->f;
        frac2 = arg.f;
        s1 = (frac1>>7);
        s2 = (frac2>>7);
        c1 = (frac1&0x7f);
        c2 = (frac2&0x7f);
        frac3 = (c1*s2+c2*s1)>>16;
        frac4 = (s1*s2)>>9;
        fracr = frac1+frac2+frac3+frac4;
        if (fracr>0x007FFFFF)
        {
            fracr = ((fracr+(1<<23))>>1);
            exp1++;
        }
        result.dw = (fracr&0x007FFFFF)|(exp1<<23)|(_sign<<31);
        return result;
    }

     Just in case you have a C++ compiler for your NOR computer, if you have one, but no math routines.  Well, what...

    Read more »

  • Life in the Slow Lane - or else Here Comes the Sun?

    glgorman07/02/2025 at 07:54 0 comments

    Apparently, there is now a "One Hertz Challenge".  Not sure exactly how I am going to go about this.  Maybe take a Parallax Propeller II module, which is capable of VGA as well as HDMI output, and make a version of the clock that I was talking about.  Just in case I don't need trig calls.  Just in case I don't need full OpenGL, but also just in case I would like to have a virtual clock face that accurately casts a shadow of the hands on the face of the clock, as if according to the position of the sun in the sky, that is according to the desired Longitude, Lattitude and maybe even current weather.

    So, of course, if we are going to do this, we need to calculate the position of the sun in the sky, to a reasonable approximation, at least once per second, right?  How hard can that be?  Maybe not all that hard at all if we assume a circular orbit, ignore atmospheric effects, leap seconds, precession of the equinoxes, etc.

    #include "stdafx.h"
    #include <ATLComTime.h>
    #include <math.h>
    #include "../rubidium/defines.h" #include "../rubidium/drawstuff.h"
    
    #define INCLINATION_OF_EARTH_ORBIT    23.439281
    
    using namespace TENSORS;
    
    class celestial_coordinates
    {
    public:
        MATH_TYPE right_ascension;
        MATH_TYPE declination;
    };
    
    solar_elements::solar_elements ()
    {
        COleDateTime _dt = COleDateTime::GetCurrentTime();
    
        m_year = _dt.GetYear ();
        m_month = _dt.GetMonth ();
        m_day = _dt.GetDay ();
        m_hour = _dt.GetHour ();
        m_minute = _dt.GetMinute ();
        m_second = _dt.GetSecond ();
    
        m_longitude = 119.81;
        m_latitude = 39.53;
        m_time_zone = -8;
        m_daylight_savings = 0;        R = 3958.8*5280.0*FEET_TO_CM*1.0e-5;
        m_ROTX = tensor::rotate_x (TO_RADIANS(INCLINATION_OF_EARTH_ORBIT));
    }
    
    void solar_elements::debug_test ()
    {
        ASSERT (julian_day (1,1,2000)==2451545);
        ASSERT (julian_day (6,19,1987)==2446966);
        ASSERT (julian_day (12,8,2009)==2455174);
    
        int H,M;
        for (H=0;H<24;H++)
        for (M=0;M<60;M+=10)
        {    m_hour = H;
            m_minute = M;
            compute_local_aspect();
    //    TRACE ("SOLAR time = %02d:%02d  AZIMUTH = %f, EL = %f\n",H,M,m_az,m_el);
        }
    }
    
    double solar_elements::julian_day  (int M, MATH_TYPE D, int Y)
    {
        int mm = (M-14)/12;
        int yy = (Y+4800+mm);
        int JDN1 = (1461*yy)/4;
        int JDN2 = (367*(M-2-12*mm))/12;
        int JDN3 = (3*((yy+100)/100))/4;
        MATH_TYPE JDN = JDN1+JDN2-JDN3+D-32075;
        return JDN;
    }
    
    void solar_elements::compute_local_aspect()
    {
        MATH_TYPE solar_time, ra_base, ecliptic_aspect;
    
    //    estimate ecliptic aspect
    
        m_gmt_seconds = 3600.0*(m_hour-m_daylight_savings-m_time_zone)+60.0*m_minute+m_second;
        solar_time = m_gmt_seconds/3600.0 - m_longitude/15.0;
        m_julian = julian_day (m_month,m_day,m_year) - julian_day (3,20,1900) + solar_time/24.0;
        ra_base = fmodf(m_julian,365.242191)/(360.0/24.0);
        ecliptic_aspect = ra_base*TWO_PI/24.0;
        tensor SIDT = tensor::rotate_z ((solar_time-ra_base)*TWO_PI/24.0);
        _vector ecliptic_aspect_vector = tensor::rotate_z (ecliptic_aspect)*_vector(1,0,0);
        m_geocentric_solar_vector = m_ROTX*ecliptic_aspect_vector;
        _vector...
    Read more »

  • Is It Time To Revisit The Visitor?

    glgorman05/25/2025 at 14:31 0 comments

    I am thinking about revisiting the visitor pattern as soon as I can remember exactly what it is and how it works or is supposed to work.  If I remember correctly, the visitor pattern is a design pattern in object-oriented programming that makes use of three properties that can be bound to a set of objects.  One of these properties is that of being a “client”, another property is that of being or becoming an “operator”, and the third property is that of being or otherwise acting as the “observer”.

    I might have this all wrong, but as I see it, these roles should not be fixed.  For example, suppose in a real-world situation, a “client” might be an actual customer who visits a hair salon, or perhaps someone who hires a plumber to fix some leaking pipes.   Whereas the observer in one of those cases could be the salon owner, or perhaps the person who holds a plumbing contractor's license.  The operator, then, is the employee who does the actual work.  Sounds simple, right?  Well, maybe that is until the business owner gets inspected by the Department of Environmental Health, or they get audited by the IRS, for example.  Now they become the client, or something like that.

    Now, computer software is usually a little more abstract, or is it?  What if we similarly define objects and methods to what has been described, where a word processing application might be the “observer”, the document is the client (or visit), and the spell-checker is the operator, or something like that?

    This has huge implications for things like memory management, of course.  Who is responsible for deleting an object when its reference count reaches zero if reference counting is used?  And what if we more often than not don’t really need reference counting semantics, and all the inefficiencies that it brings to what might otherwise be a very high-performance application?  Consider, for example, “publish and subscribe semantics”.  Maybe a graphics application “publishes” a shape library for use by a parallelized set of shaders and other renderers?  Likewise, what if we don’t need to have reference counting for objects in a relational database that is based on a so-called “journaling file system”?  So, object persistence might negate the need for reference counting, allowing the use of unsafe pointer types in many cases, while at the same time, the reference count might just somehow reappear anyway, in the form of the “subscriber” count in some other context. 

    So here I am thinking about braids, again, and how this might affect our understanding of object complexity, and that, of course, has me imagining yet another use for the visitor pattern.  Maybe.

    O.K., then – what if there is the notion of “the rambling manifesto”, vs enforcing the “chain of thought”, as well as the need for a “prompt” in an LLM or transformer-based AI model?  A use case should exist, therefore, for the visitor pattern, or outright “weaving” of some kind of abstract hypergeometric non-Abelian braiding topology, along with its associated Hilbert spaces.  If Swinnerton-Dyer holds, then the keys to AGI might be concordant with the concepts of “ascension” and “generalization,” that is to say, by the nature of the fact that the implied diffeomorphism with respect certain concepts in General Relativity, such as “raising an index” or “contracting a manifold” by deducing the invariants associated with a particular matrix formulation.

    This should work out quite nicely, that is to say, if the geometrization of space-time is in fact rigorous.

    In the meantime, at least I have some ideas about how to proceed with the design patterns for use with improvements...

    Read more »

  • Beyond the Sands of Time?

    glgorman05/06/2025 at 09:17 0 comments

    Perhaps my drawing room needs an old-fashioned drafting table, for my compass and straight-edge proofs. A clock on the wall would be nice, as would be some books for my bookshelves. The piano still needs legs and a place for some sheet music. Thus, while writing a game engine entirely from scratch is never an easy undertaking, I still think that it is a worthwhile endeavor. Most who dwell around these parts will understand why.

    So, yeah - I am having thoughts about making a game engine that contains some kind of object editor, "in-game", as it were, or as I should say, as it eventually will be.  Then I also want to have the stuff from "Teapot in the Garden", which you can find elsewhere, i.e., along the photo-realistic hair generating stuff, that also does blades of grass, trees, etc., all based on the same theory of "Digital DNA" based procedural mesh generation, among other things, and where some of other things includes the foundational stuff that is all based on the principles of Euclid, also as previously discussed.

    Thus, likewise, I think that AI, LLMs, and transformers as such are going to turn out to be quite useful, not just for giving personality to avatars, as such, but also for doing things according to some modern variant of SHRDLU, which I am also still working on, in addition to the Eliza stuff, believe it or not.

    Not that I couldn't perhaps run some variant of Ki-CAD as an ActiveX X control, for example, that is to say, within a view - inside a game engine perhaps? Even if the Meta-verse is pretty much a failure.  Even if Microsoft BOB was a failure.  Just so long as I don't try to reinvent "Clippy!"  Right?

    O.K., maybe an old-fashioned analog clock on one of those walls would be nice, at least for now.  Along with an old-fashioned drafting table.

    I wonder how many people remember that BeOS could do "books" with page-turning effects, along with animations on the individual pages?  A rather impressive feat for the late 90's, that is, that something like that could actually be done, even then without a GPU, i.e., on just a PowerPC.

    Then there is reflection, as an optical concept, or as a psychological concept, or even as a programming concept.  This is something to ponder - or at least reflect upon.

    To be continued ...

  • What if Time could go Sideways?

    glgorman05/02/2025 at 20:22 0 comments

    Well, time doesn't go sideways, but I can turn my 3-D perspective view of the Euclid style renderings on its side, just because it is possible to do.  Of course, there is the idea of Feynman's sum-over-all histories approach to quantum electrodynamics, where one interpretation might be to allow for time to act, perhaps like it has multiple dimensions, which converge, usually, to a single path chosen.  Yet, that is not what this post is about.   What then is this post about?  Well, keep reading.

    I saw the other day how someone got an LLM to run TinyStories260K on a C64 with 2MB of RAM expansion, of course, and that looks interesting, obviously - especially if LLAMA2 can be reduced to just 700 lines of C.  So, I think that I am on track as far as eventually doing a better AI based on some of my log entries from Hackaday, among other things.  Thus, this log entry, like many others, will eventually, all in due time of course, go into the training file for a small LLM, as it were, or else I should perhaps say, as it will be.  So that is part of the method for the madness.

    Other than that, I realized something while finally rendering the hexagon.  Something quite interesting, that is.  Here is a simple question.  Is it better to draw five hexagons, according to the vertices of the pentagon, and thereby obtain, hopefully, a set of 30 points that can be further used to construct the 60-minute marks, as well as the hour marks for a clock face?   Or is it better to construct one reference hexagon and then construct six pentagons, even though that would obviously be more work computationally?  The definition of "better," of course, might depend on such things as the accumulation of roundoff error, for example, and maybe compute time doesn't matter so much, if the calculations, all being done without trig calls of course, only need to be done once, as in the constructor for a master set of points when a module is instantiated.

    Then I realized that there might be a third approach.  Draw a simple equilateral triangle inside a circle.  Then construct at least one pentagon, sharing a vertex, and then, according to the points of the pentagon, construct a couple of hexagons, acting as if kind of random, in effect, just doing whatever, so as to get more points.

    This could get messy, since some sets of vertices might get constructed more than once, and maybe some comparisons and sorting operations would need to be performed, even though that would probably involve branches, and it would also really mess with things as far as the meanings of words like "proof" and "rigor" are concerned, especially insofar as trying to prove the equivalence of the results of an analytic construction vs. a real world compass and straight edge construction are concerned.

    Fortunately, I don't think that would involve an infinite regression, just some kind of tree search that could include redundancy checking, as a part of a larger equivalence testing regimen.

View all 13 project logs

  • 1
    Gather the Required Software and Hardware Components.

    If you need GPS synchronization for your PC, first obtain a suitable GPS module and TTL to USB converter as described in the project "Teapot In the Garden", and simply hook it up, according to whatever instructions that might come with whatever you can get your hands on that works.  If you use PuTTY to connect to the GPS, for example, and you have a 4800 bps module, then you should have no problem viewing streaming NMEA data in that application.  Next, you should also obtain some of the source code from any of a number of previous projects that I have posted to Hackaday, and which are also associated with repositories on Git.  

  • 2
    Now the fun begins. As an alternative to the previous step, you might want to try Processing or another application.

    Whatever, right?  Once you have decided on what platform you want to build for, let's say, if you want to try connecting to a GPS module over Bluetooth from an Android Tablet?  Well, then you are on your own to get that setup working on the hardware side, since it should actually be quite easy to do, and in which case you would want to see if Processing for Android will let you talk Bluetooth, and so on.  Thus, from this point forward, we will assume that you have your hardware setup and your commination's working, whether in the Propeller Debug Terminal on a PC, or in some other environment.

  • 3
    Get the Euclidian Stuff and go to Town.

    Generating fully animated proofs of all 465 of Euclid's proofs and demonstrations is a bit beyond the scope of this project, but certainly within the realm of possibilities, just in case you need some really interesting tools for some yet ever so even weirder proof of something attributed to that Pythagoras. Otherwise, maybe this is a really good time for me to post the C++ source and header files for the Euclid stuff, which proves that yes, it really is possible to use branchless, or nearly branchless programming, with or without loops. and so on, to do some really interesting stuff.  Just like Ptolemy or Euclid.  Even if I haven't quite eliminated ALL trig calls quite yet.  But it can be done.  Maybe some other time.  Real soon now.

View all 3 instructions

Enjoy this project?

Share

Discussions

Wouter Minjauw wrote 08/18/2025 at 21:57 point

One half of my brain was intrigued by the branchless code (but refused to analyze it after midnight). The other half wanted to make it 10.000 times more energy efficient by using lookup tables. :-) 

  Are you sure? yes | no

Gravis wrote 03/30/2025 at 21:28 point

Stop being a Microsoft slave. Seriously, Linux is just one other OS that has a full desktop. I'm using it right now and the clock/calandar widget is great. You can fully customize how the time is displayed. Your desire to continue to be abused by Microsoft is mystifying.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates