'PROGRAM : BIG MULTIPLICATION VER #1
'LRCVS 01.01.2010
'THIS PROGRAM SIMPLY MAKES A MULTIPLICATION
'WITH ALL THE PARTIAL PRODUCTS.
'............................................................

DECLARE SUB A.INICIO (A$, B$)
DECLARE SUB B.STORE (CAD$, N$)
DECLARE SUB C.PIZARRA ()
DECLARE SUB D.ENCABEZADOS (A$, B$)
DECLARE SUB E.MULTIPLICACION (A$, B$)
DECLARE SUB G.SUMA ()
DECLARE FUNCTION F.INVCAD$ (CAD$)

RANDOMIZE TIMER
CALL A.INICIO(A$, B$)
CALL B.STORE(A$, "A")
CALL B.STORE(B$, "B")
CALL C.PIZARRA
CALL D.ENCABEZADOS(A$, B$)
CALL E.MULTIPLICACION(A$, B$)
CALL G.SUMA

SUB A.INICIO (A$, B$)
    CLS
'Note: Number of digits > 1000
    INPUT "NUMBER OF DIGITS  "; S
    CLS
    A$ = ""
    B$ = ""
    FOR N = 1 TO S
        A$ = A$ + LTRIM$(STR$(INT(RND * 9)))
    NEXT N
    FOR N = 1 TO S
        B$ = B$ + LTRIM$(STR$(INT(RND * 9)))
    NEXT N
END SUB

SUB B.STORE (CAD$, N$)
    OPEN "O", #1, N$
    FOR M = LEN(CAD$) TO 1 STEP -1
        WRITE #1, MID$(CAD$, M, 1)
    NEXT M
    CLOSE (1)
END SUB

SUB C.PIZARRA
    OPEN "A", #3, "R"
    WRITE #3, ""
    CLOSE (3)
    KILL "R"
END SUB

SUB D.ENCABEZADOS (A$, B$)
    LT = LEN(A$) + LEN(B$) + 1
    L$ = STRING$(LT, " ")
    OPEN "A", #3, "R"
    MID$(L$, LT - LEN(A$) + 1) = A$
    WRITE #3, L$
    CLOSE (3)
    L$ = STRING$(LT, " ")
    OPEN "A", #3, "R"
    MID$(L$, LT - LEN(B$) - 1) = "X " + B$
    WRITE #3, L$
    CLOSE (3)
END SUB

SUB E.MULTIPLICACION (A$, B$)
    LT = LEN(A$) + LEN(B$) + 1
    L$ = STRING$(LT, " ")
    C$ = ""
    D$ = ""
    E$ = ""
    CT1 = 1
    ACUM = 0
    OPEN "I", #2, "B"
    WHILE EOF(2) <> -1
        INPUT #2, B$
        OPEN "I", #1, "A"
        WHILE EOF(1) <> -1
            INPUT #1, A$
            RP = (VAL(A$) * VAL(B$)) + ACUM
            C$ = LTRIM$(STR$(RP))
            IF EOF(1) <> -1 THEN D$ = D$ + RIGHT$(C$, 1)
            IF EOF(1) = -1 THEN D$ = D$ + F.INVCAD$(C$)
            E$ = LEFT$(C$, LEN(C$) - 1)
            ACUM = VAL(E$)
        WEND
        CLOSE (1)
        MID$(L$, LT - CT1 - LEN(D$) + 2) = F.INVCAD$(D$)
        OPEN "A", #3, "R"
        WRITE #3, L$
        CLOSE (3)
        L$ = STRING$(LT, " ")
        ACUM = 0
        C$ = ""
        D$ = ""
        E$ = ""
        CT1 = CT1 + 1
    WEND
    CLOSE (2)
END SUB

FUNCTION F.INVCAD$ (CAD$)
    LCAD = LEN(CAD$)
    CADTEM$ = ""
    FOR CAD = LCAD TO 1 STEP -1
        CADTEM$ = CADTEM$ + MID$(CAD$, CAD, 1)
    NEXT CAD
    F.INVCAD$ = CADTEM$
END FUNCTION

SUB G.SUMA
    CF = 0
    OPEN "I", #3, "R"
    WHILE EOF(3) <> -1
        INPUT #3, R$
        CF = CF + 1
        AN = LEN(R$)
    WEND
    CF = CF - 2
    CLOSE (3)
    W$ = ""
    ST = 0
    ACUS = 0
    FOR P = 1 TO AN
        K = 0
        OPEN "I", #3, "R"
        WHILE EOF(3) <> -1
            INPUT #3, R$
            K = K + 1
            IF K > 2 THEN ST = ST + VAL(MID$(R$, AN - P + 1, 1))
            IF K > 2 THEN M$ = LTRIM$(STR$(ST + ACUS))
        WEND
        'COLOR 10: LOCATE CF + 3, AN - P + 1: PRINT RIGHT$(M$, 1); : COLOR 7
        W$ = W$ + RIGHT$(M$, 1)
        ACUS = VAL(LEFT$(M$, LEN(M$) - 1))
        CLOSE (3)
        ST = 0
    NEXT P

    OPEN "A", #3, "R"
    WRITE #3, " " + RIGHT$(F.INVCAD(W$), AN - 1)
    CLOSE (3)
    CLS
    PRINT "THE SOLUTION IN THE FILE: R"
END SUB


::Long Multiplication Task from Rosetta Code
::Batch File Implementation

@echo off
call :longmul 18446744073709551616 18446744073709551616 answer
echo(%answer%
exit /b 0

rem The Hellish Procedure
rem Syntax: call :longmul <n1> <n2> <variable to store product>
:longmul
    setlocal enabledelayedexpansion

    rem Define variables
    set "num1=%1"
    set "num2=%2"
    set "limit1=-1"
    set "limit2=-1"
    set "length=0"
    set "prod="

    rem Reverse the digits of each factor
    for %%A in (1,2) do (
        for /l %%B in (0,1,9) do set "num%%A=!num%%A:%%B=%%B !"
        for %%C in (!num%%A!) do ( set /a limit%%A+=1 & set "rev%%A=%%C!rev%%A!" )
    )

    rem Do the multiplication
    for /l %%A in (0,1,%limit1%) do (
        for /l %%B in (0,1,%limit2%) do (
            set /a iter=%%A+%%B
            set /a iternext=iter+1
            set /a iternext2=iter+2

            set /a prev=digit!iter!
            set /a digit!iter!=!rev1:~%%A,1!*!rev2:~%%B,1!

            rem The next line updates the length of "digits"
            if !iternext! gtr !length! set length=!iternext!
            if !iter! lss !length! set /a digit!iter!+=prev

            set /a currdigit=digit!iter!
            if !currDigit! gtr 9 (
                set /a prev=digit!iternext!
                set /a digit!iternext!=currdigit/10
                set /a digit!iter!=currdigit%%10

                rem The next line updates the length of "digits"
                if !iternext2! gtr !length! set length=!iternext2!
                if !iternext! lss !length! set /a digit!iternext!+=prev
            )
        )
    )

    rem Finalize product reversing the digits
    for /l %%F in (0,1,%length%) do set "prod=!digit%%F!!prod!"
    endlocal & set "%3=%prod%"
goto :eof


      INSTALL @lib$+"BB4WMAPMLIB"
      MAPM_DllPath$ = @lib$+"BB4WMAPM.DLL"
      PROCMAPM_Init

      twoto64$ = "18446744073709551616"
      PRINT "2^64 * 2^64 = " ; FNMAPM_Multiply(twoto64$, twoto64$)


#include <stdio.h>
#include <string.h>

/* c = a * b.  Caller is responsible for memory.
   c must not be the same as either a or b. */
void longmulti(const char *a, const char *b, char *c)
{
	int i = 0, j = 0, k = 0, n, carry;
	int la, lb;

	/* either is zero, return "0" */
	if (!strcmp(a, "0") || !strcmp(b, "0")) {
		c[0] = '0', c[1] = '\0';
		return;
	}

	/* see if either a or b is negative */
	if (a[0] == '-') { i = 1; k = !k; }
	if (b[0] == '-') { j = 1; k = !k; }

	/* if yes, prepend minus sign if needed and skip the sign */
	if (i || j) {
		if (k) c[0] = '-';
		longmulti(a + i, b + j, c + k);
		return;
	}

	la = strlen(a);
	lb = strlen(b);
	memset(c, '0', la + lb);
	c[la + lb] = '\0';

#	define I(a) (a - '0')
	for (i = la - 1; i >= 0; i--) {
		for (j = lb - 1, k = i + j + 1, carry = 0; j >= 0; j--, k--) {
			n = I(a[i]) * I(b[j]) + I(c[k]) + carry;
			carry = n / 10;
			c[k] = (n % 10) + '0';
		}
		c[k] += carry;
	}
#	undef I
	if (c[0] == '0') memmove(c, c + 1, la + lb);

	return;
}

int main()
{
	char c[1024];
	longmulti("-18446744073709551616", "-18446744073709551616", c);
	printf("%s\n", c);

	return 0;
}


using System;
using static System.Console;
using BI = System.Numerics.BigInteger;

class Program {

  static decimal mx = 1E28M, hm = 1E14M, a;

  // allows for 56 digit representation, using 28 decimal digits from each decimal
  struct bi { public decimal hi, lo; }

  // sets up for squaring process
  static bi set4sq(decimal a) { bi r; r.hi = Math.Floor(a / hm); r.lo = a % hm; return r; }

  // outputs bi structure as string, optionally inserting commas
  static string toStr(bi a, bool comma = false) {
    string r = a.hi == 0 ? string.Format("{0:0}", a.lo) :
                           string.Format("{0:0}{1:" + new string('0', 28) + "}", a.hi, a.lo);
    if (!comma) return r;  string rc = "";
    for (int i = r.Length - 3; i > 0; i -= 3) rc = "," + r.Substring(i, 3) + rc;
    return r.Substring(0, ((r.Length + 2) % 3) + 1) + rc; }

  // needed because Math.Pow() returns a double
  static decimal Pow_dec(decimal bas, uint exp) {
    if (exp == 0) return 1M; decimal tmp = Pow_dec(bas, exp >> 1); tmp *= tmp;
    if ((exp & 1) == 0) return tmp; return tmp * bas; }

  static void Main(string[] args) {
    for (uint p = 64; p < 95; p += 30) {        // show prescribed output and maximum power of 2 output
      bi x = set4sq(a = Pow_dec(2M, p)), y;     // setup for squaring process
      WriteLine("The square of (2^{0}):                    {1,38:n0}", p, a); BI BS = BI.Pow((BI)a, 2);
      y.lo = x.lo * x.lo; y.hi = x.hi * x.hi;   // square lo and hi parts
      a = x.hi * x.lo * 2M;                     // calculate midterm
      y.hi += Math.Floor(a / hm);               // increment hi part w/ high part of midterm
      y.lo += (a % hm) * hm;                    // increment lo part w/ low part of midterm
      while (y.lo > mx) { y.lo -= mx; y.hi++; } // check for overflow, adjust both parts as needed
      WriteLine(" is {0,75} (which {1} match the BigInteger computation)\n", toStr(y, true),
          BS.ToString() == toStr(y) ? "does" : "fails to"); } }

}


#include <iostream>
#include <sstream>
//--------------------------------------------------------------------------------------------------
typedef long long bigInt;
//--------------------------------------------------------------------------------------------------
using namespace std;
//--------------------------------------------------------------------------------------------------
class number
{
public:
    number()                                { s = "0"; neg = false; }
    number( bigInt a )                      { set( a ); }
    number( string a )                      { set( a ); }
    void set( bigInt a )                    { neg = false; if( a < 0 ) { a = -a; neg = true; } ostringstream o; o << a; s = o.str(); clearStr(); }
    void set( string a )                    { neg = false; s = a; if( s.length() > 1 && s[0] == '-' ) { neg = true; } clearStr(); }
    number operator *  ( const number& b )  { return this->mul( b ); }
    number& operator *= ( const number& b ) { *this = *this * b; return *this; }
    number& operator = ( const number& b )  { s = b.s; return *this; }
    friend ostream& operator << ( ostream& out, const number& a ) { if( a.neg ) out << "-"; out << a.s; return out; }
    friend istream& operator >> ( istream& in, number& a ){ string b; in >> b; a.set( b ); return in; }

private:
    number mul( const number& b )
    {
	number a; bool neg = false;
	string r, bs = b.s; r.resize( 2 * max( b.s.length(), s.length() ), '0' );
	int xx, ss, rr, t, c, stp = 0;
	string::reverse_iterator xi = bs.rbegin(), si, ri;
	for( ; xi != bs.rend(); xi++ )
	{
	    c = 0; ri = r.rbegin() + stp;
	    for( si = s.rbegin(); si != s.rend(); si++ )
	    {
		xx = ( *xi ) - 48; ss = ( *si ) - 48; rr = ( *ri ) - 48;
		ss = ss * xx + rr + c; t = ss % 10; c = ( ss - t ) / 10;
		( *ri++ ) = t + 48;
	    }
	    if( c > 0 ) ( *ri ) = c + 48;
	    stp++;
	}
	trimLeft( r ); t = b.neg ? 1 : 0; t += neg ? 1 : 0;
	if( t & 1 ) a.s = "-" + r;
	else a.s = r;
	return a;
    }

    void trimLeft( string& r )
    {
	if( r.length() < 2 ) return;
	for( string::iterator x = r.begin(); x != ( r.end() - 1 ); )
	{
	    if( ( *x ) != '0' ) return;
	    x = r.erase( x );
	}
    }

    void clearStr()
    {
	for( string::iterator x = s.begin(); x != s.end(); )
	{
	    if( ( *x ) < '0' || ( *x ) > '9' ) x = s.erase( x );
	    else x++;
	}
    }
    string s;
    bool neg;
};
//--------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    number a, b;
    a.set( "18446744073709551616" ); b.set( "18446744073709551616" );
    cout << a * b << endl << endl;

    cout << "Factor 1 = "; cin >> a;
    cout << "Factor 2 = "; cin >> b;
    cout << "Product: = " << a * b << endl << endl;
    return system( "pause" );
}
//--------------------------------------------------------------------------------------------------


"run() is the main function of this module."

shared void run() {

    function multiply(String|Integer|Integer[] top, String|Integer|Integer[] bottom, Integer base = 10) {

        function fromString(String s) =>
                s
                .filter(not(','.equals))
                .map((char) => Integer.parse(char.string))
                .narrow<Integer>()
                .sequence()
                .reversed;

        function toString(Integer[] ints) =>
                ""
                .join(ints.interpose(',', 3))
                .reversed
                .trimLeading((char) => char in "0,");

        function fromInteger(Integer int) => fromString(int.string);

        function convertArg(String|Integer|Integer[] arg) =>
                switch(arg)
                case (is String) fromString(arg)
                case (is Integer) fromInteger(arg)
                case (is Integer[]) arg;

        value a = convertArg(top);
        value b = convertArg(bottom);

        value p = a.size;
        value q = b.size;
        value product = Array.ofSize(p + q, 0);

        for (bIndex->bDigit in b.indexed) {
            variable value carry = 0;
            for (aIndex->aDigit in a.indexed) {
                assert (exists prodDigit = product[aIndex + bIndex]);
                value temp =  prodDigit + carry + aDigit * bDigit;
                carry = temp / base;
                product[aIndex + bIndex] = temp % base;
            }
            assert (exists lastDigit = product[bIndex + p]);
            product[bIndex + p] = lastDigit + carry;
        }

        return toString(product.sequence());
    }

    value twoToThe64th = "18,446,744,073,709,551,616";
    value expectedResult = "340,282,366,920,938,463,463,374,607,431,768,211,456";
    value result = multiply(twoToThe64th, twoToThe64th);

    print("The expected result is ``expectedResult``");
    print("The actual result is   ``result``");
    print("Do they match? ``expectedResult == result then "Yes!" else "No!"``");
}


       identification division.
       program-id. long-mul.
       data division.
       replace ==ij-lim== by ==7== ==ir-lim== by ==14==.
       working-storage section.
       1 input-string pic x(26) value "18,446,744,073,709,551,616".
       1 a-table.
        2 a pic 999 occurs ij-lim.
       1 b-table.
        2 b pic 999 occurs ij-lim.
       1 ir-table value all "0".
        2 occurs ij-lim.
         3 ir pic 999 occurs ir-lim.
       1 s-table value all "0".
        2 s pic 999 occurs ir-lim.
       1 display.
        2 temp-result pic 9(6) value 0.
        2 carry pic 999 value 0.
        2 remain pic 999 value 0.
       1 binary.
        2 i pic 9(4) value 0.
        2 j pic 9(4) value 0.
        2 k pic 9(4) value 0.
       procedure division.
       begin.
           move 1 to j
           perform varying i from 1 by 1 until i > ij-lim
               unstring input-string delimited ","
                   into a (i) with pointer j
           end-perform
           move a-table to b-table
           perform intermediate-calc
           perform sum-ir
           perform display-result
       stop run
       .

       intermediate-calc.
           perform varying i from ij-lim by -1 until i < 1
               move 0 to carry
               perform varying j from ij-lim by -1 until j < 1
                   compute temp-result = a (i) * b (j) + carry
                   divide temp-result by 1000 giving carry
                       remainder remain
                   compute k = i + j
                   move remain to ir (i k)
               end-perform
               subtract 1 from k
               move carry to ir (i k)
           end-perform
           .

       sum-ir.
           move 0 to carry
           perform varying k from ir-lim by -1 until k < 1
               move carry to temp-result
               perform varying i from ij-lim by -1 until i < 1
                   compute temp-result = temp-result + ir (i k)
               end-perform
               divide temp-result by 1000 giving carry
                   remainder remain
               move remain to s (k)
           end-perform
           .

       display-result.
           display "   " input-string
           display " * " input-string
           display " = " with no advancing
           perform varying k from 1 by 1
           until k > ir-lim or s (k) not = 0
           end-perform
           if s (k) < 100
               move 1 to i
               inspect s (k) tallying i for leading "0"
               display s (k) (i:) "," with no advancing
               add 1 to k
           end-if
           perform varying k from k by 1 until k > ir-lim
               display s (k) with no advancing
               if k < ir-lim
                   display "," with no advancing
               end-if
           end-perform
           display space
           .

       end program long-mul.


# This very limited BCD-based collection of functions
# allows for long multiplication.  It works for positive
# numbers only.  The assumed data structure is as follows:
# BcdInteger.from_integer(4321) == [1, 2, 3, 4]

BcdInteger =
  from_string: (s) ->
    arr = []
    for c in s
      arr.unshift parseInt(c)
    arr

  from_integer: (n) ->
    result = []
    while n > 0
      result.push n % 10
      n = Math.floor n / 10
    result

  to_string: (arr) ->
    s = ''
    for elem in arr
      s = elem.toString() + s
    s

  sum: (arr1, arr2) ->
    if arr1.length < arr2.length
      return BcdInteger.sum(arr2, arr1)
    carry = 0
    result= []
    for d1, pos in arr1
      d = d1 + (arr2[pos] || 0) + carry
      result.push d % 10
      carry = Math.floor d / 10
    if carry
      result.push 1
    result

  multiply_by_power_of_ten: (arr, power_of_ten) ->
    result = (0 for i in [0...power_of_ten])
    result.concat arr

  product_by_integer: (arr, n) ->
    result = []
    for digit, i in arr
      prod = BcdInteger.from_integer n * digit
      prod = BcdInteger.multiply_by_power_of_ten prod, i
      result = BcdInteger.sum result, prod
    result

  product: (arr1, arr2) ->
    result = []
    for digit, i in arr1
      prod = BcdInteger.product_by_integer arr2, digit
      prod = BcdInteger.multiply_by_power_of_ten prod, i
      result = BcdInteger.sum result, prod
    result

x = BcdInteger.from_integer 1
for i in [1..64]
  x = BcdInteger.product_by_integer x, 2
console.log BcdInteger.to_string x #   18446744073709551616
square = BcdInteger.product x, x
console.log BcdInteger.to_string square # 340282366920938463463374607431768211456


(defun number->digits (number)
  (do ((digits '())) ((zerop number) digits)
    (multiple-value-bind (quotient remainder) (floor number 10)
      (setf number quotient)
      (push remainder digits))))

(defun digits->number (digits)
  (reduce #'(lambda (n d) (+ (* 10 n) d)) digits :initial-value 0))

(defun long-multiply (a b)
  (labels ((first-digit (list)
             "0 if list is empty, else first element of list."
             (if (endp list) 0
               (first list)))
           (long-add (digitses &optional (carry 0) (sum '()))
             "Do long addition on the list of lists of digits.  Each
              list of digits in digitses should begin with the least
              significant digit.  This is the opposite of the digit
              list returned by number->digits which places the most
              significant digit first.  The digits returned by
              long-add do have the most significant bit first."
             (if (every 'endp digitses)
               (nconc (number->digits carry) sum)
               (let ((column-sum (reduce '+ (mapcar #'first-digit digitses)
                                         :initial-value carry)))
                 (multiple-value-bind (carry column-digit)
                     (floor column-sum 10)
                   (long-add (mapcar 'rest digitses)
                             carry (list* column-digit sum)))))))
    ;; get the digits of a and b (least significant bit first), and
    ;; compute the zero padded rows. Then, add these rows (using
    ;; long-add) and convert the digits back to a number.
    (do ((a (nreverse (number->digits a)))
         (b (nreverse (number->digits b)))
         (prefix '() (list* 0 prefix))
         (rows '()))
        ((endp b) (digits->number (long-add rows)))
      (let* ((bi (pop b))
             (row (mapcar #'(lambda (ai) (* ai bi)) a)))
        (push (append prefix row) rows)))))


require "big"

a = 2.to_big_i ** 64

puts "#{a} * #{a} = #{a*a}"


void main() {
    import std.stdio, std.bigint;

    writeln(2.BigInt ^^ 64 * 2.BigInt ^^ 64);
}


program Long_multiplication;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TLongMul = record
  private
    function Add(x, y: TArray<byte>): TArray<byte>;
    function ByteToString(b: TArray<byte>): Ansistring;
    function d(b: byte): Byte;
    function mulDigit(x: TArray<byte>; y: byte): TArray<byte>;
    function mul(x1, y1: AnsiString): AnsiString;
  public
    value: string;
    class operator Multiply(a, b: TLongMul): TLongMul;
    class operator Implicit(a: TLongMul): string;
    class operator Implicit(a: string): TLongMul;
  end;

function TLongMul.d(b: byte): Byte;
begin
  if (b < ord('0')) or (b > ord('9')) then
    raise Exception.Create('digit 0-9 expected: ' + ord(b).ToString);
  Result := ord(b) - ord('0');
end;

class operator TLongMul.Implicit(a: string): TLongMul;
begin
  Result.value := a;
end;

class operator TLongMul.Implicit(a: TLongMul): string;
begin
  Result := a.value;
end;

function TLongMul.Add(x, y: TArray<byte>): TArray<byte>;
begin
  if length(x) < Length(y) then
  begin
    var tmp := y;
    y := x;
    x := tmp;
  end;

  var b: TArray<byte>;
  SetLength(b, length(x) + 1);
  var c: byte := 0;
  for var i := 1 to Length(x) do
  begin
    if i <= Length(y) then
      c := c + d(y[Length(y) - i]);
    var s := d(x[Length(x) - i]) + c;
    c := s div 10;
    b[length(b) - i] := (s mod 10) + ord('0');
  end;
  if c = 0 then
  begin
    Result := b;
    Delete(Result, 0, 1);
    exit;
  end;

  b[0] := c + ord('0');
  Result := b;
end;

function TLongMul.mulDigit(x: TArray<byte>; y: byte): TArray<byte>;
begin
  if y = ord('0') then
  begin
    SetLength(result, 1);
    Result[0] := y;
    exit
  end;

  y := d(y);
  var b: TArray<byte>;
  SetLength(b, length(x) + 1);
  var c: byte := 0;
  for var i := 1 to Length(x) do
  begin
    var s := d(x[Length(x) - i]) * y + c;
    c := s div 10;
    b[length(b) - i] := (s mod 10) + ord('0');
  end;

  if c = 0 then
  begin
    Result := b;
    Delete(Result, 0, 1);
    exit;
  end;

  b[0] := c + ord('0');
  Result := b;
end;

class operator TLongMul.Multiply(a, b: TLongMul): TLongMul;
begin
  Result.value := a.mul(a, b);
end;

function TLongMul.ByteToString(b: TArray<byte>): Ansistring;
begin
  SetLength(Result, length(b));
  move(b[0], Result[1], length(b));
end;

function TLongMul.mul(x1, y1: AnsiString): AnsiString;
var
  x, y: TArray<byte>;
  res: TArray<byte>;
begin
  SetLength(x, length(x1));
  move(x1[1], x[0], length(x1));

  SetLength(y, length(y1));
  move(y1[1], y[0], length(y1));

  res := mulDigit(x, y[length(y) - 1]);

  var zeros: TArray<byte> := [];

  for var i := 2 to Length(y) do
  begin
    SetLength(zeros, Length(zeros) + 1);
    zeros[High(zeros)] := ord('0');

    res := add(res, Concat(mulDigit(x, y[Length(y) - i]), zeros));
  end;

  Result := ByteToString(res);
end;

const
  validate = '340282366920938463463374607431768211456';

var
  num: TLongMul;

begin
  num.value := '18446744073709551616';

  Writeln((num * num).value);
  Writeln(validate);
  Readln;
end.


(lib 'math) ;; for poly multiplication

;; convert string of decimal digits to polynomial
;; "1234" → x^3 +2x^2 +3x +4
;; least-significant digit first
(define (string->long N)
	(reverse (map string->number (string->list N))))

;; convert polynomial to string
(define (long->string N)
(if (pair? N)
   (string-append (number->string (first N)) (long->string (rest N)))  ""))

;; convert poly coefficients to base 10
(define (poly->10 P (carry 0))
(append
	(for/list ((coeff P))
		(set! coeff (+ carry coeff ))
		(set! carry (quotient coeff 10)) ;; new carry
		(modulo coeff 10))
	(if(zero? carry) null (list carry)))) ;; remove leading 0 if any

;; long multiplication
;; convert input - strings of decimal digits - to polynomials
;; perform poly multiplication in base 10
;; convert result to string of decimal digits

(define (long-mul A B )
 (long->string (reverse  (poly->10 (poly-mul (string->long A) (string->long B))))))

(define two-64 "18446744073709551616")
(long-mul two-64 two-64)
    → "340282366920938463463374607431768211456"

;; check it
(lib 'bigint)
Lib: bigint.lib loaded.
(expt 2 128)
   → 340282366920938463463374607431768211456


constant base = 1000000000

function atom_to_long(atom a)
    sequence s
    s = {}
    while a>0 do
        s = append(s,remainder(a,base))
        a = floor(a/base)
    end while
    return s
end function

function long_mult(object a, object b)
    sequence c
    if atom(a) then
        a = atom_to_long(a)
    end if
    if atom(b) then
        b = atom_to_long(b)
    end if
    c = repeat(0,length(a)+length(b))
    for i = 1 to length(a) do
        c[i .. i+length(b)-1] += a[i]*b
    end for

    for i = 1 to length(c) do
        if c[i] > base then
            c[i+1] += floor(c[i]/base) -- carry
            c[i] = remainder(c[i],base)
        end if
    end for

    if c[$] = 0 then
        c = c[1..$-1]
    end if
    return c
end function

function long_to_str(sequence a)
    sequence s
    s = sprintf("%d",a[$])
    for i = length(a)-1 to 1 by -1 do
        s &= sprintf("%09d",a[i])
    end for
    return s
end function

sequence a, b, c

a = atom_to_long(power(2,32))
printf(1,"a is %s\n",{long_to_str(a)})

b = long_mult(a,a)
printf(1,"a*a is %s\n",{long_to_str(b)})

c = long_mult(b,b)
printf(1,"a*a*a*a is %s\n",{long_to_str(c)})


USING: kernel math sequences ;

: longmult-seq ( xs ys -- zs )
[ * ] cartesian-map
dup length iota [ 0 <repetition> ] map
[ prepend ] 2map
[ ] [ [ 0 suffix ] dip [ + ] 2map ] map-reduce ;

: integer->digits ( x -- xs )  { } swap  [ dup 0 > ] [ 10 /mod swap [ prefix ] dip ] while  drop ;
: digits->integer ( xs -- x )  0 [ swap 10 * + ] reduce ;

: longmult ( x y -- z )  [ integer->digits ] [email protected] longmult-seq digits->integer ;


module LongMoltiplication
  implicit none

  type longnum
     integer, dimension(:), pointer :: num
  end type longnum

  interface operator (*)
     module procedure longmolt_ll
  end interface

contains

  subroutine longmolt_s2l(istring, num)
    character(len=*), intent(in) :: istring
    type(longnum), intent(out) :: num

    integer :: i, l

    l = len(istring)

    allocate(num%num(l))

    forall(i=1:l) num%num(l-i+1) = iachar(istring(i:i)) - 48

  end subroutine longmolt_s2l

  ! this one performs the moltiplication
  function longmolt_ll(a, b) result(c)
    type(longnum) :: c
    type(longnum), intent(in) :: a, b

    integer, dimension(:,:), allocatable :: t
    integer :: ntlen, i, j

    ntlen = size(a%num) + size(b%num) + 1
    allocate(c%num(ntlen))
    c%num = 0

    allocate(t(size(b%num), ntlen))

    t = 0
    forall(i=1:size(b%num), j=1:size(a%num)) t(i, j+i-1) = b%num(i) * a%num(j)

    do j=2, ntlen
       forall(i=1:size(b%num)) t(i, j) = t(i, j) + t(i, j-1)/10
    end do

    forall(j=1:ntlen) c%num(j) = sum(mod(t(:,j), 10))

    do j=2, ntlen
       c%num(j) = c%num(j) + c%num(j-1)/10
    end do

    c%num = mod(c%num, 10)

    deallocate(t)
  end function longmolt_ll

  subroutine longmolt_print(num)
    type(longnum), intent(in) :: num

    integer :: i, j

    do j=size(num%num), 2, -1
       if ( num%num(j) /= 0 ) exit
    end do

    do i=j, 1, -1
       write(*,"(I1)", advance="no") num%num(i)
    end do
  end subroutine longmolt_print

end module LongMoltiplication


' version 08-01-2017
' compile with: fbc -s console

Const As UInteger base_ = 1000000000 ' base 1,000,000,000

Function multiply(a1 As String, b1 As String) As String

    Dim As String a = a1, b = b1

    Trim(a) : Trim(b) ' remove spaces
    If Len(a) = 0 Or Len(b) = 0 Then Return "0"

    If Len(a) + Len(b) > 10000 Then
        Print "number(s) are to big"
        Sleep 5000,1
        Return ""
    End If

    If Len(a) < Len(b) Then
        Swap a, b
    End If

    Dim As ULongInt product
    Dim As UInteger carry, i, m, shift
    Dim As UInteger la = Len(a), lb = Len(b)
    Dim As UInteger la9 = la \ 9 + IIf((la Mod 9) = 0, 0, 1)
    Dim As UInteger lb9 = lb \ 9 + IIf((lb Mod 9) = 0, 0, 1)
    Dim As UInteger arr_a(la9), answer((la9 + lb9) + 2)
    Dim As Integer last = la9

    ' make length a, b a multipy of 9
    a = Right((String(9, "0") + a), la9 * 9)
    b = Right((String(9, "0") + b), lb9 * 9)

    For i = 1 To la9
        arr_a(la9 - i +1) = Val(Mid(a, i * 9 -8, 9))
    Next

    Do
        carry = 0
        m = Val(Mid(b, lb9 * 9 -8, 9))
        For i = 1 To la9
            product = CULngInt(arr_a(i)) * m + answer(i + shift) + carry
            carry = product \ base_
            answer(i + shift) = product - carry * base_
        Next
        If carry <> 0 Then
            last = la9 + shift +1
            answer(last) = carry
        End If
        lb9 = lb9 -1
        shift = shift +1
    Loop Until lb9 = 0

    Dim As String tmp = Str(answer(last))
    last = last -1
    While last > 0
        tmp = tmp + Right(String(9,"0") + Str(answer(last)), 9)
        last = last -1
    Wend

    Return tmp

End Function

' ------=< MAIN >=------

Dim As String a = "2", b = "2", answer
Dim As UInteger i = 1, j

For j = 1 To 7
    answer = multiply(a, b)
    a = answer
    b = answer
    i = i + i
    Print using "2 ^ ### = "; i;
    Print answer
Next

Print
Print "-------------------------------------------------"
Print

a = "2" : b = "1" : answer = ""
For j = 1 To 128
    answer = multiply(a, b)
    b = answer
Next
Print "2 ^ 128 = "; answer

' empty keyboard buffer
While InKey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End


// Long multiplication per WP article referenced by task description.
// That is, multiplicand is multiplied by single digits of multiplier
// to form intermediate results.  Intermediate results are accumulated
// for the product.  Used here is the abacus method mentioned by the
// article, of summing intermediate results as they are produced,
// rather than all at once at the end.
//
// Limitations:  Negative numbers not supported, superfluous leading zeros
// not generally removed.
package main

import "fmt"

// argument validation
func d(b byte) byte {
    if b < '0' || b > '9' {
        panic("digit 0-9 expected")
    }
    return b - '0'
}

// add two numbers as strings
func add(x, y string) string {
    if len(y) > len(x) {
        x, y = y, x
    }
    b := make([]byte, len(x)+1)
    var c byte
    for i := 1; i <= len(x); i++ {
        if i <= len(y) {
            c += d(y[len(y)-i])
        }
        s := d(x[len(x)-i]) + c
        c = s / 10
        b[len(b)-i] = (s % 10) + '0'
    }
    if c == 0 {
        return string(b[1:])
    }
    b[0] = c + '0'
    return string(b)
}

// multipy a number by a single digit
func mulDigit(x string, y byte) string {
    if y == '0' {
        return "0"
    }
    y = d(y)
    b := make([]byte, len(x)+1)
    var c byte
    for i := 1; i <= len(x); i++ {
        s := d(x[len(x)-i])*y + c
        c = s / 10
        b[len(b)-i] = (s % 10) + '0'
    }
    if c == 0 {
        return string(b[1:])
    }
    b[0] = c + '0'
    return string(b)
}

// multiply two numbers as strings
func mul(x, y string) string {
    result := mulDigit(x, y[len(y)-1])
    for i, zeros := 2, ""; i <= len(y); i++ {
        zeros += "0"
        result = add(result, mulDigit(x, y[len(y)-i])+zeros)
    }
    return result
}

// requested output
const n = "18446744073709551616"

func main() {
    fmt.Println(mul(n, n))
}


import Data.List (transpose, inits)
import Data.Char (digitToInt)

longmult :: Integer -> Integer -> Integer
longmult x y = foldl1 ((+) . (10 *)) (polymul (digits x) (digits y))

polymul :: [Integer] -> [Integer] -> [Integer]
polymul xs ys =
  sum <$>
  transpose
    (zipWith
       (<>)
       (inits $ repeat 0)
       ((\f x -> fmap ((<$> x) . f)) (*) xs ys))

digits :: Integer -> [Integer]
digits = fmap (fromIntegral . digitToInt) . show

main :: IO ()
main = print $ (2 ^ 64) `longmult` (2 ^ 64)


procedure main()
   write(2^64*2^64)
end


   digits      =: ,.&.":
   polymult    =: +//[email protected](*/)
   buildDecimal=: 10x&#.

   longmult=: [email protected]&digits


public class LongMult {

	private static byte[] stringToDigits(String num) {
		byte[] result = new byte[num.length()];
		for (int i = 0; i < num.length(); i++) {
			char c = num.charAt(i);
			if (c < '0' || c > '9') {
				throw new IllegalArgumentException("Invalid digit " + c
						+ " found at position " + i);
			}
			result[num.length() - 1 - i] = (byte) (c - '0');
		}
		return result;
	}

	public static String longMult(String num1, String num2) {
		byte[] left = stringToDigits(num1);
		byte[] right = stringToDigits(num2);
		byte[] result = new byte[left.length + right.length];
		for (int rightPos = 0; rightPos < right.length; rightPos++) {
			byte rightDigit = right[rightPos];
			byte temp = 0;
			for (int leftPos = 0; leftPos < left.length; leftPos++) {
				temp += result[leftPos + rightPos];
				temp += rightDigit * left[leftPos];
				result[leftPos + rightPos] = (byte) (temp % 10);
				temp /= 10;
			}
			int destPos = rightPos + left.length;
			while (temp != 0) {
				temp += result[destPos] & 0xFFFFFFFFL;
				result[destPos] = (byte) (temp % 10);
				temp /= 10;
				destPos++;
			}
		}
		StringBuilder stringResultBuilder = new StringBuilder(result.length);
		for (int i = result.length - 1; i >= 0; i--) {
			byte digit = result[i];
			if (digit != 0 || stringResultBuilder.length() > 0) {
				stringResultBuilder.append((char) (digit + '0'));
			}
		}
		return stringResultBuilder.toString();
	}

	public static void main(String[] args) {
		System.out.println(longMult("18446744073709551616",
				"18446744073709551616"));
	}
}


function mult(strNum1,strNum2){

    var a1 = strNum1.split("").reverse();
    var a2 = strNum2.toString().split("").reverse();
    var aResult = new Array;

    for ( var iterNum1 = 0; iterNum1 < a1.length; iterNum1++ ) {
        for ( var iterNum2 = 0; iterNum2 < a2.length; iterNum2++ ) {
            var idxIter = iterNum1 + iterNum2;    // Get the current array position.
            aResult[idxIter] = a1[iterNum1] * a2[iterNum2] + ( idxIter >= aResult.length ? 0 : aResult[idxIter] );

            if ( aResult[idxIter] > 9 ) {    // Carrying
                aResult[idxIter + 1] = Math.floor( aResult[idxIter] / 10 ) + ( idxIter + 1 >= aResult.length ? 0 : aResult[idxIter + 1] );
                aResult[idxIter] %= 10;
            }
        }
    }
    return aResult.reverse().join("");
}

mult('18446744073709551616', '18446744073709551616')


# multiply two decimal strings, which may be signed (+ or -)
def long_multiply(num1; num2):

   def stripsign:
     .[0:1] as $a
     | if $a == "-" then [ -1, .[1:]]
     elif $a == "+" then [  1, .[1:]]
     else [1, .]
     end;

  def adjustsign(sign):
     if sign == 1 then . else "-" + . end;

  # mult/2 assumes neither argument has a sign
  def mult(num1;num2):
      (num1 | explode | map(.-48) | reverse) as $a1
    | (num2 | explode | map(.-48) | reverse) as $a2
    | reduce range(0; num1|length) as $i1
        ([];  # result
         reduce range(0; num2|length) as $i2 (.;
  	  ($i1 + $i2) as $ix
  	  | ( $a1[$i1] * $a2[$i2] +
                (if $ix >= length then 0
                 else .[$ix]
                 end) ) as $r
            | if $r > 9 # carrying
              then
                .[$ix + 1] = ($r / 10 | floor) +
                   (if $ix + 1 >= length then 0
                    else .[$ix + 1]
                    end)
                | .[$ix] = $r - ( $r / 10 | floor ) * 10
              else
                .[$ix] = $r
              end
         )
       )
    | reverse | map(.+48) | implode;

     (num1|stripsign) as $a1
   | (num2|stripsign) as $a2
   | if $a1[1] == "0" or  $a2[1] == "0" then "0"
     elif $a1[1] == "1" then $a2[1]|adjustsign( $a1[0] * $a2[0] )
     elif $a2[1] == "1" then $a1[1]|adjustsign( $a1[0] * $a2[0] )
     else mult($a1[1]; $a2[1]) | adjustsign( $a1[0] * $a2[0] )
     end;


module LongMultiplication

using Compat

function addwithcarry!(r, addend, addendpos)
    while true
        pad = max(0, addendpos - lastindex(r))
        append!(r, fill(0, pad))
        addendrst = addend + r[addendpos]
        addend, r[addendpos] = divrem(addendrst, 10)
        iszero(addend) && break
        addendpos += 1
    end
    return r
end

function longmult(mult1::AbstractVector{T}, mult2::AbstractVector{T}) where T <: Integer
    r = T[]
    for (offset1, digit1) in enumerate(mult1), (offset2, digit2) in zip(eachindex(mult2) + offset1 - 1, mult2)
        single_multrst = digits(digit1 * digit2)
        for (addoffset, rstdigit) in zip(eachindex(single_multrst) + offset2 - 1, single_multrst)
            addwithcarry!(r, rstdigit, addoffset)
        end
    end
    return r
end

function longmult(a::T, b::T)::T where T <: Integer
    mult1 = digits(a)
    mult2 = digits(b)
    r = longmult(mult1, mult2)
    return sum(d * T(10) ^ (e - 1) for (e, d) in enumerate(r))
end

function longmult(a::AbstractString, b::AbstractString)
    if !ismatch(r"^\d+", a) || !ismatch(r"^\d+", b)
        throw(ArgumentError("string must contain only digits"))
    end
    mult1 = reverse(collect(Char, a) .- '0')
    mult2 = reverse(collect(Char, b) .- '0')
    r = longmult(mult1, mult2)
    return reverse(join(r))
end

end  # module LongMultiplication


fun String.toDigits() = mapIndexed { i, c ->
    if (!c.isDigit())
        throw IllegalArgumentException("Invalid digit $c found at position $i")
    c - '0'
}.reversed()

operator fun String.times(n: String): String {
    val left = toDigits()
    val right = n.toDigits()
    val result = IntArray(left.size + right.size)

    right.mapIndexed { rightPos, rightDigit ->
        var tmp = 0
        left.indices.forEach { leftPos ->
            tmp += result[leftPos + rightPos] + rightDigit * left[leftPos]
            result[leftPos + rightPos] = tmp % 10
            tmp /= 10
        }
        var destPos = rightPos + left.size
        while (tmp != 0) {
            tmp += (result[destPos].toLong() and 0xFFFFFFFFL).toInt()
            result[destPos] = tmp % 10
            tmp /= 10
            destPos++
        }
    }

    return result.foldRight(StringBuilder(result.size), { digit, sb ->
        if (digit != 0 || sb.length > 0) sb.append('0' + digit)
        sb
    }).toString()
}

fun main(args: Array<out String>) {
    println("18446744073709551616" * "18446744073709551616")
}


Natural positive numbers are defined as strings, for instance 123 -> "123".
{lambda talk} has a small set of primitives working on strings, [equal?, empty?, chars, charAt, substring]

1) helper functions

{def lastchar
 {lambda {:w}
  {charAt {- {chars :w} 1} :w}
}}
{def butlast
 {lambda {:w}
  {substring 0 {- {chars :w} 1} :w}
}}
{def zeros
 {lambda {:n}
  {if {< :n 1}
   then
   else 0{zeros {- :n 1}}
}}}

2) add function

{def add
 {def add.r
 {lambda {:a :b :c :d}
  {if {equal? :a #}
   then {if {equal? :d 1} then 1 else}{butlast :c}
   else {let { {:a :a} {:b :b} {:c :c}
               {:d {+ :d {lastchar :a} {lastchar :b} }} }
    {add.r {butlast :a} {butlast :b} {lastchar :d}:c
         {if {equal? {chars :d} 1} then 0 else 1}}
 }}}}
 {lambda {:a :b}
  {{lambda {:a :b :n}
    {add.r #{zeros {- :n {chars :a}}}:a
           #{zeros {- :n {chars :b}}}:b  # 0}
  } :a :b {max {chars :a} {chars :b}}}
}}

3) mul function

{def mul
 {def muln
  {lambda {:a :b :n}
   {if {< :n 1}
    then :b
    else {muln :a {add :a :b} {- :n 1}}
 }}}
 {def mul.r
  {lambda {:a :b :c :n}
   {if {equal? :b #}
    then :c
    else {mul.r :a {butlast :b}
         {add {muln :a 0 {lastchar :b}}{zeros :n} :c} {+ :n 1}}
 }}}
 {lambda {:a :b}
  {mul.r :a #:b 0 0}
}}

4) applying to the task

Due to JS numbers limits, we compute first 2^32 using the JS pow function, then 2^64 and 2^128 using the mul function.

2^32 = '{def p32 {pow 2 32}}          -> '{p32}  = 4294967296
2^64 = '{def p64 {mul {p32} {p32}}}   -> '{p64}  = 18446744073709551616
2^128 = '{def p128 {mul {p64} {p64}}} -> '{p128} = 340282366920938463463374607431768211456

5) a more effective implementation

Lambdatalk can be helped by the lib_BN javascript library from Jonas Raoni Soares Silva
and stored in a wiki page called by a {require lib_BN} command, computing becomes fast:

2^32 = {def p32 {BN.pow 2 32}}        -> {p32}  = 4294967296
2^64 = {def p64 {BN.* {p32} {p32}}}   -> {p64}  = 18446744073709551616
2^128 = {def p128 {BN.* {p64} {p64}}} -> {p128} = 340282366920938463463374607431768211456

This can be tested in http://lambdaway.free.fr/lambdaspeech/?view=numbers8


'[RC] long multiplication

'now, count 2^64
print "2^64"
a$="1"
for i = 1 to 64
    a$ = multByD$(a$, 2)
next
print a$
print "(check with native LB)"
print 2^64
print "(looks OK)"

'now let's do b$*a$ stuff
print
print "2^64*2^64"
print longMult$(a$, a$)
print "(check with native LB)"
print 2^64*2^64
print "(looks OK)"

end
'---------------------------------------
function longMult$(a$, b$)
    signA = 1
    if left$(a$,1) = "-" then a$ = mid$(a$,2): signA = -1
    signB = 1
    if left$(b$,1) = "-" then b$ = mid$(b$,2): signB = -1

    c$ = ""
    t$ = ""
    shift$ = ""
    for i = len(a$) to 1 step -1
        d = val(mid$(a$,i,1))
        t$ = multByD$(b$, d)
        c$ = addLong$(c$, t$+shift$)
        shift$ = shift$ +"0"
    'print d, t$, c$
    next
    if signA*signB<0 then c$ = "-" + c$
    'print c$
    longMult$ = c$
end function

function multByD$(a$, d)
'multiply a$ by digit d
c$ = ""
carry = 0
for i = len(a$) to 1 step -1
        a = val(mid$(a$,i,1))
        c = a*d+carry
        carry = int(c/10)
        c = c mod 10
        'print a, c
        c$ = str$(c)+c$
next
    if carry>0 then c$ = str$(carry)+c$
    'print c$
    multByD$ = c$
end function

function addLong$(a$, b$)
'add a$ + b$, for now only positive
    l = max(len(a$), len(b$))
    a$=pad$(a$,l)
    b$=pad$(b$,l)
    c$ = "" 'result
    carry = 0
    for i = l to 1 step -1
        a = val(mid$(a$,i,1))
        b = val(mid$(b$,i,1))
        c = a+b+carry
        carry = int(c/10)
        c = c mod 10
        'print a, b, c
        c$ = str$(c)+c$
    next
    if carry>0 then c$ = str$(carry)+c$
    'print c$
    addLong$ = c$
end function

function pad$(a$,n)  'pad from right with 0 to length n
     pad$ = a$
     while len(pad$)<n
        pad$ = "0"+pad$
     wend
end function


import std

// Very basic arbitrary-precision integers
// - only non-negative numbers
// - doesn't implement any arithmetic not necessary for the task at hand...

let base = 1000000000

class Bign:
    digits: [int] // little endian, of base base
    digitsUsed: int

    def clone():
        return Bign { digits: copy(digits), digitsUsed: digitsUsed }

    def resize(newLength):
        while digits.length < newLength:
            digits.push(0)

    def adjustDigitsUsed():
        while digitsUsed > 0 and digits[digitsUsed - 1] == 0:
                digitsUsed -= 1

    // multiplication by one digit; used to convert string to Bign
    def muldigit(multiplier : int):
        if (multiplier < 0):
            return // "Signed arithmetic isn't supported"
        resize(digitsUsed + 1)
        var temp = 0
        for(digitsUsed) i:
            temp += digits[i] * multiplier
            digits[i] = temp % base
            temp /= base
        digits[digitsUsed] = temp
        digitsUsed += 1
        adjustDigitsUsed()

    // addition of one digit; used to convert string to Bign
    def adddigit(addend: int):
        if (addend < 0):
            return // "Signed arithmetic isn't supported"
        var temp = addend
        var i = 0
        while i < digitsUsed and temp != 0:
            temp += digits[i]
            digits[i] = temp % base
            temp /= base
            i += 1
        if temp != 0:
            resize(digitsUsed + 1)
            digits[digitsUsed] = temp
            digitsUsed += 1

    def bign2str():
        var i = digitsUsed
        if i == 0:
            return "0"
        i -= 1
        var s = string(digits[i])
        while i > 0:
            i -= 1
            s += number_to_string(digits[i], 10, 9)
        return s

def str2bign(value):
    // each of our Bign digits can store 9 decimal digits
    let this = Bign { digits: map(value.length() / 9 + 1): 0, digitsUsed: 0 }
    // handle nine digits at a time
    var i = 0
    while i < value.length:
        var multiplier = 1
        var addend = 0
        for(min(9, value.length() - i)) j:
            let c = value[i+j]
            //if (c < '0' or c > '9') -- what!?
            multiplier *= 10
            addend *= 10
            addend += c - '0'
        this.muldigit(multiplier)
        this.adddigit(addend)
        i += 9
    return this

// Long multiplication

def bign_multiply(this, multiplier):
    // Make sure the shorter number is on the right side to make things a bit more efficient
    let left  = if (this.digitsUsed > multiplier.digitsUsed): this else: multiplier
    let right = if (this.digitsUsed > multiplier.digitsUsed): multiplier else: this
    let newDigits = map(left.digitsUsed + right.digitsUsed): 0
    for(right.digitsUsed) rightPos:
        let rightDigit = right.digits[rightPos]
        var temp = 0
        for(left.digitsUsed) leftPos:
            temp += newDigits[leftPos + rightPos]
            temp += rightDigit * left.digits[leftPos]
            newDigits[leftPos + rightPos] = temp % base
            temp /= base
        // Roll forward any carry we may have
        let destPos = rightPos + left.digitsUsed
        while temp != 0:
            temp += newDigits[destPos]
            newDigits[destPos] = temp % base
            temp /= base
            destPos +- 1
    let bign = Bign { digits: newDigits, digitsUsed: newDigits.length }
    bign.adjustDigitsUsed()
    return bign

let one = str2bign("18446744073709551616")
let two = one.clone()
var pro = one.bign_multiply(two)
print(bign2str(pro))


longmult := proc(a::integer,b::integer)
    local A,B,m,n,i,j;
    # Note, return a*b; works in Maple for any sized integer
    A := convert(a,base,10);
    B := convert(b,base,10);
    m := numelems(A);
    n := numelems(B);
    add( add( A[i]*B[j]*10^(j-1), j=1..n )*10^(i-1), i=1..m );
end;

> longmult( 2^64, 2^64 );
                    340282366920938463463374607431768211456


 LongMultiplication[a_,b_]:=Module[{d1,d2},
  d1=IntegerDigits[a]//Reverse;
  d2=IntegerDigits[b]//Reverse;
  Sum[d1[[i]]d2[[j]]*10^(i+j-2),{i,1,Length[d1]},{j,1,Length[d2]}]
 ]


/* NetRexx */
options replace format comments java crossref symbols nobinary

numeric digits 100

runSample(arg)
return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method multiply(multiplier, multiplicand) public static
  result = ''
  mpa = s2a(multiplier)
  mpb = s2a(multiplicand)
  r_ = 0
  rim = 1
  loop bi = 1 to mpb[0]
    loop ai = 1 to mpa[0]
      ri = ai + bi -1
      p_ = mpa[ai] * mpb[bi]
      loop i_ = ri by 1 until p_ = 0
        s_ = r_[i_] + p_
        r_[i_] = s_ // 10
        p_ = s_ % 10
        end i_
      rim = rim.max(i_)
      end ai
    end bi
  r_[0] = rim
  result = a2s(r_)
  result = result.strip('l', 0)
  if result = '' then result = 0
  return result

-- .............................................................................
-- copy characters of a numeric string into a corresponding array
-- digits are numbered 1 to n from right to left
method s2a(numbr) private static
  result = 0
  lstr = numbr.length()
  loop z_ = 1 to lstr
    result[z_] = numbr.substr(lstr - z_ + 1, 1)
    end z_
  result[0] = lstr
  return result

-- .............................................................................
-- turn the array of digits into a numeric string
method a2s(numbr) private static
  result = ''
  loop z_ = numbr[0] to 1 by -1
    result = result || numbr[z_]
    end z_
  return result

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
  mms = [ -
                      123',  '123, -
                      012',  '12, -
             123456789012' , '44444444444, -
                  2 ** 64' , '2**64, -
                        0'                      ,0 ' -
  ]
  ok = 0
  errors = 0

  loop mm over mms
    parse mm multiplier . ',' multiplicand .
    builtIn = multiplier * multiplicand
    calculated = multiply(multiplier, multiplicand)
    say 'Calculate' multiplier + 0 'x' multiplicand + 0
    say 'Built in:' builtIn
    say 'Derived: ' calculated
    say
    if builtIn = calculated then ok = ok + 1
    else                         errors = errors + 1
    end mm
  say ok 'ok'
  say errors 'not ok'

  return


import strutils

proc ti(a: char): int = ord(a) - ord('0')

proc longmulti(a, b: string): string =
  var
    i, j = 0
    k = false

  # either is zero, return "0"
  if a == "0" or b == "0":
    return "0"

  # see if either a or b is negative
  if a[0] == '-':
    i = 1; k = not k
  if b[0] == '-':
    j = 1; k = not k

  # if yes, prepend minus sign if needed and skip the sign
  if i > 0 or j > 0:
    result = if k: "-" else: ""
    result.add longmulti(a[i..a.high], b[j..b.high])
    return

  result = repeat('0', a.len + b.len)

  for i in countdown(a.high, 0):
    var carry = 0
    var k = i + b.len
    for j in countdown(b.high, 0):
      let n = ti(a[i]) * ti(b[j]) + ti(result[k]) + carry
      carry = n div 10
      result[k] = chr(n mod 10 + ord('0'))
      dec k
    result[k] = chr(ord(result[k]) + carry)

  if result[0] == '0':
    result[0..result.high-1] = result[1..result.high]

echo longmulti("-18446744073709551616", "-18446744073709551616")


Program TwoUp; Uses DOS, crt;
{Concocted by R.N.McLean (whom God preserve), Victoria university, NZ.}
 Procedure Croak(gasp: string);
  Begin
   Writeln;
   Write(Gasp);
   HALT;
  End;

 const BigBase = 10;		{The base of big arithmetic.}
 const BigEnuff = 333;		{The most storage possible is 65532 bytes with Turbo Pascal.}
 type  BigNumberIndexer = word;	{To access 0:BigEnuff BigNumberDigit data.}
 type  BigNumberDigit = byte;	{The data.}
 type  BigNumberDigit2 = word;	{Capable of digit*digit + carry. Like, 255*255 = 65025}

 type BigNumber =		{All sorts of arrangements are possible.}
  Record				{Could include a sign indication.}
   TopDigit: BigNumberDigit;		{Finger the high-order digit.}
   digit: array[0..BigEnuff] of byte;	{The digits: note the "downto" in BigShow.}
  end;					{Could add fractional digits too. Endless, endless.}

 Procedure BigShow(var a: BigNumber);	{Print the number.}
  var i: integer;	{A stepper.}
  Begin
   for i:=a.TopDigit downto 0 do	{Thus high-order to low, as is the custom.}
    if BigBase = 10 then write(a.digit[i])	{Constant following by the Turbo Pascal compiler}
     else if BigBase = 100 then Write(a.digit[i] div 10,a.digit[i] mod 10)	{Means that there will be no tests.}
      else write(a.digit[i],',');		{And dead code will be omitted.}
  End;

 Procedure BigZero(var A: BigNumber); {A:=0;}
  Begin;
   A.TopDigit:=0;
   A.Digit[0]:=0;
  End;
 Procedure BigOne(var A: BigNumber);  {A:=1;}
  Begin;
   A.TopDigit:=0;
   A.Digit[0]:=1;
  End;
 Function BigInt(n: longint): BigNumber; {A:=N;}
  var l: BigNumberIndexer;
  Begin
   l:=0;
   if n < 0 then croak('Negative integers are not yet considered.');
   repeat		{At least one digit is to be placed.}
    if l > BigEnuff then Croak('BigInt overflowed!');	{Oh dear.}
    BigInt.Digit[l]:=N mod BigBase;	{The low-order digit.}
    n:=n div BigBase;			{Shift down a digit.}
    l:=l + 1;				{Count in anticipation.}
   until N = 0;			{Still some number left?}
   BigInt.TopDigit:=l - 1;	{Went one too far.}
  End;

 Function BigMult(a,b: BigNumber): BigNumber;	{x:=BigMult(a,b);}
{Suppose the digits of A are a5,a4,a3,a2,a1,a0...
 To multiply A and B.
                               a5   a4   a3   a2   a1   a0: six digits, d1
                                x   b4   b3   b2   b1   b0: five digits, d2
                               ---------------------------
                             a5b0 a4b0 a3b0 a2b0 a1b0 a0b0
                        a5b1 a4b1 a3b1 a2b1 a1b1 a0b1
                   a5b2 a4b2 a3b2 a2b2 a1b2 a0b2
              a5b3 a4b3 a3b3 a2b3 a1b3 a0b3
         a5b4 a4b4 a3b4 a2b4 a1b4 a0b4
   -------------------------------------------------------
   carry    9    8    7    6    5    4    3    2    1    0: at least nine digits,
   -------------------------------------------------------  = d1 + d2 - 1
   But the indices are also the powers, so the highest power is 9 = 5 + 4,
and a possible tenth for any carry.}
  var X: BigNumber;		{Scratchpad, so b:=BigMult(a,b); doesn't overwrite b as it goes...}
  var d: BigNumberDigit;	{A digit.}
  var c: BigNumberDigit;	{A carry.}
  var dd: BigNumberDigit2;	{A digit product.}
  var i,j,l: BigNumberIndexer;	{Steppers.}
  Begin
   if ((A.TopDigit = 0) and (A.Digit[0] = 0))
    or((B.TopDigit = 0) and (B.Digit[0] = 0)) then begin BigZero(BigMult); exit; end;
   l:=A.TopDigit + B.TopDigit;       {Minimal digit requirement. (Counting is from zero)}
   if l > BigEnuff then Croak('BigMult will overflow.');
   for i:=l downto 0 do X.Digit[i]:=0;	{Clear for action.}
   for i:=0 to A.TopDigit do		{Arbitrarily, choose A on the one hand.}
    begin				{Though there could be a better choice.}
     d:=A.Digit[i];			{Select the digit.}
     if d <> 0 then			{What the hell. One in BigBase chance.}
      begin				{But not this time.}
       l:=i;				{Locate the power of BigBase.}
       c:=0;				{Start this digit's multiply pass.}
       for j:=0 to B.TopDigit do	{Stepping along B's digits.}
        begin				{One by one.}
         dd:=BigNumberDigit2(B.Digit[j])*d + X.Digit[l] + c;	{The deed.}
         X.Digit[l]:=dd mod BigBase;	{Place the new digit.}
         c:=dd div BigBase;		{And extract the carry.}
         l:=l + 1;			{Ready for the next power up.}
        end;				{Advance to it.}
       if c > 0 then			{The multiply done, place the carry.}
        begin				{Ah. We *will* use the next power up.}
         if l > BigEnuff then Croak('BigMultX has overflowed.');	{Oh dear.}
         X.Digit[l]:=c;		{Thus as if BigMult..Digit[l] was zeroed.}
         l:=l + 1;			{Preserve the one-too-far for the last case}
        end;				{So much for a carry at the end of a pass.}
      end;				{So much for a non-zero digit.}
    end;			{On to another digit to multiply with.}
   X.TopDigit:=l - 1;	{Remember the one-too-far.}
   BigMult:=X;		{Deliver, possibly scragging A or B, or, both!}
 End; {of BigMult.}

 Procedure BigPower(var X: BigNumber; P: longint); {Replaces X by X**P}
  var A,W: BigNumber;	{Scratchpads}
  label up;
  Begin		{Each squaring doubles the power, melding nicely with binary reduction.}
   if P <= 0 then Croak('Negative powers are not accommodated!');
   BigOne(A);		{x**0 = 1}
   W:=X;		{Holds X**1, 2, 4, 8, etc.}
up:if P mod 2 = 1 then A:=BigMult(A,W);	{Bit on, so include this order.}
   P:=P div 2;		{Halve the power contrariwise to W's doubling.}
   if P > 0 then 	{Still some power to come?}
    begin		{Yes.}
     W:=BigMult(W,W);	{Step up to the next bit's power.}
     goto up;		{And see if it is "on".}
    end;		{Odd layout avoids multiply testing P > 0.}
   X:=A;		{The result.}
  End;

 var X: BigNumber;
 var p: longint;
 BEGIN
  ClrScr;
  WriteLn('To calculate  x = 2**64, then x*x via multi-digit long multiplication.');
  p:=64;		{As per the specification.}
  X:=BigInt(2);		{Start with 2.}
  BigPower(X,p);	{First stage: 2**64}
  Write ('x = 2**',p,' = '); BigShow(X);
  WriteLn;
  X:=BigMult(X,X);	{Second stage.}
  Write ('x*x = ');BigShow(X);	{Can't have Write('x*x = ',BigShow(BigMult(X,X))), after all. Oh well.}
 END.


#!/usr/bin/perl -w
use strict;

# This should probably be done in a loop rather than be recursive.
sub add_with_carry
{
  my $resultref = shift;
  my $addend = shift;
  my $addendpos = shift;

  push @$resultref, (0) while (scalar @$resultref < $addendpos + 1);
  my $addend_result = $addend + $resultref->[$addendpos];
  my @addend_digits = reverse split //, $addend_result;
  $resultref->[$addendpos] = shift @addend_digits;

  my $carry_digit = shift @addend_digits;
  &add_with_carry($resultref, $carry_digit, $addendpos + 1)
    if( defined $carry_digit )
}

sub longhand_multiplication
{
  my @multiplicand = reverse split //, shift;
  my @multiplier = reverse split //, shift;
  my @result = ();
  my $multiplicand_offset = 0;
  foreach my $multiplicand_digit (@multiplicand)
  {
    my $multiplier_offset = $multiplicand_offset;
    foreach my $multiplier_digit (@multiplier)
    {
      my $multiplication_result = $multiplicand_digit * $multiplier_digit;
      my @result_digit_addend_list = reverse split //, $multiplication_result;

      my $addend_offset = $multiplier_offset;
      foreach my $result_digit_addend (@result_digit_addend_list)
      {
        &add_with_carry(\@result, $result_digit_addend, $addend_offset++)
      }

      ++$multiplier_offset;
    }

    ++$multiplicand_offset;
  }

  @result = reverse @result;

  return join '', @result;
}

my $sixtyfour = "18446744073709551616";

my $onetwentyeight = &longhand_multiplication($sixtyfour, $sixtyfour);
print "$onetwentyeight\n";


F leo_numbers(cnt, =l0 = 1, =l1 = 1, add = 1)
   L 1..cnt
      print(l0, end' ‘ ’)
      (l0, l1) = (l1, l0 + l1 + add)
   print()

print(‘Leonardo Numbers: ’, end' ‘’)
leo_numbers(25)
print(‘Fibonacci Numbers: ’, end' ‘’)
leo_numbers(25, 0, 1, 0)


constant base = 1_000_000_000

function bcd9_mult(sequence a, sequence b)

    sequence c = repeat(0,length(a)+length(b))
    for i=1 to length(a) do
        integer j = i+length(b)-1
        c[i..j] = sq_add(c[i..j],sq_mul(a[i],b))
    end for

    for i=1 to length(c) do
        atom ci = c[i]
        if ci>base then
            c[i+1] += floor(ci/base) -- carry
            c[i] = remainder(ci,base)
        end if
    end for

    if c[$]=0 then
        c = c[1..$-1]
    end if
    return c
end function

function atom_to_bcd9(atom a)
sequence s = {}
    while a>0 do
        s = append(s,remainder(a,base))
        a = floor(a/base)
    end while
    return s
end function

function bcd9_to_str(sequence a)
string s = sprintf("%d",a[$])
    for i=length(a)-1 to 1 by -1 do
        s &= sprintf("%09d",a[i])
    end for
    -- (might want to trim leading 0s here)
    return s
end function

sequence a, b, c

a = atom_to_bcd9(power(2,32))
printf(1,"a is %s\n",{bcd9_to_str(a)})

b = bcd9_mult(a,a)
printf(1,"a*a is %s\n",{bcd9_to_str(b)})

c = bcd9_mult(b,b)
printf(1,"a*a*a*a is %s\n",{bcd9_to_str(c)})


CARD FUNC Leonardo(BYTE n)
  CARD curr,prev,tmp

  IF n<=1 THEN
    RETURN (1)
  FI

  prev=1
  curr=1
  DO
    tmp=prev
    prev=curr
    curr==+tmp+1
    n==-1
  UNTIL n=1
  OD
RETURN (curr)

PROC Main()
  BYTE n
  CARD l

  Put(125) ;clear screen

  FOR n=0 TO 22 ;limited to 22 because of CARD limitations
  DO
    l=Leonardo(n)
    IF n MOD 2=0 THEN
      Position(2,n/2+1)
    ELSE
      Position(21,n/2+1)
    FI
    PrintF("L(%B)=%U",n,l)
  OD
RETURN


with Ada.Text_IO; use Ada.Text_IO;

procedure Leonardo is

   function Leo
     (N      : Natural;
      Step   : Natural := 1;
      First  : Natural := 1;
      Second : Natural := 1) return Natural   is
      L : array (0..1) of Natural := (First, Second);
	begin
		for i in 1 .. N loop
			L := (L(1), L(0)+L(1)+Step);
		end loop;
		return L (0);
	end Leo;

begin
   Put_Line ("First 25 Leonardo numbers:");
   for I in 0 .. 24 loop
      Put (Integer'Image (Leo (I)));
   end loop;
   New_Line;
   Put_Line ("First 25 Leonardo numbers with L(0) = 0, L(1) = 1, " &
             "step = 0 (fibonacci numbers):");
   for I in 0 .. 24 loop
      Put (Integer'Image (Leo (I, 0, 0, 1)));
   end loop;
   New_Line;
end Leonardo;


BEGIN
    # leonardo number parameters #
    MODE LEONARDO = STRUCT( INT l0, l1, add number );
    # default leonardo number parameters #
    LEONARDO leonardo numbers = LEONARDO( 1, 1, 1 );
    # operators to allow us to specify non-default parameters #
    PRIO WITHLZERO = 9, WITHLONE = 9, WITHADDNUMBER = 9;
    OP   WITHLZERO     = ( LEONARDO parameters, INT l0         )LEONARDO:
         LEONARDO( l0, l1 OF parameters, add number OF parameters );
    OP   WITHLONE      = ( LEONARDO parameters, INT l1         )LEONARDO:
         LEONARDO( l0 OF parameters, l1, add number OF parameters );
    OP   WITHADDNUMBER = ( LEONARDO parameters, INT add number )LEONARDO:
         LEONARDO( l0 OF parameters, l1 OF parameters, add number );
    # show the first n Leonardo numbers with the specified parameters #
    PROC show = ( INT n, LEONARDO parameters )VOID:
         IF n > 0 THEN
            INT l0         = l0         OF parameters;
            INT l1         = l1         OF parameters;
            INT add number = add number OF parameters;
            print( ( whole( l0, 0 ), " " ) );
            IF n > 1 THEN
                print( ( whole( l1, 0 ), " " ) );
                INT lp := l0;
                INT ln := l1;
                FROM 2 TO n - 1 DO
                    INT next = ln + lp + add number;
                    lp := ln;
                    ln := next;
                    print( ( whole( ln, 0 ), " " ) )
                OD
            FI
         FI # show # ;

    # first series #
    print( ( "First 25 Leonardo numbers", newline ) );
    show( 25, leonardo numbers );
    print( ( newline ) );
    # second series #
    print( ( "First 25 Leonardo numbers from 0, 1 with add number = 0", newline ) );
    show( 25, leonardo numbers WITHLZERO 0 WITHADDNUMBER 0 );
    print( ( newline ) )
END


------------------------ GENERATOR -------------------------

-- leo :: Int -> Int -> Int -> Generator [Int]
on leo(L0, L1, delta)
    script
        property x : L0
        property y : L1
        on |λ|()
            set n to x
            set {x, y} to {y, x + y + delta}
            return n
        end |λ|
    end script
end leo

--------------------------- TEST ---------------------------
on run
    set leonardo to leo(1, 1, 1)
    set fibonacci to leo(0, 1, 0)

    unlines({"First 25 Leonardo numbers:", ¬
        twoLines(take(25, leonardo)), "", ¬
        "First 25 Fibonacci numbers:", ¬
        twoLines(take(25, fibonacci))})
end run

------------------------ FORMATTING ------------------------

-- twoLines :: [Int] -> String
on twoLines(xs)
    script row
        on |λ|(ns)
            tab & intercalate(", ", ns)
        end |λ|
    end script
    return unlines(map(row, chunksOf(16, xs)))
end twoLines

------------------------- GENERIC --------------------------

-- chunksOf :: Int -> [a] -> [[a]]
on chunksOf(n, xs)
    set lng to length of xs
    script go
        on |λ|(a, i)
            set x to (i + n) - 1
            if x ≥ lng then
                a & {items i thru -1 of xs}
            else
                a & {items i thru x of xs}
            end if
        end |λ|
    end script
    foldl(go, {}, enumFromThenTo(1, n, lng))
end chunksOf

-- enumFromThenTo :: Int -> Int -> Int -> [Int]
on enumFromThenTo(x1, x2, y)
    set xs to {}
    set d to max(1, (x2 - x1))
    repeat with i from x1 to y by d
        set end of xs to i
    end repeat
    return xs
end enumFromThenTo

-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from 1 to lng
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldl

-- intercalate :: String -> [String] -> String
on intercalate(sep, xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, sep}
    set s to xs as text
    set my text item delimiters to dlm
    return s
end intercalate

-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn

-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map

-- max :: Ord a => a -> a -> a
on max(x, y)
    if x > y then
        x
    else
        y
    end if
end max

-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
    set c to class of xs
    if list is c then
        if 0 < n then
            items 1 thru min(n, length of xs) of xs
        else
            {}
        end if
    else if string is c then
        if 0 < n then
            text 1 thru min(n, length of xs) of xs
        else
            ""
        end if
    else if script is c then
        set ys to {}
        repeat with i from 1 to n
            set v to xs's |λ|()
            if missing value is v then
                return ys
            else
                set end of ys to v
            end if
        end repeat
        return ys
    else
        missing value
    end if
end take

-- unlines :: [String] -> String
on unlines(xs)
    set {dlm, my text item delimiters} to ¬
        {my text item delimiters, linefeed}
    set str to xs as text
    set my text item delimiters to dlm
    str
end unlines


(de multi (A B)
   (setq A (format A) B (reverse (chop B)))
   (let Result 0
      (for (I . X) B
         (setq Result (+ Result (* (format X) A (** 10 (dec I)))))) ) )


/* Multiply a by b, giving c. */
multiply: procedure (a, b, c);
   declare (a, b, c) (*) fixed decimal (1);
   declare (d, e, f) (hbound(a,1)) fixed decimal (1);
   declare pr (-hbound(a,1) : hbound(a,1)) fixed decimal (1);
   declare p fixed decimal (2), (carry, s) fixed decimal (1);
   declare neg bit (1) aligned;
   declare (i, j, n, offset) fixed binary (31);

   n = hbound(a,1);
   d = a;
   e = b;
   s = a(1) + b(1);
   neg = (s = 9);
   if a(1) = 9 then call complement (d);
   if b(1) = 9 then call complement (e);
   pr = 0;
   offset = 0; carry = 0;
   do i = n to 1 by -1;
      do j = n to 1 by -1;
         p = d(i) * e(j) + pr(j-offset) + carry;
         if p > 9 then do; carry = p/10; p = mod(p, 10); end; else carry = 0;
         pr(j-offset) = p;
      end;
      offset = offset + 1;
   end;
   do i = hbound(a,1) to 1 by -1;
      c(i) = pr(i);
   end;
   do i = -hbound(a,1) to 1;
      if pr(i) ^= 0 then signal fixedoverflow;
   end;
   if neg then call complement (c);
end multiply;

complement: procedure (a);
   declare a(*) fixed decimal (1);
   declare i fixed binary (31), carry fixed decimal (1);
   declare s fixed decimal (2);

   carry = 1;
   do i = hbound(a,1) to 1 by -1;
      s = 9 - a(i) + carry;
      if s > 9 then do; s = s - 10; carry = 1; end; else carry = 0;
      a(i) = s;
   end;
end complement;


L: function [n l0 l1 ladd].memoize[
    (n=0)? -> l0 [
        (n=1)? -> l1
               -> (L n-1 l0 l1 ladd) + (L n-2 l0 l1 ladd) + ladd
    ]
]

Leonardo: function [z]-> L z 1 1 1

print "The first 25 Leonardo numbers:"
print map 0..24 => Leonardo
print ""
print "The first 25 Leonardo numbers with L0=0, L1=1, LADD=0"
print map 0..24 'x -> L x 0 1 0


Leonardo(n, L0:=1, L1:=1, step:=1){
	if n=0
		return L0
	if n=1
		return L1
	return Leonardo(n-1, L0, L1, step) + Leonardo(n-2, L0, L1, step) + step
}


# syntax: GAWK -f LEONARDO_NUMBERS.AWK
BEGIN {
    leonardo(1,1,1,"Leonardo")
    leonardo(0,1,0,"Fibonacci")
    exit(0)
}
function leonardo(L0,L1,step,text,  i,tmp) {
    printf("%s numbers (%d,%d,%d):\n",text,L0,L1,step)
    for (i=1; i<=25; i++) {
      if (i == 1) {
        printf("%d ",L0)
      }
      else if (i == 2) {
        printf("%d ",L1)
      }
      else {
        printf("%d ",L0+L1+step)
        tmp = L0
        L0 = L1
        L1 = tmp + L1 + step
      }
    }
    printf("\n")
}


100H: /* LONG MULTIPLICATION OF LARGE INTEGERS                               */
   /* LARGE INTEGERS ARE REPRESENTED BY ARRAYS OF BYTES WHOSE VALUES ARE     */
   /* A SINGLE DECIMAL DIGIT OF THE NUMBER                                   */
   /* THE LEAST SIGNIFICANT DIGIT OF THE LARGE INTEGER IS IN ELEMENT 1       */
   /* ELEMENT 0 CONTAINS THE NUMBER OF DIGITS THE NUMBER HAS                 */
   BDOS: PROCEDURE( FN, ARG ); /* CP/M BDOS SYSTEM CALL                      */
      DECLARE FN BYTE, ARG ADDRESS;
      GOTO 5;
   END BDOS;
   PRINT$CHAR:   PROCEDURE( C ); DECLARE C BYTE;    CALL BDOS( 2, C ); END;
   PRINT$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
   DECLARE PRINT$NL LITERALLY 'PRINT$STRING( .( 0DH, 0AH, ''$'' ) )';

   DECLARE LONG$INTEGER  LITERALLY '(201)BYTE';
   DECLARE DIGIT$BASE    LITERALLY '10';

   /* PRINTS A LONG INTEGER                                                  */
   PRINT$LONG$INTEGER: PROCEDURE( N$PTR );
      DECLARE N$PTR ADDRESS;
      DECLARE N BASED N$PTR LONG$INTEGER;
      DECLARE ( D, F ) BYTE;
      F = N( 0 );
      DO D = 1 TO N( 0 );
         CALL PRINT$CHAR( N( F ) + '0' );
         F = F - 1;
      END;
   END PRINT$LONG$INTEGER;
   /* IMPLEMENTS LONG MULTIPLICATION, C IS SET TO A * B                      */
   /*     C CAN BE THE SAME LONG$INTEGER AS A OR B                           */
   LONG$MULTIPLY: PROCEDURE( A$PTR, B$PTR, C$PTR );
      DECLARE ( A$PTR, B$PTR, C$PTR ) ADDRESS;
      DECLARE ( A BASED A$PTR, B BASED B$PTR, C BASED C$PTR ) LONG$INTEGER;
      DECLARE MRESULT LONG$INTEGER;
      DECLARE RPOS    BYTE;

      /* MULTIPLIES THE LONG INTEGER IN B BY THE INTEGER A, THE RESULT       */
      /*     IS ADDED TO C, STARTING FROM DIGIT START                        */
      /*     OVERFLOW IS IGNORED                                             */
      MULTIPLY$ELEMENT: PROCEDURE( A, B$PTR, C$PTR, START );
         DECLARE ( B$PTR, C$PTR )                 ADDRESS;
         DECLARE ( A, START )                     BYTE;
         DECLARE ( B BASED B$PTR, C BASED C$PTR ) LONG$INTEGER;
         DECLARE ( CDIGIT, D$CARRY, BPOS, CPOS )  BYTE;
         D$CARRY = 0;
         CPOS    = START;
         DO BPOS = 1 TO B( 0 );
            CDIGIT = C( CPOS ) + ( A * B( BPOS ) ) + D$CARRY;
            IF CDIGIT < DIGIT$BASE THEN D$CARRY = 0;
            ELSE DO;
               /* HAVE DIGITS TO CARRY                                       */
               D$CARRY = CDIGIT  /  DIGIT$BASE;
               CDIGIT  = CDIGIT MOD DIGIT$BASE;
            END;
            C( CPOS ) = CDIGIT;
            CPOS = CPOS + 1;
         END;
         C( CPOS ) = D$CARRY;
         /* REMOVE LEADING ZEROS BUT IF THE NUMBER IS 0, KEEP THE FINAL 0    */
         DO WHILE( CPOS > 1 AND C( CPOS ) = 0 );
            CPOS = CPOS - 1;
         END;
         C( 0 ) = CPOS;
      END MULTIPLY$ELEMENT ;

      /* THE RESULT WILL BE COMPUTED IN MRESULT, ALLOWING A OR B TO BE C     */
      DO RPOS = 1 TO LAST( MRESULT ); MRESULT( RPOS ) = 0; END;
      /* MULTIPLY BY EACH DIGIT AND ADD TO THE RESULT                        */
      DO RPOS = 1 TO A( 0 );
         IF A( RPOS ) <> 0 THEN DO;
            CALL MULTIPLY$ELEMENT( A( RPOS ), B$PTR, .MRESULT, RPOS );
         END;
      END;
      /* RETURN THE RESULT IN C                                              */
      DO RPOS = 0 TO MRESULT( 0 ); C( RPOS ) = MRESULT( RPOS ); END;
   END;

   /* CALCULATE AND OUTPUT 2^128                                             */
   DECLARE ( TWO$TO$64, TWO$TO$128 ) LONG$INTEGER;
   DECLARE ( PWR, TPOS ) BYTE;
   /* CONSTRUCT 2^64 IN TWO$TO$64                                            */
   DO TPOS = 0 TO LAST( TWO$TO$64 ); TWO$TO$64( TPOS ) = 0; END;
   TWO$TO$64( 0 ) = 1;
   TWO$TO$64( 1 ) = 2;
   PWR          = 1;
   DO WHILE PWR < 64;
      CALL LONG$MULTIPLY( .TWO$TO$64, .TWO$TO$64, .TWO$TO$64 );
      PWR  = PWR + PWR;
   END;
   /* CONSTRUCT 2^128                                                        */
   TWO$TO$128( 0 ) = 1;
   TWO$TO$128( 1 ) = 0;
   CALL LONG$MULTIPLY( .TWO$TO$64, .TWO$TO$64, .TWO$TO$128 );
   CALL PRINT$STRING( .( '2', 05EH, '128: $' ) ); /* 05EH = "^" IN ASCII     */
   CALL PRINT$LONG$INTEGER( .TWO$TO$128 );
   CALL PRINT$NL;
EOF


#!/bin/bash

function leonardo_number () {
    L0_value=${2:-1}
    L1_value=${3:-1}
    Add=${4:-1}
    leonardo_numbers=($L0_value $L1_value)
    for (( i = 2; i < $1; ++i))
    do
       leonardo_numbers+=( $((leonardo_numbers[i-1] + leonardo_numbers[i-2] + Add)) )
    done
    echo "${leonardo_numbers[*]}"
}


subroutine leonardo(L0, L1, suma, texto)
	print "Numeros de " + texto + " (" + L0 + "," + L1 + "," + suma + "):"
	for i = 1 to 25
		if i = 1 then
			print L0 + " ";
		else
			if i = 2 then
				print L1 + " ";
			else
				print L0 + L1 + suma + " ";
				tmp = L0
				L0 = L1
				L1 = tmp + L1 + suma
			end if
		end if
	next i
	print chr(10)
end subroutine

#--- Programa Principal ---
call leonardo(1,1,1,"Leonardo")
call leonardo(0,1,0,"Fibonacci")
end


REM >leonardo
:
PRINT "Enter values of L0, L1, and ADD, separated by commas:"
INPUT l0%, l1%, add%
PRINT l0% ' l1%
FOR i% = 3 TO 25
  temp% = l1%
  l1% += l0% + add%
  l0% = temp%
  PRINT l1%
NEXT
PRINT
END


# LongAddition only supports Unsigned Integers represented as Strings/Character Arrays
Function LongAddition ( [Char[]] $lhs, [Char[]] $rhs )
{
	$lhsl = $lhs.length
	$rhsl = $rhs.length
	if(($lhsl -gt 0) -and ($rhsl -gt 0))
	{
		$maxplace = [Math]::Max($rhsl,$lhsl)+1
		1..$maxplace | ForEach-Object {
			$carry = 0
			$result = ""
		} {
			$add1 = 0
			$add2 = 0
			if( $_ -le $lhsl ) { $add1 = [int]$lhs[ -$_ ] - 48 }
			if( $_ -le $rhsl ) { $add2 = [int]$rhs[ -$_ ] - 48 }
			$iresult = $add1 + $add2 + $carry
			if( ( $_ -lt $maxplace ) -or ( $iresult -gt 0 ) )
			{
				$result = "{0}{1}" -f ( $iresult % 10 ),$result
			}
			$carry = [Math]::Floor( $iresult / 10 )
		} {
			$result
		}
	} elseif($lhsl -gt 0) {
		[String]::Join( '', $lhs )
	} elseif($rhsl -gt 0) {
		[String]::Join( '', $rhs )
	} else {
		"0"
	}
}

# LongMultiplication only supports Unsigned Integers represented as Strings/Character Arrays
Function LongMultiplication ( [Char[]] $lhs, [Char[]] $rhs )
{
	$lhsl = $lhs.length
	$rhsl = $rhs.length
	if(($lhsl -gt 0) -and ($rhsl -gt 0))
	{
		1..$lhsl | ForEach-Object {
			$carry0 = ""
			$result0 = ""
		} {
			$i = -$_
			$add1 = ( 1..$rhsl | ForEach-Object {
				$carry1 = 0
				$result1 = ""
			} {
				$j = -$_
				$mult1 = [int]$lhs[ $i ] - 48
				$mult2 = [int]$rhs[ $j ] - 48
				$iresult1 = $mult1 * $mult2 + $carry1
				$result1 = "{0}{1}" -f ( $iresult1 % 10 ), $result1
				$carry1 = [Math]::Floor( $iresult1 / 10 )
			} {
				if( $carry1 -gt 0 )
				{
					$result1 = "{0}{1}" -f $carry1, $result1
				}
				$result1
			} )
			$iresult0 = ( LongAddition $add1 $carry0 )
			$iresultl = $iresult0.length
			$result0 = "{0}{1}" -f $iresult0[-1],$result0
			if( $iresultl -gt 1 ) {
				$carry0 = [String]::Join( '', $iresult0[ -$iresultl..-2 ] )
			} else { $carry0 = "" }
		} {
			if( $carry0 -ne "" )
			{
				$result0 = "{0}{1}" -f $carry0, $result0
			}
			$result0
		}
	} else { "0" }
}

LongMultiplication "18446744073709551616" "18446744073709551616"


#include<stdio.h>

void leonardo(int a,int b,int step,int num){

	int i,temp;

	printf("First 25 Leonardo numbers : \n");

	for(i=1;i<=num;i++){
		if(i==1)
			printf(" %d",a);
		else if(i==2)
			printf(" %d",b);
		else{
			printf(" %d",a+b+step);
			temp = a;
			a = b;
			b = temp+b+step;
		}
	}
}

int main()
{
	int a,b,step;

	printf("Enter first two Leonardo numbers and increment step : ");

	scanf("%d%d%d",&a,&b,&step);

	leonardo(a,b,step,25);

	return 0;
}


using System;
using System.Linq;

public class Program
{
    public static void Main() {
        Console.WriteLine(string.Join(" ", Leonardo().Take(25)));
        Console.WriteLine(string.Join(" ", Leonardo(L0: 0, L1: 1, add: 0).Take(25)));
    }

    public static IEnumerable<int> Leonardo(int L0 = 1, int L1 = 1, int add = 1) {
        while (true) {
            yield return L0;
            (L0, L1) = (L1, L0 + L1 + add);
        }
    }
}


Structure decDigitFmt ;decimal digit format
  Array Digit.b(0) ;contains each digit of number, right-most digit is index 0
  digitCount.i ;zero based
  sign.i ; {x < 0} = -1, {x = 0} = 0,  {x > 0} = 1
EndStructure

Global zero_decDigitFmt.decDigitFmt ;represents zero in the decimal digit format

;converts string representation of integer into the digit format, number can include signus but no imbedded spaces
Procedure stringToDecDigitFmt(numString.s, *x.decDigitFmt)
  Protected *c.Character, digitIdx, digitCount
  If numString And *x
    *c.Character = @numString
    Repeat
      Select *c\c
        Case '0' To '9', '-', '+'
          *c + SizeOf(Character)
        Default
          numString = Left(numString, *c - @numString)
          Break
      EndSelect
    ForEver
    *c = @numString
    Select  *c\c
      Case '-'
        *x\sign = -1
        *c + SizeOf(Character)
      Case '+'
        *x\sign = 1
        *c + SizeOf(Character)
      Case '0' To '9'
        *x\sign = 1
    EndSelect

    numString = LTrim(PeekS(*c), "0") ;remove leading zeroes
    If numString = "" ;is true if equal to zero or if only a signus is present
      CopyStructure(@zero_decDigitFmt, *x, decDigitFmt)
      ProcedureReturn
    EndIf
    *c = @numString

    digitCount = Len(PeekS(*c)) - 1
    Dim *x\Digit(digitCount)
    *x\digitCount = digitCount

    digitIdx = 0
    While *c\c
      If *c\c >= '0' And *c\c <= '9'
        *x\Digit(digitCount - digitIdx) = *c\c - '0'
        digitIdx + 1
        *c + SizeOf(Character)
      Else
        Break
      EndIf
    Wend

  EndIf
EndProcedure

;converts digit format representation of integer into string representation
Procedure.s decDigitFmtToString(*x.decDigitFmt)
  Protected i, number.s
  If *x
    If *x\sign = 0
      number = "0"
    Else

      For i = *x\digitCount To 0 Step -1
        number + Str(*x\Digit(i))
      Next
      number = LTrim(number, "0")
      If *x\sign = -1
        number = "-" + number
      EndIf
    EndIf
  EndIf

  ProcedureReturn number
EndProcedure

;handles only positive numbers and zero, negative numbers left as an exercise for the reader ;)
Procedure add_decDigitFmt(*a.decDigitFmt, *b.decDigitFmt, *sum.decDigitFmt, digitPos = 0) ;*sum contains the result of (*a ) * 10^digitPos + (*b)
  Protected carry, i, newDigitCount, workingSum, a_dup.decDigitFmt

  If *a And *b And *sum

    If *a = *sum: CopyStructure(*a, @a_dup, decDigitFmt): *a = @a_dup: EndIf ;handle special case of  *sum + *b = *sum
    If *b <> *sum: CopyStructure(*b, *sum, decDigitFmt): EndIf ;handle general case of *a + *b = *sum and special case of *a + *sum = *sum

    ;calculate number of digits needed for sum and resize array of digits if necessary
    newDigitCount = *a\digitCount + digitPos
    If newDigitCount >= *sum\digitCount
      If *sum\digitCount = newDigitCount And *sum\Digit(*sum\digitCount) <> 0
        newDigitCount + 1
      EndIf

      If *sum\digitCount <> newDigitCount
        *sum\digitCount = newDigitCount
        Redim *sum\Digit(*sum\digitCount)
      EndIf
    EndIf

    i = 0
    Repeat
      If i <= *a\digitCount
        workingSum = *a\Digit(i) + *sum\Digit(digitPos) + carry
      Else
        workingSum = *sum\Digit(digitPos) + carry
      EndIf

      If workingSum > 9
        carry = 1
        workingSum - 10
      Else
        carry = 0
      EndIf
      *sum\Digit(digitPos)  = workingSum
      digitPos + 1
      i + 1
    Until i > *a\digitCount And carry = 0

    If *a\sign <> 0 Or *sum\sign <> 0
      *sum\sign = 1 ;only handle positive numbers and zero for now
    EndIf
  EndIf
EndProcedure

Procedure multiply_decDigitFmt(*a.decDigitFmt, *b.decDigitFmt, *product.decDigitFmt) ;*product contains the result of (*a) * (*b)
  Protected i, digitPos, productSignus
  Protected Dim multTable.decDigitFmt(9)
  Protected NewList digitProduct.decDigitFmt()

  If *a And *b And *product
    If *a\sign = 0 Or *b\sign = 0
      CopyStructure(zero_decDigitFmt, *product, decDigitFmt)
      ProcedureReturn
    EndIf

    If *b\digitCount > *a\digitCount: Swap *a, *b: EndIf

    ;build multiplication table
    CopyStructure(*a, @multTable(1), decDigitFmt): multTable(1)\sign = 1 ;always positive
    For i = 2 To 9
      add_decDigitFmt(*a, multTable(i - 1), multTable(i))
    Next

    ;collect individual digit products for later summation; these could also be added as we go along
    For i = 0 To *b\digitCount
      AddElement(digitProduct())
      digitProduct() = multTable(*b\Digit(i))
    Next

    ;determine sign of product
    If *a\sign <> *b\sign
      productSignus = -1
    Else
      productSignus = 1
    EndIf

    digitPos = 0
    CopyStructure(zero_decDigitFmt, *product, decDigitFmt)
    ForEach digitProduct()
      add_decDigitFmt(digitProduct(), *product, *product, digitPos)
      digitPos + 1
    Next
    *product\sign = productSignus ;set sign of product
  EndIf
EndProcedure

;handles only positive integer exponents or an exponent of zero, does not raise an error for 0^0
Procedure exponent_decDigitFmt(*a.decDigitFmt, exponent, *product.decDigitFmt)
  Protected i, a_dup.decDigitFmt
  If *a And *product And exponent >= 0
    If *a = *product: CopyStructure(*a, @a_dup, decDigitFmt): *a = @a_dup: EndIf
    stringToDecDigitFmt("1", *product)
    For i = 1 To exponent: multiply_decDigitFmt(*product, *a, *product): Next
  EndIf
EndProcedure

If OpenConsole()
  Define a.decDigitFmt, product.decDigitFmt

  stringToDecDigitFmt("2", a)
  exponent_decDigitFmt(a, 64, a) ;2^64
  multiply_decDigitFmt(a, a, product)
  PrintN("The result of 2^64 * 2^64 is " + decDigitFmtToString(product))
  Print(#crlf$ + #crlf$ + "Press ENTER to exit"): Input()
  CloseConsole()
EndIf


#include <iostream>

void leoN( int cnt, int l0 = 1, int l1 = 1, int add = 1 ) {
    int t;
    for( int i = 0; i < cnt; i++ ) {
        std::cout << l0 << " ";
        t = l0 + l1 + add; l0 = l1; l1 = t;
    }
}
int main( int argc, char* argv[] ) {
    std::cout << "Leonardo Numbers: "; leoN( 25 );
    std::cout << "\n\nFibonacci Numbers: "; leoN( 25, 0, 1, 0 );
    return 0;
}


;;;
;;; leo - calculates the first n number from a leo sequence.
;;; The first argument n is the number of values to return. The next three arguments a, b, add are optional.
;;; Default values provide the "original" leonardo numbers as defined in the task.
;;; a and b are the first and second element of the leonardo sequence.
;;; add is the "add number" as defined in the task definition.
;;;

(defun leo (n &optional (a 1) (b 1) (add 1))
  (labels ((iterate (n foo)
             (if (zerop n) (reverse foo)
                           (iterate (- n 1)
                                    (cons (+ (first foo) (second foo) add) foo)))))
     (cond ((= n 1) (list a))
           (T       (iterate (- n 2) (list b a))))))


def leonardo(l_zero, l_one, add, amount)
    terms = [l_zero, l_one]
    while terms.size < amount
        new = terms[-1] + terms[-2]
        new += add
        terms << new
    end
    terms
end

puts "First 25 Leonardo numbers: \n#{ leonardo(1,1,1,25) }"
puts "Leonardo numbers with fibonacci parameters:\n#{ leonardo(0,1,0,25) }"


( ------------- preamble to task, some i/o related words ------------- )

  [ [] swap witheach
      [ char 0 -
        swap join ] ]                    is $->long    (     $ --> L   )

  [ number$ $->long ]                    is long       (     n --> L   )

  [ reverse behead
    swap witheach
      [ swap 10 * + ] ]                  is long->num  (     L --> n   )

  [ reverse
    witheach echo ]                      is echolong   (     L -->     )

( ------------------------- task starts here ------------------------- )

  [ [ table
      [ 0  1  2  3  4  5  6  7  8  9 ]
      [ 1  2  3  4  5  6  7  8  9 10 ]
      [ 2  3  4  5  6  7  8  9 10 11 ]
      [ 3  4  5  6  7  8  9 10 11 12 ]
      [ 4  5  6  7  8  9 10 11 12 13 ]
      [ 5  6  7  8  9 10 11 12 13 14 ]
      [ 6  7  8  9 10 11 12 13 14 15 ]
      [ 7  8  9 10 11 12 13 14 15 16 ]
      [ 8  9 10 11 12 13 14 15 16 17 ]
      [ 9 10 11 12 13 14 15 16 17 18 ] ]
    swap peek 10 /mod ]                  is add        (   n n --> n n )

  [ dip add add dip [ add nip ] swap ]   is addc       ( n n c --> n c )

  [ over size
    over size -
    dup dip
      [ 0 < if swap ]
    abs times
      [ 0 join ] ]                       is zeropad    (   L L --> L L )

  [ zeropad            ( when adding two numbers of different lengths )
    0 temp put         ( leading zeroes are added to make the lengths )
    [] unrot witheach  ( equal. This is implicit when the calculation )
      [ dip behead     ( done by hand, and performed by zeropad here. )
        temp take
        addc
        temp put
        rot swap join swap ]
    drop
    temp take dup 0 !=
    iff join else drop ]                 is longadd    (   L L --> L   )

  [ [ table
      [ 0  0  0  0  0  0  0  0  0  0 ]
      [ 0  1  2  3  4  5  6  7  8  9 ]
      [ 0  2  4  6  8 10 12 14 16 18 ]
      [ 0  3  6  9 12 15 18 21 24 27 ]
      [ 0  4  8 12 16 20 24 28 32 36 ]
      [ 0  5 10 15 20 25 30 35 40 45 ]
      [ 0  6 12 18 24 30 36 42 48 54 ]
      [ 0  7 14 21 28 35 42 49 56 63 ]
      [ 0  8 16 24 32 40 48 56 64 72 ]
      [ 0  9 18 27 36 45 54 63 72 81 ] ]
    swap peek 10 /mod ]                  is mult       (   n n --> n n )

  [ dip mult add dip [ add nip ] swap ]  is multc      ( n n c --> n c )

  [ dup 0 = iff
      [ 2drop 0 long ] done
    0 temp put
    [] unrot swap witheach
      [ over temp take
        multc
        temp put
        swap dip join ]
    drop
    temp take dup 0 !=
    iff join else drop ]                 is shortmult  (   L n --> L   )

  [ dup 0 long != iff
    [ 0 swap join ] ]                    is timesten   (     L --> L   )

  [ dup 0 long = iff
      [ 2drop 0 long ] done
    0 long unrot
    witheach
      [ dip dup shortmult
        rot longadd swap
        timesten ]
     drop ]                              is longmult   (   L L --> L   )

( ------------------------ additional to task ------------------------ )

  [ stack ]                              is linelength (       --> s   )

  [ linelength share times
      [ char - emit ]
    cr ]                                 is separator  (       -->     )

  [ linelength share
    over size - times sp
    echolong cr ]                        is showlong   (     L -->     )

  [ over size
    over size + linelength put
    over showlong
    dup showlong
    separator
    dup 0 long = iff
      [ 2drop 0 long ] done
    0 long unrot
    witheach
      [ dip dup shortmult
        dup showlong
        rot longadd swap
        timesten ]
    drop
    separator
    showlong
    separator
    linelength release ]                 is workings   (   L L -->     )

( --------------------------- demonstration -------------------------- )

say "Using long multiplication: "
2  64 ** long dup longmult dup echolong cr

say "Using built-in arithmetic: "
2 128 ** dup echo cr cr

swap long->num = iff
  say "10/10, Gold star!"
else
  say "0/10, See me after class."

cr cr
say "(Show your workings.)" cr cr
2 64 ** long dup workings cr


import std.stdio;

void main() {
    write("Leonardo Numbers: ");
    leonardoNumbers( 25 );

    write("Fibonacci Numbers: ");
    leonardoNumbers( 25, 0, 1, 0 );
}

void leonardoNumbers(int count, int l0=1, int l1=1, int add=1) {
    int t;
    for (int i=0; i<count; ++i) {
        write(l0, " ");
        t = l0 + l1 + add;
        l0 = l1;
        l1 = t;
    }
    writeln();
}


open System

let leo l0 l1 d =
    Seq.unfold (fun (x, y) -> Some (x, (y, x + y + d))) (l0, l1)

let leonardo = leo 1 1 1
let fibonacci = leo 0 1 0

[<EntryPoint>]
let main _ =
    let leoNums = Seq.take 25 leonardo |> Seq.chunkBySize 16
    printfn "First 25 of the (1, 1, 1) Leonardo numbers:\n%A" leoNums
    Console.WriteLine()

    let fibNums = Seq.take 25 fibonacci |> Seq.chunkBySize 16
    printfn "First 25 of the (0, 1, 0) Leonardo numbers (= Fibonacci number):\n%A" fibNums

    0 // return an integer exit code


USING: fry io kernel math prettyprint sequences ;
IN: rosetta-code.leonardo-numbers

: first25-leonardo ( vector add -- seq )
    23 swap '[ dup 2 tail* sum _ + over push ] times ;

: print-leo ( seq -- ) [ pprint bl ] each nl ;

"First 25 Leonardo numbers:" print
V{ 1 1 } 1 first25-leonardo print-leo

"First 25 Leonardo numbers with L(0)=0, L(1)=1, add=0:" print
V{ 0 1 } 0 first25-leonardo print-leo


#lang racket

(define (mult A B)
  (define nums
    (let loop ([B B] [zeros '()])
      (if (null? B)
        '()
        (cons (append zeros (let loop ([c 0] [A A])
                              (cond [(pair? A)
                                     (define-values [q r]
                                       (quotient/remainder
                                        (+ c (* (car A) (car B)))
                                        10))
                                     (cons r (loop q (cdr A)))]
                                    [(zero? c) '()]
                                    [else (list c)])))
              (loop (cdr B) (cons 0 zeros))))))
  (let loop ([c 0] [nums nums])
    (if (null? nums)
      '()
      (let-values ([(q r) (quotient/remainder (apply + c (map car nums)) 10)])
        (cons r (loop q (filter pair? (map cdr nums))))))))

(define (number->list n)
  (if (zero? n) '()
      (let-values ([(q r) (quotient/remainder n 10)])
        (cons r (number->list q)))))

(define 2^64 (number->list (expt 2 64)))
(for-each display (reverse (mult 2^64 2^64))) (newline)
;; for comparison
(* (expt 2 64) (expt 2 64))

;; Output:
;; 340282366920938463463374607431768211456
;; 340282366920938463463374607431768211456


Func Leonardo(size, l0, l1, add) =
    Array leo[1,size];             {set up as a row rather than column vector; looks nicer to print}
    leo[1,1]:=l0; leo[1,2]:=l1;    {fermat arrays are 1-indexed}
    for i=3 to size do
        leo[1,i]:=leo[1,i-2]+leo[1,i-1]+add;
    od;
    .;

Leonardo(25, 1, 1, 1);
[leo];

Leonardo(25, 0, 1, 0);
[leo];


      SUBROUTINE LEONARDO(LAST,L0,L1,AF)	!Show the first LAST values of the sequence.
       INTEGER LAST	!Limit to show.
       INTEGER L0,L1	!Starting values.
       INTEGER AF	!The "Add factor" to deviate from Fibonacci numbers.
       OPTIONAL AF	!Indicate that this parameter may be omitted.
       INTEGER EMBOLISM	!The bloat to employ.
       INTEGER N,LN,LNL1,LNL2	!Assistants to the calculation.
        IF (PRESENT(AF)) THEN	!Perhaps the last parameter has not been given.
          EMBOLISM = AF			!It has. Take its value.
         ELSE			!But if not,
          EMBOLISM = 1			!This is the specified default.
        END IF			!Perhaps there should be some report on this?
        WRITE (6,1) LAST,L0,L1,EMBOLISM	!Announce.
    1   FORMAT ("The first ",I0,	!The I0 format code avoids excessive spacing.
     1   " numbers in the Leonardo sequence defined by L(0) = ",I0,
     2   " and L(1) = ",I0," with L(n) = L(n - 1) + L(n - 2) + ",I0)
        IF (LAST .GE. 1) WRITE (6,2) L0	!In principle, LAST may be small.
        IF (LAST .GE. 2) WRITE (6,2) L1	!!So, suspicion rules.
    2   FORMAT (I0,", ",$)	!Obviously, the $ sez "don't finish the line".
        LNL1 = L0	!Syncopation for the sequence's initial values.
        LN = L1		!Since the parameters ought not be damaged.
        DO N = 3,LAST	!Step away.
          LNL2 = LNL1		!Advance the two state variables one step.
          LNL1 = LN		!Ready to make a step forward.
          LN = LNL1 + LNL2 + EMBOLISM	!Thus.
          WRITE (6,2) LN	!Reveal the value. Overflow is distant...
        END DO		!On to the next step.
        WRITE (6,*)	!Finish the line.
      END SUBROUTINE LEONARDO	!Only speedy for the sequential production of values.

      PROGRAM POKE

      CALL LEONARDO(25,1,1,1)	!The first 25 Leonardo numbers.
      CALL LEONARDO(25,0,1,0)	!Deviates to give the Fibonacci sequence.
      END


Sub leonardo(L0 As Integer, L1 As Integer, suma As Integer, texto As String)
    Dim As Integer i, tmp
    Print "Numeros de " &texto &" (" &L0 &"," &L1 &"," &suma &"):"
    For i = 1 To 25
        If i = 1 Then
            Print L0;
        Elseif i = 2 Then
            Print L1;
        Else
            Print L0 + L1 + suma;
            tmp = L0
            L0 = L1
            L1 = tmp + L1 + suma
        End If
    Next i
    Print Chr(10)
End Sub

'--- Programa Principal ---
leonardo(1,1,1,"Leonardo")
leonardo(0,1,0,"Fibonacci")
End


sub num_to_groups ( $num ) { $num.flip.comb(/.**1..4/)».flip     };
sub groups_to_num ( @g   ) { [~] flat @g.pop, @g.reverse».fmt('%04d') };

sub long_multiply ( Str $x, Str $y ) {
    my @group_sums;
    for flat num_to_groups($x).pairs X num_to_groups($y).pairs -> $xp, $yp {
        @group_sums[ $xp.key + $yp.key ] += $xp.value * $yp.value;
    }

    for @group_sums.keys -> $k {
        next if @group_sums[$k] < 10000;
        @group_sums[$k+1] += @group_sums[$k].Int div 10000;
        @group_sums[$k] %= 10000;
    }

    return groups_to_num @group_sums;
}

my $str = '18446744073709551616';
long_multiply( $str, $str ).say;

# cross-check with native implementation
say +$str * +$str;


package main

import "fmt"

func leonardo(n, l0, l1, add int) []int {
    leo := make([]int, n)
    leo[0] = l0
    leo[1] = l1
    for i := 2; i < n; i++ {
        leo[i] = leo[i - 1] + leo[i - 2] + add
    }
    return leo
}

func main() {
    fmt.Println("The first 25 Leonardo numbers with L[0] = 1, L[1] = 1 and add number = 1 are:")
    fmt.Println(leonardo(25, 1, 1, 1))
    fmt.Println("\nThe first 25 Leonardo numbers with L[0] = 0, L[1] = 1 and add number = 0 are:")
    fmt.Println(leonardo(25, 0, 1, 0))
}


import Data.List (intercalate, unfoldr)
import Data.List.Split (chunksOf)

--------------------- LEONARDO NUMBERS ---------------------
-- L0 -> L1 -> Add number -> Series (infinite)
leo :: Integer -> Integer -> Integer -> [Integer]
leo l0 l1 d = unfoldr (\(x, y) -> Just (x, (y, x + y + d))) (l0, l1)

leonardo :: [Integer]
leonardo = leo 1 1 1

fibonacci :: [Integer]
fibonacci = leo 0 1 0

--------------------------- TEST ---------------------------
main :: IO ()
main =
  (putStrLn . unlines)
    [ "First 25 default (1, 1, 1) Leonardo numbers:\n"
    , f $ take 25 leonardo
    , "First 25 of the (0, 1, 0) Leonardo numbers (= Fibonacci numbers):\n"
    , f $ take 25 fibonacci
    ]
  where
    f = unlines . fmap (('\t' :) . intercalate ",") . chunksOf 16 . fmap show


/*REXX program  performs  long multiplication  on  two numbers  (without the "E").      */
numeric digits 300                               /*be able to handle gihugeic input #s. */
parse arg x y .                                  /*obtain optional arguments from the CL*/
if x=='' | x==","  then x= 2**64                 /*Not specified?  Then use the default.*/
if y=='' | y==","  then y= x                     /* "      "         "   "   "     "    */
if x<0  &&  y<0    then sign= '-'                /*there only a single negative number? */
                   else sign=                    /*no, then result sign must be positive*/
xx=x;    x=strip(x, 'T', .);      x1= left(x, 1) /*remove any trailing decimal points.  */
yy=y;    y=strip(y, 'T', .);      y1= left(y, 1) /*   "    "     "        "       "     */
if x1=='-' | x1=="+"  then x= substr(x, 2)       /*remove a leading  ±  sign.           */
if y1=='-' | y1=="+"  then y= substr(y, 2)       /*   "   "    "     "    "             */
parse var x  '.' xf;  parse var y  "." yf        /*obtain the fractional part of X and Y*/
#= length(xf || yf)                              /*#: digits past the decimal points (.)*/
x= space( translate( x, , .),  0)                /*remove decimal point if there is any.*/
y= space( translate( y, , .),  0)                /*   "       "     "    "    "   "  "  */
Lx= length(x);  Ly=length(y)                     /*get the lengths of the new  X and Y. */
numeric digits max(digits(), Lx + Ly)            /*use a new  decimal digits  precision.*/
$= 0                                             /*$:  is the product  (so far).        */
                  do j=Ly  by -1  for Ly         /*almost like REXX does it, ··· but no.*/
                  $= $  +  ((x*substr(y, j, 1))copies(0, Ly-j) )
                  end   /*j*/
f= length($) - #                                 /*does product has enough decimal digs?*/
if f<0  then $=copies(0, abs(f) + 1)$            /*Negative?  Add leading 0s for INSERT.*/
say 'long mult:'  xx  "*"  yy  '──►'   sign || strip( insert(., $, length($) - #), 'T', .)
say ' built─in:'  xx  "*"  yy  '──►'   xx*yy     /*stick a fork in it,  we're all done. */


import java.util.Arrays;
import java.util.List;

@SuppressWarnings("SameParameterValue")
public class LeonardoNumbers {
    private static List<Integer> leonardo(int n) {
        return leonardo(n, 1, 1, 1);
    }

    private static List<Integer> leonardo(int n, int l0, int l1, int add) {
        Integer[] leo = new Integer[n];
        leo[0] = l0;
        leo[1] = l1;
        for (int i = 2; i < n; i++) {
            leo[i] = leo[i - 1] + leo[i - 2] + add;
        }
        return Arrays.asList(leo);
    }

    public static void main(String[] args) {
        System.out.println("The first 25 Leonardo numbers with L[0] = 1, L[1] = 1 and add number = 1 are:");
        System.out.println(leonardo(25));
        System.out.println("\nThe first 25 Leonardo numbers with L[0] = 0, L[1] = 1 and add number = 0 are:");
        System.out.println(leonardo(25, 0, 1, 0));
    }
}


const leoNum = (c, l0 = 1, l1 = 1, add = 1) =>
    new Array(c).fill(add).reduce(
        (p, c, i) => i > 1 ? (
            p.push(p[i - 1] + p[i - 2] + c) && p
        ) : p, [l0, l1]
    );

console.log(leoNum(25));
console.log(leoNum(25, 0, 1, 0));


decimals(0)
see pow(2,64)*pow(2,64) + nl


def longmult(x,y)
  result = [0]
  j = 0
  y.digits.each do |m|
    c = 0
    i = j
    x.digits.each do |d|
      v = result[i]
      result << 0 if v.zero?
      c, v = (v + c + d*m).divmod(10)
      result[i] = v
      i += 1
    end
    result[i] += c
    j += 1
  end
  # calculate the answer from the result array of digits
  result.reverse.inject(0) {|sum, n| 10*sum + n}
end

n=2**64
printf "         %d * %d = %d\n", n, n, n*n
printf "longmult(%d, %d) = %d\n", n, n, longmult(n,n)


def Leonardo(zero; one; incr):
  def leo:
    if . == 0 then zero
    elif . == 1 then one
    else ((.-1) |leo) + ((.-2) | leo) +  incr
    end;
  leo;


function L(n, add::Int=1, firsts::Vector=[1, 1])
    l = max(maximum(n) .+ 1, length(firsts))
    r = Vector{Int}(l)
    r[1:length(firsts)] = firsts
    for i in 3:l
        r[i] = r[i - 1] + r[i - 2] + add
    end
    return r[n .+ 1]
end

# Task 1
println("First 25 Leonardo numbers: ", join(L(0:24), ", "))

# Task 2
@show L(0) L(1)

# Task 4
println("First 25 Leonardo numbers starting with [0, 1]: ", join(L(0:24, 0, [0, 1]), ", "))


// version 1.1.2

fun leonardo(n: Int, l0: Int = 1, l1: Int = 1, add: Int = 1): IntArray {
    val leo = IntArray(n)
    leo[0] = l0
    leo[1] = l1
    for (i in 2 until n) leo[i] = leo[i - 1] + leo[i - 2] + add
    return leo
}

fun main(args: Array<String>) {
    println("The first 25 Leonardo numbers with L[0] = 1, L[1] = 1 and add number = 1 are:")
    println(leonardo(25).joinToString(" "))
    println("\nThe first 25 Leonardo numbers with L[0] = 0, L[1] = 1 and add number = 0 are:")
    println(leonardo(25, 0, 1, 0).joinToString(" "))
}


function leoNums (n, L0, L1, add)
  local L0, L1, add = L0 or 1, L1 or 1, add or 1
  local lNums, nextNum = {L0, L1}
  while #lNums < n do
    nextNum = lNums[#lNums] + lNums[#lNums - 1] + add
    table.insert(lNums, nextNum)
  end
  return lNums
end

function show (msg, t)
  print(msg .. ":")
  for i, x in ipairs(t) do
    io.write(x .. " ")
  end
  print("\n")
end

show("Leonardo numbers", leoNums(25))
show("Fibonacci numbers", leoNums(25, 0, 1, 0))