I have had the chance to get back into calculator programming, and though it'd be a nice challenge to create a QR code generator.

The simple parts (drawing the finder, alignment, and timing patterns to the screen, encoding the data into a bitstream, data masking, hard-coding version information) were a fun exercise in TI-BASIC graphics and list manipulation. It was nice to freshen up on these skills.

More difficult was the actual drawing pattern for the data bits themselves. A zig-zagging left-right, down-up, 2-pixels-at-a-time pattern that had to skip over the fixed parts of the QR code. This is compounded by having to support all versions that fit on a monochrome screen, up to the 61x61 pixel Version 11, holding up to 321 bytes.

But the Reed-Solomon Error Correction... oh my. The took quite some work to get functioning properly, and even then, it is not quick. It requires heavy use of bitwise XOR between two 8-bit values. This is not something that 83+/84+ TI-BASIC does well (TI-89/92/Voyage has bitwise XOR built-in 😛 ).

There are two 256-element lists that are hard-coded, trading off RAM usage for a bit more speed. One has a LUT for 4-bit XOR (call the LUT on the low and high nibbles of the two values, add them together, you get an 8-bit XOR). The other is a conversion from Galois Field 256 alpha notation and their exponents, a sort of log/anti-log table in GF(256). The XOR LUT, and perhaps even the GF(256) LUT, could be removed, saving 2-5kB+ of RAM during execution, if there existed a much faster way of calculating bitwise XOR.

If anyone has a better idea for bitwise XOR in pure TI-BASIC (that works for all values [0,255]) that are faster than the LUT...

This up for approval into the archives as well.


Code:
:DCS6
"FD3F84A1B52DB4AD8521FCBF0100AAAA55550000FCCE8529B529B52E8549FCA9"
ClrHome
""Goto A
Menu("USE Str1 AS-IS?","YES",A,"NO (NEW Str1)",B
Lbl B
ClrHome
Input "Str1:",Str1
ClrHome
Lbl A
//Store the variables used for restoration later
{A,B,C,D,E,F,G,H,S,V}->|LA
Output(1,1,"BYTES:    VER:  "
Output(1,7,length(Str1
//Determine Verion needed based on Str1 length. Up to 321 characters (encoded bytes) in Version 11
1+sum({17,32,53,78,106,134,154,192,230,271,321}<length(Str1))->V
//If too long, truncate Str1 and note this by displaying ^^o next to the BYTES readout
If length(Str1)>321
Then
   sub(Str1,1,321->Str1
   11->V
   Output(1,10,"^^o"
End
Output(1,15,V
//Start Encoding the bitstream, broken into bytes in |LD
//Byte-encoding is used, so the first 4 bits should be 0100
{4*16}->|LD
//For Versions 1-9, 8 bits are needed to store the length of the encoded data. for versions 10 and 11, 16 bits are used. Since the encoding method takes up 4 bits, put the high 4 bits of the length into the lower 4 bits of the first bytestream byte, and the next 4 bits into the higher 4 bits of the next byte.
If V>=10
Then
   iPart(length(Str1)/256)->C
   |LD(1)+iPart(C/16)->|LD(1)
   16*16fPart(C/16)->|LD(2)
End
//This line extracts the lower 8 bits of the length. For V's 1-9, this does not do anything.
256fPart(length(Str1)/256)->C
//Again, upper 4 bits into the lower 4 bits of the last byte, lower 4 bits into the upper 4 bits of the next byte
|LD(dim(|LD))+iPart(C/16)->|LD(dim(|LD))
16*16fPart(C/16)->|LD(1+dim(|LD))
//At this point, the datastream looks like this:
//V 1-9: [0100 XXXX] [XXXX 0000], where XXXXXXXX is the 8-bit length of the encoded data
//10-11: [0100 YYYY] [YYYY XXXX] [XXXX 0000], where YYYYYYYYXXXXXXXX is the 16-bit length of the encoded data
Output(2,1,"DATAWORD:0  /   "
Output(2,14,length(Str1
//For each character, convert it to the ASCII codeword (0x20-0x7E), and split that 8-bit code into high and low 4-bit nibbles, putting them in the datastream in order.
//SourceCoder removes the \ character, so I have replaced it here with / (between [ snd ]). This is correct in the .8xp
For(A,1,length(Str1
   //Find the codeword corresponding to the character
   31+inString(" !^^o#$%&'()*+,-./0123456789:;<\=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}|~",sub(Str1,A,1))->C
   //If it's not found, replace it with a space
   If C=31
   32->C
   dim(|LD)->D
   //upper 4 bits of codeword go into the lower 4 bits in the last byte of the datastream
   |LD(D)+iPart(C/16)->|LD(D)
   //lower 4 bits of the codeword go into the upper 4 bits into the next byte of the datastream
   256*fPart(C/16)->|LD(D+1
   Output(2,10,A
End
//After all characters are encoded, the datastream need to be padded out to fill the length required of its version.
{19,34,55,80,108,136,156,194,232,274,324}
//Find the difference between the length of the datastream and the requried length
Ans(V)-dim(|LD)->C
If C
Then
   1->D
   //If there is a difference, alternate between adding bytes 236 and 17 to the end of the datastream. Being 3 bytes short would result in the augmentation of 236, 17, 236
   For(A,1,C
      D236+(1-D)17->|LD(1+dim(|LD))
      1-D->D
   End
End
//The datasteam is then broken into blocks, and each block has a number of error correction codes calculated. The version's error correction code count per block is determined
{7,10,15,20,26,18,20,24,30,18,20
Ans(V->E
Output(3,1,"BLOCKING:0  /   "
Output(3,14,dim(|LD
//For each version, the number of blocks the datastream is broken into is determined. For V1-5, the datastream is treated as a single block.
{1,1,1,1,1,2,2,2,2,4,4
Ans(V->B
//The datastream is split into half or into 4 pieces. The number of datawords in each block is calculated based on the number of datawords in that version and dividing that by how many blocks it is being broken into. For Version 10, the division results in 68.5 datawords. This is a special case, where the first two blocks are 68 datawords, and the last two blocks are 69 datawords.
{19,34,55,80,108,136,156,194,232,274,324}
iPart(Ans(V)/B->D
//Example: datasteam is {1,2,3,4,5,6,7,8}, breaking that into 2 blocks:
// block 1: {1,2,3,4}, block 2: {5,6,7,8}
{0->|LB1
{0->|LB2
{0->|LB3
{0->|LB4
//Set the dimensions of the Block lists, adding 1 to B3 and B4 for the special case of V10
D->dim(|LB1
If B>=2
D->dim(|LB2
If B>=3
D+(V=10->dim(|LB3
If B>=4
D+(V=10->dim(|LB4
1->A
1->D
//Var D tracks which block is being written to. Var A counts how many bytes have been written to that block so far.
For(C,1,dim(|LD
   If D=1
   |LD(C->|LB1(A
   If D=2
   |LD(C->|LB2(A
   If D=3
   |LD(C->|LB3(A
   If D=4
   |LD(C->|LB4(A
   A+1->A
   //When the whole block has been written, move to the next block.
   If A>(dim(|LB1)+(V=10 and D>=3)
   Then
      1->A
      D+1->D
   End
   Output(3,10,C
End
//To save RAM, once the datastream |LD has been split into blocks |LB1-3, delete |LD.
0->dim(|LD
//Reed-Solomon Error Correction emplys heavy use of bit-wise XOR operations. On the 68k calulators (TI-89, TI-92/Voyage), XOR is already a bitwise operator. But this is not the case on the Z80 calcs, so XOR calculations in TI-BASIC are computationally expensive.
//To aid in this, a 4-bit XOR table is populated into |LX. For values of F=[0,15] and G=[0,15], the lookup table |LX(16F+G+1) contains the value of bitwise F OR G. Performing this lookup on both the upper and lower nibbles of two bytes is faster than extracting each bit, comparing them, and calculating the result. Even with this speedup, the Error Correction calculations take the majority of the time spent on generating the QR code.
0->dim(|LX
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14,2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13,3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12,4,5,6,7,0,1,2,3,12,13,14,15,8,9,10,11,5,4,7,6,1,0,3,2,13,12,15,14,9,8,11,10,6,7,4,5,2,3,0,1,14,15,12,13,10,11,8,9,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7,9,8,11,10,13,12,15,14,1,0,3,2,5,4,7,6,10,11,8,9,14,15,12,13,2,3,0,1,6,7,4,5,11,10,9,8,15,14,13,12,3,2,1,0,7,6,5,4,12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3,13,12,15,14,9,8,11,10,5,4,7,6,1,0,3,2,14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}->|LX
//The Error Correction calculations must create data that falls within the limits [1-255] (Galois Field 256, or GF(256)), so the error codes all fit within a byte each. For this, as you multiply by 2, for every number over 255, a modulo'd value is calculated (256 turns into 29, which multiplied by 2 is 58, 116, 232, then 464 is turned into 205, etc). Doing the calculation for each time this is needed would take too long, so these numbers are pre-calculated into a Log lookup table.
0->dim(|LLOG
{1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,1}->|LLOG
//For each version, the number of error codes for each block is determined.
//Then, for that number of error codes, a generator polynomial with that number of coefficients is defined. These are calculatable, but are easier just to have pre-calculated.
//coeffiecient count = {7,10,15,20,26,18,20,24,30,18,20}(V)
If V=1
{0,87,229,146,149,238,102,21->|LG
If V=2
{0,251,67,46,61,118,70,64,94,32,45->|LG
If V=3
{0,8,183,61,91,202,37,51,58,58,237,140,124,5,99,105->|LG
If V=4 or V=7 or V=11
{0,17,60,79,50,61,163,26,187,202,180,221,225,83,239,156,164,212,212,188,190->|LG
If V=5
{0,173,125,158,2,103,182,118,17,145,201,111,28,165,53,161,21,245,142,13,102,48,227,153,145,218,70->|LG
If V=6 or V=10
{0,215,234,158,94,184,97,118,170,79,187,152,148,252,179,5,98,96,153->|LG
If V=8
{0,229,121,135,48,211,117,251,126,159,180,169,152,192,226,228,218,111,0,117,232,87,96,227,21->|LG
If V=9
{0,41,173,145,152,216,31,179,182,50,48,110,86,239,96,222,125,42,173,226,193,224,130,156,37,251,216,238,40,192,180->|LG
//These Generator Polynomials are used as the divisor in a long-division algorithm with each block's bytes as the coefficients of a polylomial in the numerator. The remainder of the this long-division is the error correction code.
{0->|LE1
{0->|LE2
{0->|LE3
{0->|LE4
//Prepare the Error Correction Code (ECC) lists, based on the number of B Blocks the datastream was broken into.
E->dim(|LE1
If B>=2
E->dim(|LE2
If B>=3
E->dim(|LE3
If B>=4
E->dim(|LE4
//For each Error Code list E up to the number of B Blocks:
For(E,1,B
   If E=1
   |LB1->|LM
   If E=2
   |LB2->|LM
   If E=3
   |LB3->|LM
   If E=4
   |LB4->|LM
   //Store the correspongin Block into an in-work Message |LM
   dim(|LM->C
   Output(4,1,"ERR: / , 0  /   "
   Output(4,5,E
   Output(4,7,B
   Output(4,14,C
   //For every byte A in the Message:
   For(A,1,C
      //Find the exponent (reverse lookup into |LLOG) of the byte
      sum(not(cumSum(|LLOG=|LM(1)->D
      //Store the Generator Polynomial into an in-work |LH
      |LG->|LH
      //For every coefficient in the in-work Generator Polynomial:
      For(G,1,dim(|LH
         //Add the exponents of the byte A and the coefficient of the generator polynomial (mod 255), effectivly multiplying the generator polynomial such that the leading term of the resulting polynomial (which used to be 1) is now equal to the byte.
         D+|LH(G
         If Ans>255
         Ans-255
         |LLOG(1+Ans)->|LH(G
      End
      //In Long division, if calculating 781/2, we have now said that two goes into seven 3 times. This 3 has been multiplied by the divisor 2 resulting in 6 (the current contents of |LH is "6"). Now we need to subtract 600 from the numerator 781, giving us a remainder to continue the long division.
      //In Galois Field 256, addition and subtraction act on bits independently, which is to say addition and subtraction are the same operation: bitwise XOR. So for each element in the Message (781), subtract (XOR) the result of the multiplacation of the Generator polynomial and how many times the leading term of that polynomial fits into the leading byte of the message (600, |LH)
      max({dim(|LM),dim(|LH)->dim(|LM
      Ans->dim(|LH
      For(D,1,dim(|LM
         |LH(D)/16->F
         |LM(D)/16->G
         16|LX(16int(F)+int(G)+1)+|LX(256fPart(F)+16fPart(G)+1->|LM(D
      End
      //This result is a new message polynomial that has a leading coefficient of 0, so chop off that zero and move down to the next byte in the remainder. (781-600=181, now move on to the ten's place)
      DeltaList(cumSum(|LM->|LM
      Output(4,10,A
   End
   //Do this for each block. The remainder after stepping through every byte in the message is the ECC. Store these for later
   If E=1
   |LM->|LE1
   If E=2
   |LM->|LE2
   If E=3
   |LM->|LE3
   If E=4
   |LM->|LE4
End
//To save on RAM, delete the in-work lists and lookup tables.
DelVar |LM
DelVar |LG
DelVar |LH
DelVar |LX
DelVar |LLOG
Output(5,1,"INTERLEAVING:"
Output(6,1," DATA: 0 /     "
Output(6,11,dim(|LB1
//Now we re-build the Datastream using the blocks and the ECCs. For codes with more than one block, this involves interleaving the data from each block byte-wise.
For(A,1,dim(|LB1)
   |LB1(A->|LD(1+dim(|LD
   If B>=2
   |LB2(A->|LD(1+dim(|LD
   If B>=3
   |LB3(A->|LD(1+dim(|LD
   If B>=4
   |LB4(A->|LD(1+dim(|LD
   Output(6,8,A
End
//V10 is the special case, where blocks 3 and 4 are 69 bytes long. Tack those on the end.
If V=10
Then
   |LB3(dim(|LB3->|LD(1+dim(|LD
   |LB4(dim(|LB4->|LD(1+dim(|LD
End
//To save RAM, delete the blocks.
DelVar |LB1
DelVar |LB2
DelVar |LB3
DelVar |LB4
Output(7,1," ERROR: 0  /   "
Output(7,13,dim(|LE1
//After all the blocks' data bytes are interleaved, the same process is enacted on the Error codes, reulting in a final bitstream to draw the QR code.
For(A,1,dim(|LE1)
   |LE1(A->|LD(1+dim(|LD
   If B>=2
   |LE2(A->|LD(1+dim(|LD
   If B>=3
   |LE3(A->|LD(1+dim(|LD
   If B>=4
   |LE4(A->|LD(1+dim(|LD
   Output(7,9,A
End
//To save RAM, delete the error codes.
DelVar |LE1
DelVar |LE2
DelVar |LE3
DelVar |LE4
//The resulting datatream |LD is used to draw the QR code.
//Set up the graphscreen to be blank, ready to draw.
PlotsOff
FnOff
AxesOff
GridOff
ClrDraw
//The size of the QR code is calculated based on the version. V1 is 21 pixels, with each version being 4 pixels larger. This is 0-indexed, so Size will be 20 for V1, not 21.
4V+16->S
//Calculate the Upper-Left pixel position of the QR code. Limiting this to V11 means a 61x61 pixel code, which has only a single row of pixels spare on the top and bottom of the code on the 63x95 pixel space of a monochome calculator. The color calculators could handle much larger codes, but for simplicity, these have not been implemented. Even so, that much data is not possible to be viewed on the homescreen at once (26x10=260 characters on the homescreen of a color calc, only 16x8=128 on monochrome), and if your data is longer than 300 bytes, it's probably best not to use a QR code, or shorten your data IMO)
31-S/2->A
47-S/2->B
//The 3 characteristic finder patterns are drawn to the screen (the bulls-eyes in the 3 corners).
{0,0,0,0,0,0,0,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,6,6,6,6,6,6,6,0,1,2,3,4,5,6,0,6,0,2,3,4,6,0,2,3,4,6,0,2,3,4,6,0,6,0,1,2,3,4,5,6}
//Ans is used since it is quicker to access than a list.
For(C,1,33
   Pxl-On(A+Ans(C),B+Ans(C+33)
   Pxl-On(A+S-Ans(C),B+Ans(C+33)
   Pxl-On(A+Ans(C),B+S-Ans(C+33)
End
//Alignment pattern(s) are drawn. These are the smaller bulls-eye(s) that are in the bottom-right of larger QR codes, and in the center and along the edges of even larger QR codes.
{~2,~1,0,1,2,~2,2,~2,0,2,~2,2,~2,~1,0,1,2,~2,~2,~2,~2,~2,~1,~1,0,0,0,1,1,2,2,2,2,2}
For(C,1,17
   If V>=2
   Pxl-On(25+S/2+Ans(C),41+S/2+Ans(C+17)
   If V>=7
   Then
      Pxl-On(31+Ans(C),53+Ans(C+17)-S/2
      Pxl-On(37+Ans(C)-S/2,47+Ans(C+17)
      Pxl-On(31+Ans(C),47+Ans(C+17)
      Pxl-On(31+Ans(C),41+Ans(C+17)+S/2
      Pxl-On(25+Ans(C)+S/2,47+Ans(C+17)
   End
End
//Timing patterns are drawn between the Finders, alternating black and white pixels.
For(C,1,2V+1
   Pxl-On(A+2C+6,B+6
   Pxl-On(A+6,B+2C+6
End
//For every QR code, there is a single pixel that is always black, and is not dependent on any condition.
Pxl-On(A+4V+9,B+8
//Weare using bitmask 0, and correction level L. The L-0 format information is drawn around the finders.
Pxl-On(A+8,B
Pxl-On(A+8,B+1
Pxl-On(A+8,B+2
Pxl-On(A+8,B+4
Pxl-On(A+8,B+5
Pxl-On(A+8,B+7
Pxl-On(A+8,B+8
Pxl-On(A+7,B+8
Pxl-On(A+2,B+8
Pxl-On(A+S,B+8
Pxl-On(A+S-1,B+8
Pxl-On(A+S-2,B+8
Pxl-On(A+S-4,B+8
Pxl-On(A+S-5,B+8
Pxl-On(A+S-6,B+8
Pxl-On(A+8,B+S-7
Pxl-On(A+8,B+S-6
Pxl-On(A+8,B+S-2
//G keeps track of which byte is currently being drawn.
//H keeps track of which bit in that byte is being drawn.
1->G
0->H
0->|LD(1+dim(|LD
//Working from the right to the left, every 2 pixels:
For(F,S,0,~2
   fPart((S-F)/4)<.5->C
   //starting from the botton up, then from the top down, every 4 pixels
   For(D,SC,Snot(C),1-2C
      //For each of the 2 pixels, from right to left (D,E contains the Y,X position of the pixel to be evaluated
      For(E,F,F-1,~1
         //if the pixel is not in the finder pattern or format information sections
         If not((D<9 and E<9) or (D<9 and E>S-8) or (D>S-8 and E<9)
         Then
            //if the pixel is not in the timing pattern, or in the alignment patterns, or in version sections
            If not(D=6 or E=6 or (V>=2)(D>=S-8 and D<=S-4 and E>=S-8 and E<=S-4) or (V>=7)((D<6 and E>S-11) or (D>S-11 and E<6) or (abs(D-S/2)<=2 and max(abs(E-{S/2,6,S-6})<=2)) or (max(abs(D-{6,S-6})<=2) and abs(E-S/2)<=2)))
            Then
               //it is a pixel that can be drawn to
               //if the current bit of the current byte is 1, draw the pixel
               If iPart(2fPart(|LD(G)/2^(8-H)
               Pxl-On(A+D,B+E
               //if the current position of the drawn pixel falls on the checkerboard pattern (datamask 0), change the pixel.
               If 0=fPart((D+E)/2
               Pxl-Change(A+D,B+E
               //increment the bit
               H+1->H
               If H=8
               Then
                  //increment the byte
                  0->H
                  G+1->G
               End
            End
         End
      End
   End
   //if on the left timing pattern, skip this column of pixels.
   If F=8
   7->F
End
//We are done drawing the data, so we can delete the datastream
DelVar |LD
//For versions 7 and higher (those with additional alignment patterns), the version is encoded as an 18-bit number into a 3x6 block near the finder patterns.
If V>=7
Then
   //These 18-bit numbers can be calculated for each version, but are easier to have hard-coded.
   {31892,34236,39577,42195,48118}
   Ans(V-6)->F
   For(D,0,5
      For(E,0,2
         //For each bit in that number, draw that bit in its respective location in the QR code.
         F/2->F
         If fPart(Ans
         Then
            Pxl-On(A+S-10+E,B+D
            Pxl-On(A+D,B+S-10+E
            iPart(Ans->F
         End
      End
   End
End
//For Monocrome calcs, draw black bars down the outside of the screen to indicate (out of the corner of the eye, having left this program to run for half an hour) that the program is finished.
If (Xmax-Xmin)/DeltaX<100
Then
   For(A,0,62
      Pxl-On(A,0
      Pxl-On(A,1
      Pxl-On(A,2
      Pxl-On(A,3
      Pxl-On(A,94
      Pxl-On(A,93
      Pxl-On(A,92
      Pxl-On(A,91
   End
Else
   //For Color calcs, the QR code has been drawn really small in the upper-left of the screen. Enlarge this x2, and center it properly. This is also an ou-the-corner-of-the-eye indication of program completion.
   For(D,A+S,A,~1
      For(E,B,B+S
         If pxl-Test(D,E
         Then
            Pxl-Off(D,E
            Pxl-On(2D+18,2E+36
            Pxl-On(2D+19,2E+36
            Pxl-On(2D+19,2E+37
            Pxl-On(2D+18,2E+37
         End
      End
   End
End
//Restore the used variables
|LA(1->A
|LA(2->B
|LA(3->C
|LA(4->D
|LA(5->E
|LA(6->F
|LA(7->G
|LA(8->H
|LA(9->S
|LA(10->V
//Leave No Trace
DelVar |LA
ClrHome
//DispGraph so that if this program was executed from a Shell, it won't just disappear never to be seen again. This could have been a Pause, or a StorePic 1, or something else.
DispGraph
That looks... Complicated. Any chance of an 84+ CE version, possibly with Celtic?
This already does run on the CE! It scales the QR code up by 2x on color calcs to better fill the graphscreen.

Celtic CE (and by extension, Celtic III on the monochrome calcs) does support bitwise operations, which would make this run a lot faster. On DCS 7.X this is det(31, but on Celctic CE, it is det(50, and for the 84PCSE, as far as I am aware, the BitOperate command has not been implemented.

No doubt that hybrid libs will make this a lot faster (and smaller), but it would require separate versions for the different platforms. But considering the majority of folks are on the CE now, maybe it's not a bad idea. Will look into it.
Nice work! Some basic optimization tips I've learned are to use the italics n variable as the iterator in your for( loops to make them a bit faster. Also, use L1 - L6 since they're faster than custom named lists. You're already using Ans in most places so you clearly know that optimization.

I'm sure womp will have many more suggestions once he gets his hands on it.

edit: could you please upload the .8xp to github? SourceCoder throws some strange errors when I copy and paste from the code block.
Ans optimizations are almost second nature, but the memory of using finance, window, and sequence variables has faded. There seem to be enough of those to noticeably decrease the runtime. (N,I%,PV,PMT,FV,P/Y,n).

What is the etiquette around using L1-L6? I know that the A-Z variables are generally considered free to use, but if a user is using the calculator for plotting data a stats class, and a program overwrites the Lists, that doesn't sound great.

Very much looking forward to seeing how this can be golfed and optimized. It's big and slow as it stands.

edit: re: github: It has been approved into the Archives: http://ceme.tech/DL2709
Which pixel on the graph is it drawn from, and what are the dimensions?
The QR code is drawn centered around pixel 31,47, the center of the monochrome screen. Then on the color calcs (CSE, CE, CE Python), it is scaled by 2x and centered on the screen around 80,130.

Version 1 is 21x21 pixels, Version 11 is 61x61 pixels, and each successive version is 4 pixels larger than the previous.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement