Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,34 +0,0 @@
|
|||
package Long_Multiplication is
|
||||
type Number (<>) is private;
|
||||
|
||||
Zero : constant Number;
|
||||
One : constant Number;
|
||||
|
||||
function Value (Item : in String) return Number;
|
||||
function Image (Item : in Number) return String;
|
||||
|
||||
overriding
|
||||
function "=" (Left, Right : in Number) return Boolean;
|
||||
|
||||
function "+" (Left, Right : in Number) return Number;
|
||||
function "*" (Left, Right : in Number) return Number;
|
||||
|
||||
function Trim (Item : in Number) return Number;
|
||||
private
|
||||
Bits : constant := 16;
|
||||
Base : constant := 2 ** Bits;
|
||||
|
||||
type Accumulated_Value is range 0 .. (Base - 1) * Base;
|
||||
subtype Digit is Accumulated_Value range 0 .. Base - 1;
|
||||
|
||||
type Number is array (Natural range <>) of Digit;
|
||||
for Number'Component_Size use Bits; -- or pragma Pack (Number);
|
||||
|
||||
Zero : constant Number := (1 .. 0 => 0);
|
||||
One : constant Number := (0 => 1);
|
||||
|
||||
procedure Divide (Dividend : in Number;
|
||||
Divisor : in Digit;
|
||||
Result : out Number;
|
||||
Remainder : out Digit);
|
||||
end Long_Multiplication;
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
package body Long_Multiplication is
|
||||
function Value (Item : in String) return Number is
|
||||
subtype Base_Ten_Digit is Digit range 0 .. 9;
|
||||
Ten : constant Number := (0 => 10);
|
||||
begin
|
||||
case Item'Length is
|
||||
when 0 =>
|
||||
raise Constraint_Error;
|
||||
when 1 =>
|
||||
return (0 => Base_Ten_Digit'Value (Item));
|
||||
when others =>
|
||||
return (0 => Base_Ten_Digit'Value (Item (Item'Last .. Item'Last)))
|
||||
+ Ten * Value (Item (Item'First .. Item'Last - 1));
|
||||
end case;
|
||||
end Value;
|
||||
|
||||
function Image (Item : in Number) return String is
|
||||
Base_Ten : constant array (Digit range 0 .. 9) of String (1 .. 1) :=
|
||||
("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
Result : Number (0 .. Item'Last);
|
||||
Remainder : Digit;
|
||||
begin
|
||||
if Item = Zero then
|
||||
return "0";
|
||||
else
|
||||
Divide (Dividend => Item,
|
||||
Divisor => 10,
|
||||
Result => Result,
|
||||
Remainder => Remainder);
|
||||
|
||||
if Result = Zero then
|
||||
return Base_Ten (Remainder);
|
||||
else
|
||||
return Image (Trim (Result)) & Base_Ten (Remainder);
|
||||
end if;
|
||||
end if;
|
||||
end Image;
|
||||
|
||||
overriding
|
||||
function "=" (Left, Right : in Number) return Boolean is
|
||||
begin
|
||||
for Position in Integer'Min (Left'First, Right'First) ..
|
||||
Integer'Max (Left'Last, Right'Last) loop
|
||||
if Position in Left'Range and Position in Right'Range then
|
||||
if Left (Position) /= Right (Position) then
|
||||
return False;
|
||||
end if;
|
||||
elsif Position in Left'Range then
|
||||
if Left (Position) /= 0 then
|
||||
return False;
|
||||
end if;
|
||||
elsif Position in Right'Range then
|
||||
if Right (Position) /= 0 then
|
||||
return False;
|
||||
end if;
|
||||
else
|
||||
raise Program_Error;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return True;
|
||||
end "=";
|
||||
|
||||
function "+" (Left, Right : in Number) return Number is
|
||||
Result : Number (Integer'Min (Left'First, Right'First) ..
|
||||
Integer'Max (Left'Last , Right'Last) + 1);
|
||||
Accumulator : Accumulated_Value := 0;
|
||||
Used : Integer := Integer'First;
|
||||
begin
|
||||
for Position in Result'Range loop
|
||||
if Position in Left'Range then
|
||||
Accumulator := Accumulator + Left (Position);
|
||||
end if;
|
||||
|
||||
if Position in Right'Range then
|
||||
Accumulator := Accumulator + Right (Position);
|
||||
end if;
|
||||
|
||||
Result (Position) := Accumulator mod Base;
|
||||
Accumulator := Accumulator / Base;
|
||||
|
||||
if Result (Position) /= 0 then
|
||||
Used := Position;
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
if Accumulator = 0 then
|
||||
return Result (Result'First .. Used);
|
||||
else
|
||||
raise Constraint_Error;
|
||||
end if;
|
||||
end "+";
|
||||
|
||||
function "*" (Left, Right : in Number) return Number is
|
||||
Accumulator : Accumulated_Value;
|
||||
Result : Number (Left'First + Right'First ..
|
||||
Left'Last + Right'Last + 1) := (others => 0);
|
||||
Used : Integer := Integer'First;
|
||||
begin
|
||||
for L in Left'Range loop
|
||||
for R in Right'Range loop
|
||||
Accumulator := Left (L) * Right (R);
|
||||
|
||||
for Position in L + R .. Result'Last loop
|
||||
exit when Accumulator = 0;
|
||||
|
||||
Accumulator := Accumulator + Result (Position);
|
||||
Result (Position) := Accumulator mod Base;
|
||||
Accumulator := Accumulator / Base;
|
||||
Used := Position;
|
||||
end loop;
|
||||
end loop;
|
||||
end loop;
|
||||
|
||||
return Result (Result'First .. Used);
|
||||
end "*";
|
||||
|
||||
procedure Divide (Dividend : in Number;
|
||||
Divisor : in Digit;
|
||||
Result : out Number;
|
||||
Remainder : out Digit) is
|
||||
Accumulator : Accumulated_Value := 0;
|
||||
begin
|
||||
Result := (others => 0);
|
||||
|
||||
for Position in reverse Dividend'Range loop
|
||||
Accumulator := Accumulator * Base + Dividend (Position);
|
||||
Result (Position) := Accumulator / Divisor;
|
||||
Accumulator := Accumulator mod Divisor;
|
||||
end loop;
|
||||
|
||||
Remainder := Accumulator;
|
||||
end Divide;
|
||||
|
||||
function Trim (Item : in Number) return Number is
|
||||
begin
|
||||
for Position in reverse Item'Range loop
|
||||
if Item (Position) /= 0 then
|
||||
return Item (Item'First .. Position);
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
return Zero;
|
||||
end Trim;
|
||||
end Long_Multiplication;
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
with Ada.Text_IO;
|
||||
with Long_Multiplication;
|
||||
|
||||
procedure Test_Long_Multiplication is
|
||||
use Ada.Text_IO, Long_Multiplication;
|
||||
|
||||
N : Number := Value ("18446744073709551616");
|
||||
M : Number := N * N;
|
||||
begin
|
||||
Put_Line (Image (N) & " * " & Image (N) & " = " & Image (M));
|
||||
end Test_Long_Multiplication;
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
type Long_Number is array (Natural range <>) of Unsigned_32;
|
||||
|
||||
function "*" (Left, Right : Long_Number) return Long_Number is
|
||||
Result : Long_Number (0..Left'Length + Right'Length - 1) := (others => 0);
|
||||
Accum : Unsigned_64;
|
||||
begin
|
||||
for I in Left'Range loop
|
||||
for J in Right'Range loop
|
||||
Accum := Unsigned_64 (Left (I)) * Unsigned_64 (Right (J));
|
||||
for K in I + J..Result'Last loop
|
||||
exit when Accum = 0;
|
||||
Accum := Accum + Unsigned_64 (Result (K));
|
||||
Result (K) := Unsigned_32 (Accum and 16#FFFF_FFFF#);
|
||||
Accum := Accum / 2**32;
|
||||
end loop;
|
||||
end loop;
|
||||
end loop;
|
||||
for Index in reverse Result'Range loop -- Normalization
|
||||
if Result (Index) /= 0 then
|
||||
return Result (0..Index);
|
||||
end if;
|
||||
end loop;
|
||||
return (0 => 0);
|
||||
end "*";
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
procedure Div
|
||||
( Dividend : in out Long_Number;
|
||||
Last : in out Natural;
|
||||
Remainder : out Unsigned_32;
|
||||
Divisor : Unsigned_32
|
||||
) is
|
||||
Div : constant Unsigned_64 := Unsigned_64 (Divisor);
|
||||
Accum : Unsigned_64 := 0;
|
||||
Size : Natural := 0;
|
||||
begin
|
||||
for Index in reverse Dividend'First..Last loop
|
||||
Accum := Accum * 2**32 + Unsigned_64 (Dividend (Index));
|
||||
Dividend (Index) := Unsigned_32 (Accum / Div);
|
||||
if Size = 0 and then Dividend (Index) /= 0 then
|
||||
Size := Index;
|
||||
end if;
|
||||
Accum := Accum mod Div;
|
||||
end loop;
|
||||
Remainder := Unsigned_32 (Accum);
|
||||
Last := Size;
|
||||
end Div;
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||
with Ada.Text_IO; use Ada.Text_IO;
|
||||
with Interfaces; use Interfaces;
|
||||
|
||||
procedure Long_Multiplication is
|
||||
-- Insert definitions above here
|
||||
procedure Put (Value : Long_Number) is
|
||||
X : Long_Number := Value;
|
||||
Last : Natural := X'Last;
|
||||
Digit : Unsigned_32;
|
||||
Result : Unbounded_String;
|
||||
begin
|
||||
loop
|
||||
Div (X, Last, Digit, 10);
|
||||
Append (Result, Character'Val (Digit + Character'Pos ('0')));
|
||||
exit when Last = 0 and then X (0) = 0;
|
||||
end loop;
|
||||
for Index in reverse 1..Length (Result) loop
|
||||
Put (Element (Result, Index));
|
||||
end loop;
|
||||
end Put;
|
||||
|
||||
X : Long_Number := (0 => 0, 1 => 0, 2 => 1) * (0 => 0, 1 => 0, 2 => 1);
|
||||
begin
|
||||
Put (X);
|
||||
end Long_Multiplication;
|
||||
|
|
@ -1,46 +1 @@
|
|||
; The following two functions assume the 7-bit encoding is ASCII.
|
||||
char2BCD: function [c] [
|
||||
return (and (to :integer c) 15) % 10
|
||||
]
|
||||
BCD2char: function [i] [
|
||||
return (to :char (or i 48))
|
||||
]
|
||||
|
||||
multiplyBCD: function [u v] [
|
||||
m: size u
|
||||
n: size v
|
||||
w: array.of: (m + n) `0`
|
||||
|
||||
predm: m - 1
|
||||
predn: n - 1
|
||||
predszw: (size w) - 1
|
||||
|
||||
; Long multiplication. See Algorithm 4.3.1M in Volume 2 of Knuth,
|
||||
; ‘The Art of Computer Programming’. Here b = 10. Only the less
|
||||
; significant nibble of a character is considered. Thus zero can be
|
||||
; represented by either `0` or ` `, and other digits by their
|
||||
; respective ASCII characters.
|
||||
loop 0..predn 'j [
|
||||
vj: char2BCD v\[predn - j]
|
||||
if? vj = 0 [
|
||||
set w (predn - j) `0`
|
||||
] else [
|
||||
carry: 0
|
||||
loop 0..predm 'i [
|
||||
ui: char2BCD u\[predm - i]
|
||||
wij: char2BCD w\[predszw - (i + j)]
|
||||
t: (ui * vj) + wij + carry
|
||||
[carry digit]: divmod t 10
|
||||
set w (predszw - (i + j)) (BCD2char digit)
|
||||
]
|
||||
set w (predn - j) (BCD2char carry)
|
||||
]
|
||||
]
|
||||
|
||||
return join w
|
||||
]
|
||||
|
||||
twoRaised64: "18446744073709551616"
|
||||
twoRaised128: multiplyBCD twoRaised64 twoRaised64
|
||||
|
||||
print twoRaised128
|
||||
print 2^64 * 2
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
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)})
|
||||
|
|
@ -1,3 +1,46 @@
|
|||
##
|
||||
# Show how to implement big number multiplication (even though Icon and Unicon
|
||||
# handle big numbers transparently...)
|
||||
global dpw, maxs
|
||||
|
||||
procedure main()
|
||||
write(2^64*2^64)
|
||||
dpw := 10
|
||||
maxs := 10^dpw
|
||||
every (n1|n2) := cvt2bn(2^64)
|
||||
write(2^64)
|
||||
write(2^64*2^64) # How one really does multiply in Icon and Unicon
|
||||
write(bn2str(bnmult(n1,n2))) # How this challenge wants it done
|
||||
end
|
||||
|
||||
procedure bnmult(n1,n2)
|
||||
n := [0]
|
||||
k := 1
|
||||
if *n1 > *n2 then n1 :=: n2
|
||||
every i := 1 to *n1 do {
|
||||
every j := 1 to *n2 do {
|
||||
if k > *n then put(n,0)
|
||||
x := n1[i]*n2[j]
|
||||
r := x/maxs
|
||||
n[k] +:= x%maxs
|
||||
if r > 0 then {
|
||||
if k = *n then put(n,0)
|
||||
n[k+1] +:= r
|
||||
}
|
||||
k +:= 1
|
||||
}
|
||||
k := i+1
|
||||
}
|
||||
return n
|
||||
end
|
||||
|
||||
procedure cvt2bn(n)
|
||||
bn := []
|
||||
while (n > 0, put(bn,n%maxs), n /:= maxs)
|
||||
return bn
|
||||
end
|
||||
|
||||
procedure bn2str(bn)
|
||||
s := ""||bn[-1]
|
||||
every s ||:= right(bn[*bn-1 to 1 by -1],dpw,"0")
|
||||
return s
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
# 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"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[BigInt]$n = [Math]::Pow(2,64)
|
||||
[BigInt]::Multiply($n,$n)
|
||||
Loading…
Add table
Add a link
Reference in a new issue