From 71ad025aaf2b888119d4ac080cf5ac4c8c3a0b52 Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Thu, 14 Nov 2019 19:03:13 +0100 Subject: [PATCH 01/14] random.passwords: new vocab --- basis/random/passwords/authors.txt | 1 + basis/random/passwords/passwords-docs.factor | 48 +++++++++++++++++++ basis/random/passwords/passwords-tests.factor | 14 ++++++ basis/random/passwords/passwords.factor | 27 +++++++++++ 4 files changed, 90 insertions(+) create mode 100644 basis/random/passwords/authors.txt create mode 100644 basis/random/passwords/passwords-docs.factor create mode 100644 basis/random/passwords/passwords-tests.factor create mode 100644 basis/random/passwords/passwords.factor diff --git a/basis/random/passwords/authors.txt b/basis/random/passwords/authors.txt new file mode 100644 index 0000000000..8e1955f8e1 --- /dev/null +++ b/basis/random/passwords/authors.txt @@ -0,0 +1 @@ +Alexander Ilin diff --git a/basis/random/passwords/passwords-docs.factor b/basis/random/passwords/passwords-docs.factor new file mode 100644 index 0000000000..7f9d9dfc34 --- /dev/null +++ b/basis/random/passwords/passwords-docs.factor @@ -0,0 +1,48 @@ +! Copyright (C) 2019 Alexander Ilin. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax kernel random strings ; +IN: random.passwords + +ABOUT: "random.passwords" + +ARTICLE: "random.passwords" "Generating random passwords" +"The " { $vocab-link "random.passwords" } " vocab provides functions for generation of random passwords." +$nl +"Generate password of a given length from some often used character sets:" +{ $subsections alnum-password hex-password ascii-password } +"Generate a password from a custom character set:" +{ $subsections password } +; + +HELP: password +{ $values + { "n" "password length" } + { "charset" string } + { "string" string } +} +{ $description "Generate a password of length " { $snippet "n" } " by randomly selecting characters from the " { $snippet "charset" } " string. All characters of the " { $snippet "charset" } " have equal probability of appearing at any position of the result." +$nl +"If " { $snippet "n" } " = 0, return empty string. If " { $snippet "n" } " < 0, throw an error." +$nl +{ $link secure-random-generator } " is used as the randomness source." } ; + +HELP: alnum-password +{ $values + { "n" "password length" } + { "string" string } +} +{ $description "Generate a random password consisting of " { $snippet "n" } " alphanumeric characters (0..9, A..Z, a..z)." } ; + +HELP: ascii-password +{ $values + { "n" "password length" } + { "string" string } +} +{ $description "Generate a random password consisting of " { $snippet "n" } " printable ASCII characters." } ; + +HELP: hex-password +{ $values + { "n" "password length" } + { "string" string } +} +{ $description "Generate a random password consisting of " { $snippet "n" } " hexadecimal characters (0..9, A..F)." } ; diff --git a/basis/random/passwords/passwords-tests.factor b/basis/random/passwords/passwords-tests.factor new file mode 100644 index 0000000000..b47e682c37 --- /dev/null +++ b/basis/random/passwords/passwords-tests.factor @@ -0,0 +1,14 @@ +! Copyright (C) 2019 Alexander Ilin. +! See http://factorcode.org/license.txt for BSD license. +USING: math math.parser random.passwords sequences tools.test ; +IN: random.passwords.tests + +{ "aaaaaaaaaa" } [ 10 "a" password ] unit-test +{ 10 } [ 10 "ab" password length ] unit-test +{ "" } [ 0 "ab" password ] unit-test +[ -1 "ab" password ] must-fail + +{ 2 } [ 2 ascii-password length ] unit-test +{ 3 } [ 3 alnum-password length ] unit-test +{ 4 } [ 4 hex-password length ] unit-test +{ t } [ 4 hex-password hex> 65535 <= ] unit-test diff --git a/basis/random/passwords/passwords.factor b/basis/random/passwords/passwords.factor new file mode 100644 index 0000000000..44cd127efd --- /dev/null +++ b/basis/random/passwords/passwords.factor @@ -0,0 +1,27 @@ +! Copyright (C) 2019 Alexander Ilin. +! See http://factorcode.org/license.txt for BSD license. +USING: fry literals math.ranges random sequences ; +IN: random.passwords + + + +: password ( n charset -- string ) + '[ [ _ random ] "" replicate-as ] with-secure-random ; + +: ascii-password ( n -- string ) + ascii-printable-charset password ; + +: hex-password ( n -- string ) + hex-charset password ; + +: alnum-password ( n -- string ) + alphanum-charset password ; From ce0584adcb51b66cc96549c67f7eb42fe724ddf0 Mon Sep 17 00:00:00 2001 From: Nandeeka Nayak Date: Tue, 29 Oct 2019 10:09:38 -0700 Subject: [PATCH 03/14] tensors: create basic tensors vocabulary. tensors: create tensors vocabulary. tensors: create file heading tensors: define tensor constructor. tensors: add additional constructors. tensors: add reshaping. tensors: implement add and include tests. tensors: add binary operations. tensors: add scalar multiply. tensors: added >array functionality tensors: tests for >array tensors: unit tests fix tensors: use more idiomatic >array. tensors: add multi-methods for scalar multiplication. tensors: cleaned up >array tensors: combine a few constructors tensors: added dims function and unit tests. tensors: add documentation capabilities. tensors: added multi-methods for scalar addition/subtraction/division help.lint.coverage: fix for shadowing "empty" word; prevent the other test-only words from being shadowed too soundex: move to extra as it's unused; fix authors.txt filename modify arange to match numpy; replace with naturals create >float-array for efficient float array construction use combinators tensors: documentation added for public functions. tensors: implement t% and matrix multiplication. tensors: add slice with non-zero step tensors: add documentation. tensors: added transposition funcitonality, with documentation and tests tensors: add error documentation. Add error documentation tensors: fix matmul documentation. extra/tensors: add tests for arange tensors: make transpose style more similar tensors: make some of the PR changes. tensors: separate shape checking. tensors: add documentation for non-positive-shape-error. tensors: add missing comment. tensors: transpose edits for efficiency --- .../tensor-slice/tensor-slice-tests.factor | 12 + .../tensors/tensor-slice/tensor-slice.factor | 26 + extra/tensors/tensors-docs.factor | 136 +++++ extra/tensors/tensors-tests.factor | 530 ++++++++++++++++++ extra/tensors/tensors.factor | 245 ++++++++ 5 files changed, 949 insertions(+) create mode 100644 extra/tensors/tensor-slice/tensor-slice-tests.factor create mode 100644 extra/tensors/tensor-slice/tensor-slice.factor create mode 100644 extra/tensors/tensors-docs.factor create mode 100644 extra/tensors/tensors-tests.factor create mode 100644 extra/tensors/tensors.factor diff --git a/extra/tensors/tensor-slice/tensor-slice-tests.factor b/extra/tensors/tensor-slice/tensor-slice-tests.factor new file mode 100644 index 0000000000..a2bdb87526 --- /dev/null +++ b/extra/tensors/tensor-slice/tensor-slice-tests.factor @@ -0,0 +1,12 @@ +USING: arrays sequences tensors.tensor-slice tools.test ; +IN: tensors.tensor-slice.tests + +{ { 9 7 5 } } [ -1 -6 -2 10 >array ] unit-test +{ { 9 7 } } [ -1 -5 -2 10 >array ] unit-test +{ { 9 7 } } [ -1 -4 -2 10 >array ] unit-test +{ { 9 } } [ -1 -3 -2 10 >array ] unit-test +{ { } } [ -4 10 -2 10 >array ] unit-test +{ { 6 8 } } [ -4 15 2 10 >array ] unit-test +{ { 1 3 } } [ 1 4 2 10 >array ] unit-test +{ { 1 3 } } [ 1 5 2 10 >array ] unit-test +{ { 1 3 5 } } [ 1 6 2 10 >array ] unit-test \ No newline at end of file diff --git a/extra/tensors/tensor-slice/tensor-slice.factor b/extra/tensors/tensor-slice/tensor-slice.factor new file mode 100644 index 0000000000..47124bf768 --- /dev/null +++ b/extra/tensors/tensor-slice/tensor-slice.factor @@ -0,0 +1,26 @@ +USING: accessors kernel locals math math.order sequences ; +IN: tensors.tensor-slice + +TUPLE: step-slice < slice { step integer read-only } ; +:: ( from to step seq -- step-slice ) + step zero? [ "can't be zero" throw ] when + seq length :> len + step 0 > [ + from [ 0 ] unless* + to [ len ] unless* + ] [ + from [ len ] unless* + to [ 0 ] unless* + ] if + [ dup 0 < [ len + ] when 0 len clamp ] bi@ + ! FIXME: make this work with steps + seq dup slice? [ collapse-slice ] when + step step-slice boa ; + +M: step-slice virtual@ + [ step>> * ] [ from>> + ] [ seq>> ] tri ; + +M: step-slice length + [ to>> ] [ from>> - ] [ step>> ] tri + dup 0 < [ [ neg 0 max ] dip neg ] when /mod + zero? [ 1 + ] unless ; \ No newline at end of file diff --git a/extra/tensors/tensors-docs.factor b/extra/tensors/tensors-docs.factor new file mode 100644 index 0000000000..34cc5f4c7d --- /dev/null +++ b/extra/tensors/tensors-docs.factor @@ -0,0 +1,136 @@ +! Copyright (C) 2019 HMC Clinic. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays help.markup help.syntax math sequences ; +IN: tensors + +ARTICLE: "tensors" "Tensors" "A " { $snippet "tensor" } " is a sequence " +"of floating point numbers " +"shaped into an n-dimensional matrix. It supports fast, scalable matrix " +"operations such as matrix multiplication and transposition as well as a " +"number of element-wise operations. Words for working with tensors are found " +"in the " { $vocab-link "tensors" } " vocabulary.\n\n" +"Tensors can be created " +"by calling one of four constructors:" +{ $subsections zeros ones naturals arange } +"They can be converted to the corresponding N-dimensional array with" +{ $subsections tensor>array } +"The number of dimensions can be extracted with:" +{ $subsections dims } +"Additionally, tensors can be reshaped with:" +{ $subsections reshape flatten } +"Tensors can be combined element-wise with other tensors as well as numbers with:" +{ $subsections t+ t- t* t/ t% } +"Finally, tensors support the following matrix operations:" +{ $subsections matmul transpose } ; + +ARTICLE: "tensor-operators" "Tensor Operators" "Info here" ; + +HELP: tensor +{ $class-description "A sequence of floating-point numbers consisting of an " +{ $snippet "underlying" } " C-style array and a " { $snippet "shape" } "." } ; + +HELP: shape-mismatch-error +{ $values { "shape1" sequence } { "shape2" sequence } } +{ $description "Throws a " { $link shape-mismatch-error } "." } +{ $error-description "Thrown by element-wise operations such as " { $link t+ } +", " { $link t- } ", " { $link t* } ", " { $link t/ } ", and " { $link t% } +" as well as matrix operations such as " { $link matmul } " if two tensors are " +"passed and they cannot be combined as desired because of a difference in the " +"shape." } ; + +HELP: non-positive-shape-error +{ $values { "shape" sequence } } +{ $description "Throws a " { $link non-positive-shape-error } "." } +{ $error-description "Thrown by operations such as " { $link zeros } ", " +{ $link ones } ", " { $link naturals } ", and " { $link reshape } +", which allow users to directly set the shape of a " { $link tensor } +", when the shape has zero or negative values." } ; + +HELP: zeros +{ $values { "shape" sequence } { "tensor" tensor } } +{ $description "Initializes a tensor with shape " { $snippet "shape" } +" containing all 0s." } +{ $errors "Throws a " { $link non-positive-shape-error } " if the given " +"shape has zero or negative values." } ; + +HELP: ones +{ $values { "shape" sequence } { "tensor" tensor } } +{ $description "Initializes a tensor with shape " { $snippet "shape" } +" containing all 1s." } +{ $errors "Throws a " { $link non-positive-shape-error } " if the given " +"shape has zero or negative values." } ; + +HELP: arange +{ $values { "a" number } { "b" number } { "step" number } { "tensor" tensor } } +{ $description "Initializes a one-dimensional tensor with values in a range from " + { $snippet "a" } " to " { $snippet "b" } " (inclusive) with step-size " { $snippet "step" } "." } ; + +HELP: naturals +{ $values { "shape" sequence } { "tensor" tensor } } +{ $description "Initializes a tensor with shape " { $snippet "shape" } +" containing a range of values from 0 to " { $snippet "shape product" } "." } +{ $errors "Throws a " { $link non-positive-shape-error } " if the given " +"shape has zero or negative values." } ; + +HELP: reshape +{ $values { "tensor" tensor } { "shape" sequence } { "tensor" tensor } } +{ $description "Reshapes " { $snippet "tensor" } " to have shape " +{ $snippet "shape" } "." } +{ $errors "Throws a " { $link non-positive-shape-error } " if the given " +"shape has zero or negative values." } ; + +HELP: flatten +{ $values { "tensor" tensor } { "tensor" tensor } } +{ $description "Reshapes " { $snippet "tensor" } " so that it is one-dimensional." } ; + +HELP: dims +{ $values { "tensor" tensor } { "n" integer } } +{ $description "Returns the dimension of " { $snippet "tensor" } "." } ; + +HELP: t+ +{ $values { "x" { $or tensor number } } { "y" { $or tensor number } } { "tensor" tensor } } +{ $description "Element-wise addition. Intakes two tensors or a tensor and a number (in either order)." } +{ $errors "Throws a " { $link shape-mismatch-error } " if passed two tensors that are " +"not (or cannot be broadcast to be) the same shape." } ; + +HELP: t- +{ $values { "x" { $or tensor number } } { "y" { $or tensor number } } { "tensor" tensor } } +{ $description "Element-wise subtraction. Intakes two tensors or a tensor and a number (in either order)." } +{ $errors "Throws a " { $link shape-mismatch-error } " if passed two tensors that are " +"not (or cannot be broadcast to be) the same shape." } ; + +HELP: t* +{ $values { "x" { $or tensor number } } { "y" { $or tensor number } } { "tensor" tensor } } +{ $description "Element-wise multiplication. Intakes two tensors or a tensor and a number (in either order)." } +{ $errors "Throws a " { $link shape-mismatch-error } " if passed two tensors that are " +"not (or cannot be broadcast to be) the same shape." } ; + +HELP: t/ +{ $values { "x" { $or tensor number } } { "y" { $or tensor number } } { "tensor" tensor } } +{ $description "Element-wise division. Intakes two tensors or a tensor and a number (in either order)." } +{ $errors "Throws a " { $link shape-mismatch-error } " if passed two tensors that are " +"not (or cannot be broadcast to be) the same shape." } ; + +HELP: t% +{ $values { "x" { $or tensor number } } { "y" { $or tensor number } } { "tensor" tensor } } +{ $description "Element-wise modulo operator. Intakes two tensors or a tensor and a number (in either order)." } +{ $errors "Throws a " { $link shape-mismatch-error } " if passed two tensors that are " +"not (or cannot be broadcast to be) the same shape." } ; + +HELP: tensor>array +{ $values { "tensor" tensor } { "seq" array } } +{ $description "Returns " { $snippet "tensor" } " as an n-dimensional array." } ; + +HELP: matmul +{ $values { "tensor1" tensor } { "tensor2" tensor } { "tensor3" tensor } } +{ $description "Performs n-dimensional matrix multiplication on two tensors, where " { $snippet "tensor1" } + " has shape " { $snippet "...xmxn" } " and " { $snippet "tensor1" } " has shape " { $snippet "...xnxp" } "." } +{ $errors "Throws a " { $link shape-mismatch-error } " if the bottom two " +"dimensions of the tensors passed do not take the form " { $snippet "mxn" } +" and " { $snippet "nxp" } " and/or the top dimensions do not match." } ; + +HELP: transpose +{ $values { "tensor" tensor } { "tensor'" tensor } } +{ $description "Performs n-dimensional matrix transposition on " { $snippet "tens" } "." } ; + +ABOUT: "tensors" diff --git a/extra/tensors/tensors-tests.factor b/extra/tensors/tensors-tests.factor new file mode 100644 index 0000000000..04c4ebe1b7 --- /dev/null +++ b/extra/tensors/tensors-tests.factor @@ -0,0 +1,530 @@ +! Copyright (C) 2019 HMC Clinic. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors alien.c-types kernel math math.order math.vectors +sequences specialized-arrays tensors tools.test ; +QUALIFIED-WITH: alien.c-types c +SPECIALIZED-ARRAY: c:float +IN: tensors.tests + +! Test zeros +{ float-array{ 0.0 0.0 0.0 0.0 } } [ + { 4 } zeros vec>> +] unit-test + +{ { 4 } } [ + { 4 } zeros shape>> +] unit-test + +{ float-array{ 0.0 0.0 0.0 0.0 } } [ + { 2 2 } zeros vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } zeros shape>> +] unit-test + +[ + { 0 5 } zeros +] +[ { 0 5 } \ non-positive-shape-error boa = ] must-fail-with + +[ + { -3 5 } zeros +] +[ { -3 5 } \ non-positive-shape-error boa = ] must-fail-with + +! Test ones +{ float-array{ 1.0 1.0 1.0 1.0 } } [ + { 4 } ones vec>> +] unit-test + +{ { 4 } } [ + { 4 } ones shape>> +] unit-test + +{ float-array{ 1.0 1.0 1.0 1.0 } } [ + { 2 2 } ones vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } ones shape>> +] unit-test + +[ + { 0 5 } ones +] +[ { 0 5 } \ non-positive-shape-error boa = ] must-fail-with + +[ + { -3 5 } ones +] +[ { -3 5 } \ non-positive-shape-error boa = ] must-fail-with + + +! Test arange +{ { 4 } float-array{ 0. 1. 2. 3. } } [ + 0 3 1 arange [ shape>> ] [ vec>> ] bi +] unit-test + +{ { 4 } float-array{ 0. 2. 4. 6. } } [ + 0 7 2 arange [ shape>> ] [ vec>> ] bi +] unit-test + +{ { 3 } float-array{ 1. 4. 7. } } [ + 1 9 3 arange [ shape>> ] [ vec>> ] bi +] unit-test + +{ { 5 } float-array{ 1. 3. 5. 7. 9. } } [ + 1 9 2 arange [ shape>> ] [ vec>> ] bi +] unit-test + + +! Test naturals +{ float-array{ 0.0 1.0 2.0 3.0 } } [ + { 4 } naturals vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals shape>> +] unit-test + +{ float-array{ 0.0 1.0 2.0 3.0 } } [ + { 2 2 } naturals vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } naturals shape>> +] unit-test + +[ + { 0 5 } naturals +] +[ { 0 5 } \ non-positive-shape-error boa = ] must-fail-with + +[ + { -3 5 } naturals +] +[ { -3 5 } \ non-positive-shape-error boa = ] must-fail-with + + +! Test reshape +{ float-array{ 0.0 0.0 0.0 0.0 } } [ + { 4 } zeros { 2 2 } reshape vec>> +] unit-test + +{ { 2 2 } } [ + { 4 } zeros { 2 2 } reshape shape>> +] unit-test + +[ + { 2 2 } zeros { 2 3 } reshape +] +[ { 2 2 } { 2 3 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 2 2 } zeros { -2 -2 } reshape +] +[ { -2 -2 } \ non-positive-shape-error boa = ] must-fail-with + +! Test flatten +{ float-array{ 0.0 0.0 0.0 0.0 } } [ + { 2 2 } zeros flatten vec>> +] unit-test + +{ { 4 } } [ + { 2 2 } zeros flatten shape>> +] unit-test + +{ float-array{ 0.0 0.0 0.0 0.0 } } [ + { 4 } zeros flatten vec>> +] unit-test + +{ { 4 } } [ + { 4 } zeros flatten shape>> +] unit-test + +! Test dims +{ 1 } [ + { 3 } zeros dims +] unit-test + +{ 2 } [ + { 2 2 } ones dims +] unit-test + +{ 3 } [ + { 1 2 3 } zeros dims +] unit-test + +! Test addition +{ float-array{ 1.0 2.0 3.0 4.0 } } [ + { 4 } naturals { 4 } ones t+ vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals { 4 } ones t+ shape>> +] unit-test + +{ float-array{ 1.0 2.0 3.0 4.0 } } [ + { 2 2 } naturals { 2 2 } ones t+ vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } naturals { 2 2 } ones t+ shape>> +] unit-test + +[ + { 3 } naturals { 2 2 } ones t+ vec>> +] +[ { 3 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 4 } naturals { 2 2 } ones t+ vec>> +] +[ { 4 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +! Test scalar addition +{ float-array{ 1.0 2.0 3.0 4.0 } } [ + { 4 } naturals 1 t+ vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals 1 t+ shape>> +] unit-test + +{ float-array{ 1.0 2.0 3.0 4.0 } } [ + 1 { 4 } naturals t+ vec>> +] unit-test + +{ { 4 } } [ + 1 { 4 } naturals t+ shape>> +] unit-test + +! Test subtraction +{ float-array{ -1.0 0.0 1.0 2.0 } } [ + { 4 } naturals { 4 } ones t- vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals { 4 } ones t- shape>> +] unit-test + +{ float-array{ -1.0 0.0 1.0 2.0 } } [ + { 2 2 } naturals { 2 2 } ones t- vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } naturals { 2 2 } ones t- shape>> +] unit-test + +[ + { 3 } naturals { 2 2 } ones t- vec>> +] +[ { 3 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 4 } naturals { 2 2 } ones t- vec>> +] +[ { 4 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +! Test scalar subtraction +{ float-array{ -1.0 0.0 1.0 2.0 } } [ + { 4 } naturals 1 t- vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals 1 t- shape>> +] unit-test + +{ float-array{ 1.0 0.0 -1.0 -2.0 } } [ + 1 { 4 } naturals t- vec>> +] unit-test + +{ { 4 } } [ + 1 { 4 } naturals t- shape>> +] unit-test + +! Test multiplication +{ float-array{ 0.0 1.0 4.0 9.0 } } [ + { 4 } naturals { 4 } naturals t* vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals { 4 } naturals t* shape>> +] unit-test + +{ float-array{ 0.0 1.0 4.0 9.0 } } [ + { 2 2 } naturals { 2 2 } naturals t* vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } naturals { 2 2 } naturals t* shape>> +] unit-test + +[ + { 3 } naturals { 2 2 } naturals t* vec>> +] +[ { 3 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 4 } naturals { 2 2 } naturals t* vec>> +] +[ { 4 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +! Test division +{ t } [ + { 4 } ones + { 4 } naturals { 4 } ones t+ + t/ vec>> + { 1.0 0.5 0.33333 0.25 } v- + [ abs ] map + 0 [ max ] reduce 0.0001 < +] unit-test + +{ { 4 } } [ + { 4 } ones + { 4 } naturals { 4 } ones t+ + t/ shape>> +] unit-test + +{ t } [ + { 2 2 } ones + { 2 2 } naturals { 2 2 } ones t+ + t/ vec>> + { 1.0 0.5 0.33333 0.25 } v- + [ abs ] map + 0 [ max ] reduce 0.0001 < +] unit-test + +{ { 2 2 } } [ + { 2 2 } ones + { 2 2 } naturals { 2 2 } ones t+ + t/ shape>> +] unit-test + +[ + { 3 } ones + { 2 2 } naturals { 2 2 } ones t+ + t/ vec>> +] +[ { 3 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 4 } ones + { 2 2 } naturals { 2 2 } ones t+ + t/ vec>> +] +[ { 4 } { 2 2 } \ shape-mismatch-error boa = ] must-fail-with + +! Test scalar division +{ t } [ + 1 + { 4 } naturals { 4 } ones t+ + t/ vec>> + { 1.0 0.5 0.33333 0.25 } v- + [ abs ] map + 0 [ max ] reduce 0.0001 < +] unit-test + +{ { 4 } } [ + 1 + { 4 } naturals { 4 } ones t+ + t/ shape>> +] unit-test + +{ float-array{ 0.0 0.5 1.0 1.5 } } [ + { 4 } naturals 2 t/ vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals 2 t/ shape>> +] unit-test + +! Test scalar multiplication +{ float-array{ 0.0 3.0 6.0 9.0 } } [ + { 4 } naturals 3 t* vec>> +] unit-test + +{ { 4 } } [ + { 4 } naturals 3 t* shape>> +] unit-test + +{ float-array{ 0.0 3.0 6.0 9.0 } } [ + { 2 2 } naturals 3 t* vec>> +] unit-test + +{ { 2 2 } } [ + { 2 2 } naturals 3 t* shape>> +] unit-test + +{ float-array{ 0.0 3.0 6.0 9.0 } } [ + 3 { 4 } naturals t* vec>> +] unit-test + +{ { 4 } } [ + 3 { 4 } naturals t* shape>> +] unit-test + +{ float-array{ 0.0 3.0 6.0 9.0 } } [ + 3 { 2 2 } naturals t* vec>> +] unit-test + +{ { 2 2 } } [ + 3 { 2 2 } naturals t* shape>> +] unit-test + +! test mod +{ float-array{ 0.0 1.0 2.0 0.0 1.0 } } [ + { 5 } naturals + { 5 } ones 3 t* + t% vec>> +] unit-test + +{ { 5 } } [ + { 5 } naturals + { 5 } ones 3 t* + t% shape>> +] unit-test + +{ float-array{ 0.0 1.0 2.0 0.0 1.0 2.0 } } [ + { 2 3 } naturals + { 2 3 } ones 3 t* + t% vec>> +] unit-test + +{ { 2 3 } } [ + { 2 3 } naturals + { 2 3 } ones 3 t* + t% shape>> +] unit-test + +[ + { 4 } naturals + { 2 3 } ones 3 t* + t% vec>> +] +[ { 4 } { 2 3 } \ shape-mismatch-error boa = ] must-fail-with + +[ + { 4 } naturals + { 2 3 } ones 3 t* + t% vec>> +] +[ { 4 } { 2 3 } \ shape-mismatch-error boa = ] must-fail-with + +! Test scalar mod +{ float-array{ 0.0 1.0 2.0 0.0 1.0 } } [ + { 5 } naturals + 3 + t% vec>> +] unit-test + +{ { 5 } } [ + { 5 } naturals + 3 + t% shape>> +] unit-test + +{ float-array{ 0.0 1.0 2.0 0.0 1.0 2.0 } } [ + { 2 3 } naturals + 3 + t% vec>> +] unit-test + +{ { 2 3 } } [ + { 2 3 } naturals + 3 + t% shape>> +] unit-test + +{ float-array{ 0.0 1.0 0.0 3.0 3.0 } } [ + 3 + { 5 } naturals 1 t+ + t% vec>> +] unit-test + +{ { 5 } } [ + { 5 } naturals + 3 + t% shape>> +] unit-test + +{ float-array{ 0.0 1.0 0.0 3.0 3.0 3.0 } } [ + 3 + { 2 3 } naturals 1 t+ + t% vec>> +] unit-test + +{ { 2 3 } } [ + { 2 3 } naturals + 3 + t% shape>> +] unit-test + +! test tensor>array +{ { 0.0 0.0 } } [ + { 2 } zeros tensor>array +] unit-test + +{ { { 0.0 0.0 } { 0.0 0.0 } } } [ + { 2 2 } zeros tensor>array +] unit-test + +{ { { { 1.0 1.0 } { 1.0 1.0 } { 1.0 1.0 } } + { { 1.0 1.0 } { 1.0 1.0 } { 1.0 1.0 } } } } [ + { 2 3 2 } ones tensor>array +] unit-test + +! test matmul +{ float-array{ 70.0 76.0 82.0 88.0 94.0 190.0 212.0 234.0 + 256.0 278.0 310.0 348.0 386.0 424.0 462.0 } } [ + { 3 4 } naturals { 4 5 } naturals matmul vec>> +] unit-test + +{ { 3 5 } } [ + { 3 4 } naturals { 4 5 } naturals matmul shape>> +] unit-test + +{ float-array{ 70.0 76.0 82.0 88.0 94.0 190.0 212.0 234.0 256.0 + 278.0 310.0 348.0 386.0 424.0 462.0 1510.0 1564.0 + 1618.0 1672.0 1726.0 1950.0 2020.0 2090.0 2160.0 + 2230.0 2390.0 2476.0 2562.0 2648.0 2734.0 } } [ + { 2 3 4 } naturals { 2 4 5 } naturals matmul vec>> +] unit-test + +{ { 2 3 5 } } [ + { 2 3 4 } naturals { 2 4 5 } naturals matmul shape>> +] unit-test + +{ float-array{ 70.0 76.0 82.0 88.0 94.0 190.0 212.0 234.0 256.0 + 278.0 310.0 348.0 386.0 424.0 462.0 1510.0 1564.0 1618.0 + 1672.0 1726.0 1950.0 2020.0 2090.0 2160.0 2230.0 2390.0 2476.0 + 2562.0 2648.0 2734.0 4870.0 4972.0 5074.0 5176.0 5278.0 5630.0 + 5748.0 5866.0 5984.0 6102.0 6390.0 6524.0 6658.0 6792.0 6926.0 + 10150.0 10300.0 10450.0 10600.0 10750.0 11230.0 11396.0 11562.0 + 11728.0 11894.0 12310.0 12492.0 12674.0 12856.0 13038.0 } } [ + { 2 2 3 4 } naturals { 2 2 4 5 } naturals matmul vec>> +] unit-test + +{ { 2 2 3 5 } } [ + { 2 2 3 4 } naturals { 2 2 4 5 } naturals matmul shape>> +] unit-test + +! test transpose +{ float-array{ 0.0 2.0 1.0 3.0 } } [ + { 2 2 } naturals transpose vec>> +] unit-test + +{ float-array{ 0.0 12.0 4.0 16.0 8.0 20.0 1.0 + 13.0 5.0 17.0 9.0 21.0 2.0 14.0 6.0 18.0 + 10.0 22.0 3.0 15.0 7.0 19.0 11.0 23.0 } } [ + { 2 3 4 } naturals transpose vec>> +] unit-test + +{ { 4 3 2 } } [ + { 2 3 4 } naturals transpose shape>> +] unit-test + +{ t } [ + { 2 3 4 5 6 } naturals dup transpose transpose = +] unit-test diff --git a/extra/tensors/tensors.factor b/extra/tensors/tensors.factor new file mode 100644 index 0000000000..d952474bf2 --- /dev/null +++ b/extra/tensors/tensors.factor @@ -0,0 +1,245 @@ +! Copyright (C) 2019 HMC Clinic. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors alien.c-types alien.data arrays +concurrency.combinators grouping kernel locals math.functions +math.ranges math.statistics math multi-methods quotations sequences +sequences.private specialized-arrays tensors.tensor-slice typed ; +QUALIFIED-WITH: alien.c-types c +SPECIALIZED-ARRAY: c:float +IN: tensors + +! Tensor class definition +TUPLE: tensor + { shape array } + { vec float-array } ; + +! Errors +ERROR: non-positive-shape-error shape ; +ERROR: shape-mismatch-error shape1 shape2 ; + + ( shape seq -- tensor ) + tensor boa ; + +: >float-array ( seq -- float-array ) + c:float >c-array ; + +: repetition ( shape const -- tensor ) + [ check-shape dup product ] dip + >float-array ; + +PRIVATE> + +! Construct a tensor of zeros +: zeros ( shape -- tensor ) + 0 repetition ; + +! Construct a tensor of ones +: ones ( shape -- tensor ) + 1 repetition ; + +! Construct a one-dimensional tensor with values start, start+step, +! ..., stop (inclusive) +: arange ( a b step -- tensor ) + [ length 1array ] keep >float-array ; + +! Construct a tensors with vec { 0 1 2 ... } and reshape to the desired shape +: naturals ( shape -- tensor ) + check-shape [ ] [ product [0,b) >float-array ] bi ; + + + +! Reshape the tensor to conform to the new shape +: reshape ( tensor shape -- tensor ) + [ dup shape>> ] [ check-shape ] bi* check-reshape nip >>shape ; + +! Flatten the tensor so that it is only one-dimensional +: flatten ( tensor -- tensor ) + dup shape>> + product { } 1sequence >>shape ; + +! outputs the number of dimensions of a tensor +: dims ( tensor -- n ) + shape>> length ; + +! Turn into Factor ND array form +! Source: shaped-array>array +TYPED: tensor>array ( tensor: tensor -- seq: array ) + [ vec>> >array ] [ shape>> ] bi + [ rest-slice reverse [ group ] each ] unless-empty ; + +> tensor2 shape>> check-bop-shape + tensor1 vec>> tensor2 vec>> quot 2map ; inline + +! Apply the operation to the tensor +TYPED:: t-uop ( tensor: tensor quot: ( x -- y ) -- tensor: tensor ) + tensor vec>> quot map [ tensor shape>> ] dip ; inline + +PRIVATE> + +! Add a tensor to either another tensor or a scalar +multi-methods:GENERIC: t+ ( x y -- tensor ) +METHOD: t+ { tensor tensor } [ + ] t-bop ; +METHOD: t+ { tensor number } [ + ] curry t-uop ; +METHOD: t+ { number tensor } swap [ + ] curry t-uop ; + +! Subtraction between two tensors or a tensor and a scalar +multi-methods:GENERIC: t- ( x y -- tensor ) +METHOD: t- { tensor tensor } [ - ] t-bop ; +METHOD: t- { tensor number } [ - ] curry t-uop ; +METHOD: t- { number tensor } swap [ swap - ] curry t-uop ; + +! Multiply a tensor with either another tensor or a scalar +multi-methods:GENERIC: t* ( x y -- tensor ) +METHOD: t* { tensor tensor } [ * ] t-bop ; +METHOD: t* { tensor number } [ * ] curry t-uop ; +METHOD: t* { number tensor } swap [ * ] curry t-uop ; + +! Divide two tensors or a tensor and a scalar +multi-methods:GENERIC: t/ ( x y -- tensor ) +METHOD: t/ { tensor tensor } [ / ] t-bop ; +METHOD: t/ { tensor number } [ / ] curry t-uop ; +METHOD: t/ { number tensor } swap [ swap / ] curry t-uop ; + +! Divide two tensors or a tensor and a scalar +multi-methods:GENERIC: t% ( x y -- tensor ) +METHOD: t% { tensor tensor } [ mod ] t-bop ; +METHOD: t% { tensor number } [ mod ] curry t-uop ; +METHOD: t% { number tensor } swap [ swap mod ] curry t-uop ; + +> ] bi@ :> shape2 :> shape1 + ! Check that the matrices can be multiplied + shape1 last shape2 [ length 2 - ] keep nth = + ! Check that the other dimensions are equal + shape1 2 head* shape2 2 head* = and + ! If either is false, raise an error + [ shape1 shape2 shape-mismatch-error ] unless ] ; + +! Slice out a row from the array +: row ( arr n i p -- slice ) + ! Compute the starting index + / truncate dupd * + ! Compute the ending index + swap over + + ! Take a slice + rot ; + +! Perform matrix multiplication muliplying an +! mxn matrix with a nxp matrix +TYPED:: 2d-matmul ( vec1: slice vec2: slice res: slice n: number p: number -- ) + ! For each element in the range, we want to compute the dot product of the + ! corresponding row and column + res + [ >fixnum + ! Get the row + [ [ vec1 n ] dip p row ] + ! Get the column + ! [ p mod vec2 swap p every ] bi + [ p mod f p vec2 ] bi + ! Take the dot product + [ * ] [ + ] 2map-reduce + ] + map! drop ; + +PRIVATE> + + +! Perform matrix multiplication muliplying an +! ...xmxn matrix with a ...xnxp matrix +TYPED:: matmul ( tensor1: tensor tensor2: tensor -- tensor3: tensor ) + ! First check the shape + tensor1 tensor2 check-matmul-shape + + ! Now save all of the sizes + tensor1 shape>> unclip-last-slice :> n + unclip-last-slice :> m :> top-shape + tensor2 shape>> last :> p + top-shape product :> rest + + ! Now create the new tensor with { 0 ... m*p-1 } repeating + top-shape { m p } append naturals m p * t% :> tensor3 + + ! Now update the tensor3 to contain the multiplied matricies + rest [0,b) + [ + :> i + ! First make vec1 + m n * i * dup m n * + tensor1 vec>> + ! Now make vec2 + n p * i * dup n p * + tensor2 vec>> + ! Now make the resulting vector + m p * i * dup m p * + tensor3 vec>> + ! Push n and p and multiply the clices + n p 2d-matmul + 0 + ] map drop + tensor3 ; + + cum-product { 1 } prepend ; + +! helper for transpose: given shape, flat index, & mults for the shape, gives nd index +:: trans-index ( ind shape mults -- seq ) + ! what we use to divide things + shape reverse :> S + ! accumulator + V{ } clone + ! loop thru elements & indices of S (mod by elment m) + S [| m i | + ! we divide by the product of the 1st n elements of S + S i head-slice product :> div + ! do not mod on the last index + i S length 1 - = not :> mod? + ! multiply accumulator by mults & sum + dup mults [ * ] 2map sum + ! subtract from ind & divide + ind swap - div / + ! mod if necessary + mod? [ m mod ] [ ] if + ! append to accumulator + [ dup ] dip swap push + ] each-index + reverse ; +PRIVATE> + +! Transpose an n-dimensional tensor +TYPED:: transpose ( tensor: tensor -- tensor': tensor ) + ! new shape + tensor shape>> reverse :> newshape + ! what we multiply by to get indices in the old tensor + tensor shape>> ind-mults :> old-mults + ! what we multiply to get indices in new tensor + newshape ind-mults :> mults + ! new tensor of correct shape + newshape naturals dup vec>> + [ ! go thru each index + ! find index in original tensor + newshape mults trans-index old-mults [ * ] 2map sum >fixnum + ! get that index in original tensor + tensor vec>> nth + ] map! >>vec ; From 614256abe21ca22786cc9e6ba0481289c3db3488 Mon Sep 17 00:00:00 2001 From: John Benediktsson Date: Sun, 24 Nov 2019 15:43:29 -0800 Subject: [PATCH 04/14] tensors: fix help-lint warnings. --- extra/tensors/tensors-docs.factor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extra/tensors/tensors-docs.factor b/extra/tensors/tensors-docs.factor index 34cc5f4c7d..b4fa8cc37a 100644 --- a/extra/tensors/tensors-docs.factor +++ b/extra/tensors/tensors-docs.factor @@ -8,7 +8,7 @@ ARTICLE: "tensors" "Tensors" "A " { $snippet "tensor" } " is a sequence " "shaped into an n-dimensional matrix. It supports fast, scalable matrix " "operations such as matrix multiplication and transposition as well as a " "number of element-wise operations. Words for working with tensors are found " -"in the " { $vocab-link "tensors" } " vocabulary.\n\n" +"in the " { $vocab-link "tensors" } " vocabulary." $nl $nl "Tensors can be created " "by calling one of four constructors:" { $subsections zeros ones naturals arange } @@ -73,14 +73,14 @@ HELP: naturals "shape has zero or negative values." } ; HELP: reshape -{ $values { "tensor" tensor } { "shape" sequence } { "tensor" tensor } } +{ $values { "tensor" tensor } { "shape" sequence } } { $description "Reshapes " { $snippet "tensor" } " to have shape " { $snippet "shape" } "." } { $errors "Throws a " { $link non-positive-shape-error } " if the given " "shape has zero or negative values." } ; HELP: flatten -{ $values { "tensor" tensor } { "tensor" tensor } } +{ $values { "tensor" tensor } } { $description "Reshapes " { $snippet "tensor" } " so that it is one-dimensional." } ; HELP: dims From 99df1effea872636ee5b69677237edb1e71a3e67 Mon Sep 17 00:00:00 2001 From: Niklas Larsson Date: Thu, 31 Oct 2019 13:41:22 +0100 Subject: [PATCH 05/14] Don't use rm from the nmake build. --- Nmakefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Nmakefile b/Nmakefile index 709befb1a0..7d0dd250f4 100644 --- a/Nmakefile +++ b/Nmakefile @@ -8,21 +8,21 @@ VERSION = 0.99 !IF [git describe --all > git-describe.tmp] == 0 GIT_DESCRIBE = \ !INCLUDE -!IF [rm git-describe.tmp] == 0 +!IF [del git-describe.tmp] == 0 !ENDIF !ENDIF !IF [git rev-parse HEAD > git-id.tmp] == 0 GIT_ID = \ !INCLUDE -!IF [rm git-id.tmp] == 0 +!IF [del git-id.tmp] == 0 !ENDIF !ENDIF !IF [git rev-parse --abbrev-ref HEAD > git-branch.tmp] == 0 GIT_BRANCH = \ !INCLUDE -!IF [rm git-branch.tmp] == 0 +!IF [del git-branch.tmp] == 0 !ENDIF !ENDIF From 38ab7289b5db4bdc33b9a0ac76fa4c4daa6c092c Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Tue, 24 May 2016 20:30:02 +0300 Subject: [PATCH 06/14] windows.errors: make check-invalid-handle throw windows-error instances There are two consequences: - the thrown object is now a windows-error, previously it was a string; - if GetLastError returns zero, nothing is thrown. Previously the string "The operation completed successfully." was thrown in that case. --- basis/windows/errors/errors.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/windows/errors/errors.factor b/basis/windows/errors/errors.factor index 83a8df0148..82e8701d16 100644 --- a/basis/windows/errors/errors.factor +++ b/basis/windows/errors/errors.factor @@ -744,7 +744,7 @@ ERROR: windows-error n string ; win32-error-string throw ; : check-invalid-handle ( handle -- handle ) - dup INVALID_HANDLE_VALUE = [ throw-win32-error ] when ; + dup INVALID_HANDLE_VALUE = [ win32-error ] when ; CONSTANT: expected-io-errors ${ From 1e61dbfd2af3dcd16053f0f55eabc745dce6f30d Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Tue, 24 May 2016 20:33:19 +0300 Subject: [PATCH 07/14] Replace inline INVALID_HANDLE_VALUE checks with check-invalid-handle calls On error find-first-file will now throw a windows-error instance instead of a string. --- basis/io/directories/windows/windows.factor | 3 +-- basis/io/files/info/windows/windows.factor | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/basis/io/directories/windows/windows.factor b/basis/io/directories/windows/windows.factor index ec76156775..76cc8f33f0 100644 --- a/basis/io/directories/windows/windows.factor +++ b/basis/io/directories/windows/windows.factor @@ -48,8 +48,7 @@ M: windows delete-directory ( path -- ) RemoveDirectory win32-error=0/f ; : find-first-file ( path WIN32_FIND_DATA -- WIN32_FIND_DATA HANDLE ) - [ nip ] [ FindFirstFile ] 2bi - [ INVALID_HANDLE_VALUE = [ win32-error-string throw ] when ] keep ; + [ nip ] [ FindFirstFile ] 2bi check-invalid-handle ; : find-next-file ( HANDLE WIN32_FIND_DATA -- WIN32_FIND_DATA/f ) [ nip ] [ FindNextFile ] 2bi 0 = [ diff --git a/basis/io/files/info/windows/windows.factor b/basis/io/files/info/windows/windows.factor index 71f8e06f69..90d17a03d5 100644 --- a/basis/io/files/info/windows/windows.factor +++ b/basis/io/files/info/windows/windows.factor @@ -42,8 +42,7 @@ TUPLE: windows-file-info < file-info-tuple attributes ; : find-first-file-stat ( path -- WIN32_FIND_DATA ) WIN32_FIND_DATA [ - FindFirstFile - [ INVALID_HANDLE_VALUE = [ win32-error ] when ] keep + FindFirstFile check-invalid-handle FindClose win32-error=0/f ] keep ; From a6f0b74f03059cab725e13ff83bdfc4b242f8de3 Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Tue, 24 May 2016 20:40:11 +0300 Subject: [PATCH 08/14] io.files.windows: replace "-1 " with INVALID_HANDLE_VALUE --- basis/io/files/windows/windows.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/io/files/windows/windows.factor b/basis/io/files/windows/windows.factor index 684d8f13d7..0531551b60 100644 --- a/basis/io/files/windows/windows.factor +++ b/basis/io/files/windows/windows.factor @@ -399,7 +399,7 @@ M: windows home WIN32_FIND_STREAM_DATA 0 [ FindFirstStream ] keepd - over -1 = [ + over INVALID_HANDLE_VALUE = [ 2drop throw-win32-error ] [ 1vector swap file-streams-rest From e1be081ec93061d1e236d6d6f4c1778feef854c2 Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Tue, 24 May 2016 20:42:48 +0300 Subject: [PATCH 09/14] Delete throw-win32-error, replace with win32-error calls --- basis/io/directories/windows/windows.factor | 2 +- basis/io/files/windows/windows.factor | 4 ++-- basis/windows/errors/errors.factor | 9 +-------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/basis/io/directories/windows/windows.factor b/basis/io/directories/windows/windows.factor index 76cc8f33f0..083c5187fb 100644 --- a/basis/io/directories/windows/windows.factor +++ b/basis/io/directories/windows/windows.factor @@ -31,7 +31,7 @@ ERROR: file-delete-failed path error ; : (delete-file) ( path -- ) dup DeleteFile 0 = [ GetLastError ERROR_ACCESS_DENIED = - [ delete-read-only-file ] [ throw-win32-error ] if + [ delete-read-only-file ] [ win32-error ] if ] [ drop ] if ; M: windows delete-file ( path -- ) diff --git a/basis/io/files/windows/windows.factor b/basis/io/files/windows/windows.factor index 0531551b60..518fa8daab 100644 --- a/basis/io/files/windows/windows.factor +++ b/basis/io/files/windows/windows.factor @@ -117,7 +117,7 @@ M: windows init-io ( -- ) : handle>file-size ( handle -- n/f ) (handle>file-size) [ GetLastError ERROR_INVALID_FUNCTION = - [ f ] [ throw-win32-error ] if + [ f ] [ win32-error ] if ] unless* ; ERROR: seek-before-start n ; @@ -400,7 +400,7 @@ M: windows home 0 [ FindFirstStream ] keepd over INVALID_HANDLE_VALUE = [ - 2drop throw-win32-error + 2drop win32-error ] [ 1vector swap file-streams-rest ] if ; diff --git a/basis/windows/errors/errors.factor b/basis/windows/errors/errors.factor index 82e8701d16..5679a62eba 100644 --- a/basis/windows/errors/errors.factor +++ b/basis/windows/errors/errors.factor @@ -740,9 +740,6 @@ ERROR: windows-error n string ; dup n>win32-error-string windows-error ] if ; -: throw-win32-error ( -- * ) - win32-error-string throw ; - : check-invalid-handle ( handle -- handle ) dup INVALID_HANDLE_VALUE = [ win32-error ] when ; @@ -758,11 +755,7 @@ CONSTANT: expected-io-errors expected-io-errors member? ; : expected-io-error ( error-code -- ) - dup expected-io-error? [ - drop - ] [ - throw-win32-error - ] if ; + expected-io-error? [ win32-error ] unless ; : io-error ( return-value -- ) { 0 f } member? [ GetLastError expected-io-error ] when ; From 70d08ce743d8bae6001f28baf8cc0f13afc93c10 Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Wed, 29 Jun 2016 01:20:38 +0300 Subject: [PATCH 10/14] Replace "n>win32-error-string throw" with windows-error instance throwing --- basis/io/files/windows/windows.factor | 4 ++-- basis/windows/registry/registry.factor | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/basis/io/files/windows/windows.factor b/basis/io/files/windows/windows.factor index 518fa8daab..9b5006701d 100644 --- a/basis/io/files/windows/windows.factor +++ b/basis/io/files/windows/windows.factor @@ -76,7 +76,7 @@ SYMBOL: master-completion-port { [ dup integer? ] [ ] } { [ dup array? ] [ first dup eof? - [ drop 0 ] [ n>win32-error-string throw ] if + [ drop 0 ] [ throw-windows-error ] if ] } } cond ] with-timeout ; @@ -147,7 +147,7 @@ M: windows handle-length ( handle -- n/f ) GetLastError { { [ dup expected-io-error? ] [ drop f ] } { [ dup eof? ] [ drop t ] } - [ n>win32-error-string throw ] + [ throw-windows-error ] } cond ] [ f ] if ; diff --git a/basis/windows/registry/registry.factor b/basis/windows/registry/registry.factor index be91098276..932e09d823 100644 --- a/basis/windows/registry/registry.factor +++ b/basis/windows/registry/registry.factor @@ -45,11 +45,7 @@ CONSTANT: registry-value-max-length 16384 f 0 KEY_ALL_ACCESS f create-key* drop ; : close-key ( hkey -- ) - RegCloseKey dup ERROR_SUCCESS = [ - drop - ] [ - n>win32-error-string throw - ] if ; + RegCloseKey n>win32-error-check ; :: with-open-registry-key ( key subkey mode quot -- ) key subkey mode open-key :> hkey @@ -82,7 +78,7 @@ PRIVATE> key value-name ptr1 lpType buffer grow-buffer reg-query-value-ex ] [ - ret n>win32-error-string throw + ret throw-windows-error ] if ] if ; From 2dfb3b3a73bd2ac1200b9f5f7161a2510a98cebc Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Wed, 29 Jun 2016 01:23:36 +0300 Subject: [PATCH 11/14] Replace "win32-error-string throw" with windows-error instance throwing Remove win32-error-string, because there was only one place it was used in. --- basis/alien/libraries/windows/windows.factor | 5 +++-- basis/calendar/windows/windows.factor | 2 +- basis/io/files/info/windows/windows.factor | 4 ++-- basis/io/sockets/secure/windows/windows.factor | 2 +- basis/windows/errors/errors.factor | 3 --- extra/talks/tc-lisp-talk/tc-lisp-talk.factor | 2 +- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/basis/alien/libraries/windows/windows.factor b/basis/alien/libraries/windows/windows.factor index 249bcff57a..03a2e8b8d4 100644 --- a/basis/alien/libraries/windows/windows.factor +++ b/basis/alien/libraries/windows/windows.factor @@ -1,8 +1,9 @@ -USING: alien.libraries io.pathnames system windows.errors ; +USING: alien.libraries io.pathnames system windows.errors +windows.kernel32 ; IN: alien.libraries.windows M: windows >deployed-library-path file-name ; M: windows dlerror ( -- message ) - win32-error-string ; + GetLastError n>win32-error-string ; diff --git a/basis/calendar/windows/windows.factor b/basis/calendar/windows/windows.factor index 80253ea91b..f866fe81fa 100644 --- a/basis/calendar/windows/windows.factor +++ b/basis/calendar/windows/windows.factor @@ -31,7 +31,7 @@ IN: calendar.windows M: windows gmt-offset ( -- hours minutes seconds ) TIME_ZONE_INFORMATION dup GetTimeZoneInformation { - { TIME_ZONE_ID_INVALID [ win32-error-string throw ] } + { TIME_ZONE_ID_INVALID [ win32-error ] } { TIME_ZONE_ID_UNKNOWN [ Bias>> ] } { TIME_ZONE_ID_STANDARD [ Bias>> ] } { TIME_ZONE_ID_DAYLIGHT [ [ Bias>> ] [ DaylightBias>> ] bi + ] } diff --git a/basis/io/files/info/windows/windows.factor b/basis/io/files/info/windows/windows.factor index 90d17a03d5..99eccd1c0f 100644 --- a/basis/io/files/info/windows/windows.factor +++ b/basis/io/files/info/windows/windows.factor @@ -19,7 +19,7 @@ TUPLE: windows-file-info < file-info-tuple attributes ; : get-compressed-file-size ( path -- n ) { DWORD } [ GetCompressedFileSize ] with-out-parameters - over INVALID_FILE_SIZE = [ win32-error-string throw ] [ >64bit ] if ; + over INVALID_FILE_SIZE = [ win32-error ] [ >64bit ] if ; : set-windows-size-on-disk ( file-info path -- file-info ) over attributes>> +compressed+ swap member? [ @@ -183,7 +183,7 @@ CONSTANT: names-buf-length 16384 [ path-length FindNextVolume ] with-out-parameters swap 0 = [ GetLastError ERROR_NO_MORE_FILES = - [ drop f ] [ win32-error-string throw ] if + [ drop f ] [ win32-error ] if ] [ alien>native-string ] if ; : find-volumes ( -- array ) diff --git a/basis/io/sockets/secure/windows/windows.factor b/basis/io/sockets/secure/windows/windows.factor index 59eccfed19..c1b8e3936d 100644 --- a/basis/io/sockets/secure/windows/windows.factor +++ b/basis/io/sockets/secure/windows/windows.factor @@ -14,7 +14,7 @@ M: openssl ssl-certificate-verification-supported? f ; : load-windows-cert-store ( string -- HCERTSTORE ) [ f ] dip CertOpenSystemStore - [ win32-error-string throw ] when-zero ; + [ win32-error ] when-zero ; : X509-NAME. ( X509_NAME -- ) f 0 X509_NAME_oneline diff --git a/basis/windows/errors/errors.factor b/basis/windows/errors/errors.factor index 5679a62eba..f5e5314e2f 100644 --- a/basis/windows/errors/errors.factor +++ b/basis/windows/errors/errors.factor @@ -717,9 +717,6 @@ CONSTANT: FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF [ drop "Unknown error 0x" id 0xffff,ffff bitand >hex append ] [ alien>native-string [ blank? ] trim ] if ; -: win32-error-string ( -- str ) - GetLastError n>win32-error-string ; - ERROR: windows-error n string ; : (win32-error) ( n -- ) diff --git a/extra/talks/tc-lisp-talk/tc-lisp-talk.factor b/extra/talks/tc-lisp-talk/tc-lisp-talk.factor index 8a6b5d97e5..c0353a3e40 100644 --- a/extra/talks/tc-lisp-talk/tc-lisp-talk.factor +++ b/extra/talks/tc-lisp-talk/tc-lisp-talk.factor @@ -456,7 +456,7 @@ xyz \"TIME_ZONE_INFORMATION\" dup GetTimeZoneInformation { { TIME_ZONE_ID_INVALID [ - win32-error-string throw + win32-error ] } { TIME_ZONE_ID_STANDARD [ TIME_ZONE_INFORMATION-Bias From ca474dd154c8ce59b4a1e40281a4b9fc6e182a1a Mon Sep 17 00:00:00 2001 From: Alexander Iljin Date: Wed, 29 Jun 2016 01:55:15 +0300 Subject: [PATCH 12/14] windows.errors: streamline error handling and throwing --- basis/windows/errors/authors.txt | 1 + basis/windows/errors/errors.factor | 19 +++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/basis/windows/errors/authors.txt b/basis/windows/errors/authors.txt index 7c1b2f2279..d652f68ac8 100644 --- a/basis/windows/errors/authors.txt +++ b/basis/windows/errors/authors.txt @@ -1 +1,2 @@ Doug Coleman +Alexander Ilin diff --git a/basis/windows/errors/errors.factor b/basis/windows/errors/errors.factor index f5e5314e2f..ffb735be08 100644 --- a/basis/windows/errors/errors.factor +++ b/basis/windows/errors/errors.factor @@ -719,23 +719,18 @@ CONSTANT: FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF ERROR: windows-error n string ; -: (win32-error) ( n -- ) - [ dup win32-error-string windows-error ] unless-zero ; +: throw-windows-error ( n -- * ) + dup n>win32-error-string windows-error ; -: win32-error ( -- ) - GetLastError (win32-error) ; +: n>win32-error-check ( n -- ) + [ throw-windows-error ] unless-zero ; +! Note that win32-error* words throw GetLastError code. +: win32-error ( -- ) GetLastError n>win32-error-check ; : win32-error=0/f ( n -- ) { 0 f } member? [ win32-error ] when ; : win32-error>0 ( n -- ) 0 > [ win32-error ] when ; : win32-error<0 ( n -- ) 0 < [ win32-error ] when ; -: win32-error<>0 ( n -- ) zero? [ win32-error ] unless ; - -: n>win32-error-check ( n -- ) - dup ERROR_SUCCESS = [ - drop - ] [ - dup n>win32-error-string windows-error - ] if ; +: win32-error<>0 ( n -- ) [ win32-error ] unless-zero ; : check-invalid-handle ( handle -- handle ) dup INVALID_HANDLE_VALUE = [ win32-error ] when ; From deb324dee1edae1ee7b4939ea29b0b6e6f5d91b4 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Fri, 29 Nov 2019 12:46:53 +0700 Subject: [PATCH 13/14] Redirect when using curl Signed-off-by: Rudi Grinberg --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 66cf8f2dc5..fba998ee4e 100755 --- a/build.sh +++ b/build.sh @@ -98,7 +98,7 @@ set_downloader() { fi test_program_installed curl if [[ $? -ne 0 ]] ; then - DOWNLOADER="curl -f -O" + DOWNLOADER="curl -L -f -O" DOWNLOADER_NAME=curl return fi From 618d41251ea894f9acdda209933d403ab3073d2c Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Sat, 30 Nov 2019 01:11:31 -0500 Subject: [PATCH 14/14] random.passwords: char: --- basis/random/passwords/passwords.factor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/basis/random/passwords/passwords.factor b/basis/random/passwords/passwords.factor index 44cd127efd..3a63b05f33 100644 --- a/basis/random/passwords/passwords.factor +++ b/basis/random/passwords/passwords.factor @@ -8,9 +8,9 @@ IN: random.passwords CONSTANT: ascii-printable-charset $[ 33 126 [a,b] ] CONSTANT: hex-charset "0123456789ABCDEF" CONSTANT: alphanum-charset $[ - CHAR: 0 CHAR: 9 [a,b] - CHAR: a CHAR: z [a,b] append - CHAR: A CHAR: Z [a,b] append ] + char: 0 char: 9 [a,b] + char: a char: z [a,b] append + char: A char: Z [a,b] append ] PRIVATE>