Sign in to follow this  
Followers 0
czardas

Snippet Dump

120 posts in this topic

#1 ·  Posted (edited)

Please Note : Many of the functions in this thread have been organised into several UDFs found at the following link

Details of the changes are still being documented.

Index

1.

2.

3.

4. ?do=embed' frameborder='0' data-embedContent>

5..?do=embed' frameborder='0' data-embedContent> - No longer supported

6. - Addresses issues with window commands when a disabled control has focus

7.

8.

9.

10. - Error handling within Nested Functions

11. - Fun but not particularly useful

12. - Less fun, but more useful

13.

14.

15. - Random bitwise splitting functions.

16. - Camel Case conversion has some limited potential use.

17.

18.

19.

This thread is has been updated several times and is under constant revision. Some of the older entries contain code that has been superseded by more recent versions. Outdated code has been placed inside spoilers to preserve the integrity of the thread.


Original first post

Modular Array Rotation See post number 30 for an improved version.

Much of my code involves modular functions. I have previously rotated modular array data in a slow and inefficient way, using far too many ReDims. I have tried to find the best solution, but I would like to hear your opinions. The following code rotates a one dimensional array, as if the first and last element were adjacent to each other in a continuous modular loop.

#include <Array.au3>

; $av_4rray - One dimensional array to spin.
; $iClix - Clicks must be a positive integer.
; $iMde - Mode set to 0 or 1 indicating the rotation direction.

Func _ArrayModularSpin(ByRef $av_4rray, $iClix, $iMde)
If IsArray($av_4rray) = 0 Or UBound($av_4rray, 2) Then
     SetError(1)
ElseIf ($iClix < 0) Or (IsInt($iClix) = 0) Then
     SetError(2)
EndIf
If @error Then Return

If $iClix >= UBound($av_4rray) Then $iClix = Mod($iClix, UBound($av_4rray))
If $iClix = 0 Then Return $av_4rray
If $iMde = 0 Then ; Forward rotation. Elements move down.
     Local $i5plit = $iClix, $iLments = UBound($av_4rray) -$iClix
ElseIf $iMde = 1 Then ; Reverse Rotation. Elements move up.
     Local $i5plit = UBound($av_4rray) -$iClix, $iLments = $iClix
Else
     SetError(3)
     Return
EndIf
Local $av_Arrai[$i5plit]
For $i1nt = 0 To UBound($av_Arrai) -1
     $av_Arrai[$i1nt] = $av_4rray[$iLments +$i1nt]
Next
ReDim $av_4rray[$iLments]
_ArrayConcatenate($av_Arrai, $av_4rray)
$av_4rray = $av_Arrai
EndFunc

; ============================================================

; Example 1
Local $asDays[7] = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]

_ArrayModularSpin($asDays, 11, 0)
_ArrayDisplay($asDays)
_ArrayModularSpin($asDays, 4, 1)
_ArrayDisplay($asDays)

; ============================================================

; Example 2 => error test
Local $asMessage[4]
$asMessage[1] = "The first parameter is not a one dimensional array!"
$asMessage[2] = "Incorrect click value!"
$asMessage[3] = "Incorrect mode value!"

_ArrayModularSpin($asDays, "a", 0)
If @error Then MsgBox(0, "Error", $asMessage[@error])

Apologies for the strange variable names. I wanted to avoid accidentally repeating them outside the function. You can alter them to suit your needs. For practical purposes: the error checks can be removed, providing that you can guarantee valid parameters will always be passed to the function. Valid parameters are defined in the inline comments above.

Func _ArrayModularSpin(ByRef $av_4rray, $iClix, $iMde)
If $iClix >= UBound($av_4rray) Then $iClix = Mod($iClix, UBound($av_4rray))
If $iClix = 0 Then Return $av_4rray
If $iMde = 0 Then
     Local $i5plit = $iClix, $iLments = UBound($av_4rray) -$iClix
Else
     Local $i5plit = UBound($av_4rray) -$iClix, $iLments = $iClix
EndIf
Local $av_Arrai[$i5plit]
For $i1nt = 0 To UBound($av_Arrai) -1
     $av_Arrai[$i1nt] = $av_4rray[$iLments +$i1nt]
Next
ReDim $av_4rray[$iLments]
_ArrayConcatenate($av_Arrai, $av_4rray)
$av_4rray = $av_Arrai
EndFunc

Edited by czardas

Share this post


Link to post
Share on other sites



Much of my code involves modular functions.

Sorry to stop you here, but this should be: Much of my code could be modular functions, but I use many global variables incorrectly.

Apologies for the strange variable names. I wanted to avoid accidentally repeating them outside the function.

Once again you surprise everyone. Here's a piece of code that shows you something simple about variable scope, and why you shouldn't worry about reusing variable names. I understand why you worry, it's because you use way too many globals and thus your code is more prone to these kind of mistakes. However, if you learn to write all functions like you did in this example then you will never have this problem ever again without doing anything special.

#include-once
#include <Array.au3>

$av_4rray = 1
$iClix = 2
$iMde = 3
$i5plit = 4
$av_Arrai = 5
$i1nt = 6

Local $in[3] = ["a", "b", "c"]
_ArrayModularSpin($in, 3, 0)

ConsoleWrite($av_4rray & @CRLF)
ConsoleWrite($iClix & @CRLF)
ConsoleWrite($iMde & @CRLF)
ConsoleWrite($i5plit & @CRLF)
ConsoleWrite($av_Arrai & @CRLF)
ConsoleWrite($i1nt & @CRLF)

Func _ArrayModularSpin(ByRef $av_4rray, $iClix, $iMde) ; $av_4rray, $iClix and $iMde are automatically defined in the local scope of the function
    If $iClix >= UBound($av_4rray) Then $iClix = Mod($iClix, UBound($av_4rray))
    If $iClix = 0 Then Return $av_4rray
    If $iMde = 0 Then
        Local $i5plit = $iClix, $iLments = UBound($av_4rray) -$iClix ; here you introduce a new variable $i5Split and $iLments which you correctly define in the local scope of the function
    Else
        Local $i5plit = UBound($av_4rray) -$iClix, $iLments = $iClix; here you introduce a new variable $i5Split and $iLments which you correctly define in the local scope of the function
    EndIf
    Local $av_Arrai[$i5plit] ; again a new variable which is correctly defined on the local scope of the function
    For $i1nt = 0 To UBound($av_Arrai) -1 ; $i1nt is also automatically defined in the local scope of the function
        $av_Arrai[$i1nt] = $av_4rray[$iLments +$i1nt]
    Next
    ReDim $av_4rray[$iLments] ; if you only spin the wheel/array, how can it ever change in size?
    _ArrayConcatenate($av_Arrai, $av_4rray)
    $av_4rray = $av_Arrai
EndFunc

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I didn't like your implementation because:

- The variable names make no sense and the word "Modular" in the function name is incorrect (it shouldn't be there, you mean that it's not incorrect. All functions should be "modular", ie independent)

- It's not obvious how _ArrayConcatenate works internally and how fast it is

- ReDim an array is used to clear the array, not for changing length (misuse of ReDim, I think personally)

- A element by element copy of $av_array is made into $av_4rray in the last line, this seems unnecessary

- Inconsistency in return type or use of ByRef. Here: Return $av_4rray

Lastly, the use of ByRef for the array parameter is questionable. It is a speed gain to use a reference here instead of a copy, but it doesn't make any sense to others if you are not updating the array by reference (like in my code where it's not used). Also, I have chosen to make it Return the new array instead of altering it: This is to make it explicit to the programmer who uses the function that internally two arrays are used, something that's not inherently obvious by reading the function declaration of your code.

Here's my own take at it. I am 99,5% sure that someone will make a quicker or neater function.

#include-once
#include <Array.au3>

Local $in[5] = ["a", "b", "c", "d", "e"]

Local $out2 = _ArraySpin($in, 1)
_ArrayDisplay($out2)

Local $out = _ArraySpin($in, -1)
_ArrayDisplay($out)

Func _ArraySpin($aInput, $iSpinCount) ; To ByRef or not to ByRef $aInput
    ; store Ubound of $aInput in $aInputLen for faster access (hopefully)
    Local $aInputLen = UBound($aInput)

    ; do parameter boundary checks
    If $iSpinCount >= $aInputLen Then $iSpinCount = Mod($iSpinCount, $aInputLen)
    If $iSpinCount = 0 Then Return $aInput

    ; create array for output values
    Local $aOutput[$aInputLen]

    For $i = 0 To $aInputLen-1
         ; calculate new position for $i
        $n = $i - $iSpinCount

        ; check if $n is in bounds, this causes the wheel effect
        If $n < 0 Then $n = $aInputLen + $n
        If $n >= $aInputLen Then $n = $n - $aInputLen

        ; put value in its new position
        $aOutput[$n] = $aInput[$i]
    Next

    ; I have chosen to return because it is faster since there is no need to copy the output array more than once, even if it is implicit
    Return $aOutput
EndFunc
Edited by Manadar

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

LOL, I declare everything in the local scope and still it ends up as global! How is that possible? :x

I thought modular was a mathematical term refering to a modal system. Perhaps it has another meaning to a programmer. Thanks for the first illustration which I get. The second example you posted is counter-intuitive. Setting the second parameter to zero should not effect the array at all. There is something wrong there. I'll look deeper into what you are saying, I agree about using the Return function and avoiding copying arrays. I will need a little time to figure out your second example and hopefully fix it. Thanks for the input.

I also don't get what is wrong with using ByRef. Your code produces several arrays. That's not my intention. Okay I can see the inconsistancy of combining ByRef with Return. Thanks for that piece of wisdom. :P

Finally if I can figure out how to do this using ByRef, but without ReDim or copying part of the original array then that would be ideal.

Edited by czardas

Share this post


Link to post
Share on other sites

I was looking for somewhere to put these... So here they are:

Using WM_SIZE

To set a maximum GUI size:

#include<WindowsConstants.au3>
#include<StructureConstants.au3>

Global $iMaxWidth = 600
Global $iMaxHeight = 600

GUICreate('test', 400, 400, -1, -1, $WS_SIZEBOX)
GUISetState()

GUIRegisterMsg($WM_SIZING, "WM_SIZING")

While True
    Switch GUIGetMsg()
        Case -3
            Exit
    EndSwitch
WEnd

; Sent to a window that the user is resizing.
Func WM_SIZING($hWnd, $iMsg, $wParam, $lParam)
    Local $tRECT = DllStructCreate($tagRECT, $lParam)

    Switch $wParam ; The edge of the window that is being sized.
        Case 1 ; WMSZ_LEFT - Left edge
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Left", DllStructGetData($tRECT, "Right") - $iMaxWidth)
            EndIf
        Case 2 ; WMSZ_RIGHT - Right edge
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Right", DllStructGetData($tRECT, "Left") + $iMaxWidth)
            EndIf
        Case 3 ; WMSZ_TOP - Top edge
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - $iMaxWidth)
            EndIf
        Case 4 ; WMSZ_TOPLEFT - Top-left corner
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - $iMaxWidth)
            EndIf
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Left", DllStructGetData($tRECT, "Right") - $iMaxWidth)
            EndIf
        Case 5 ; WMSZ_TOPRIGHT - Top-right corner
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - $iMaxWidth)
            EndIf
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Right", DllStructGetData($tRECT, "Left") + $iMaxWidth)
            EndIf
        Case 6 ; WMSZ_BOTTOM - Bottom edge
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Bottom", DllStructGetData($tRECT, "Top") + $iMaxWidth)
            EndIf
        Case 7 ; WMSZ_BOTTOMLEFT - Bottom-left corner
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Bottom", DllStructGetData($tRECT, "Top") + $iMaxWidth)
            EndIf
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Left", DllStructGetData($tRECT, "Right") - $iMaxWidth)
            EndIf
        Case 8 ; WMSZ_BOTTOMRIGHT - Bottom-right corner
            If DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top") > $iMaxWidth Then
                DllStructSetData($tRECT, "Bottom", DllStructGetData($tRECT, "Top") + $iMaxWidth)
            EndIf
            If DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") > $iMaxWidth Then
                DllStructSetData($tRECT, "Right", DllStructGetData($tRECT, "Left") + $iMaxWidth)
            EndIf
    EndSwitch

    Return True ; An application should return TRUE if it processes this message.
EndFunc   ;==>WM_SIZING


To lock the aspect ratio:

#include<WindowsConstants.au3>
#include<StructureConstants.au3>

GUICreate('test', 400, 400, -1, -1, $WS_SIZEBOX)
GUISetState()

GUIRegisterMsg($WM_SIZING, "WM_SIZING")

While True
    Switch GUIGetMsg()
        Case -3
            Exit
    EndSwitch
WEnd

; Sent to a window that the user is resizing.
Func WM_SIZING($hWnd, $iMsg, $wParam, $lParam)
    Local $tRECT = DllStructCreate($tagRECT, $lParam)

    Switch $wParam ; The edge of the window that is being sized.
        Case 1 ; WMSZ_LEFT - Left edge
            DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - (DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left")))
        Case 2 ; WMSZ_RIGHT - Right edge
            DllStructSetData($tRECT, "Bottom", DllStructGetData($tRECT, "Top") + (DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left")))
        Case 3 ; WMSZ_TOP - Top edge
            DllStructSetData($tRECT, "Left", DllStructGetData($tRECT, "Right") - (DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top")))
        Case 4 ; WMSZ_TOPLEFT - Top-left corner
            DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - (DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left")))
        Case 5 ; WMSZ_TOPRIGHT - Top-right corner
            DllStructSetData($tRECT, "Top", DllStructGetData($tRECT, "Bottom") - (DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left")))
        Case 6 ; WMSZ_BOTTOM - Bottom edge
            DllStructSetData($tRECT, "Right", DllStructGetData($tRECT, "Left") + (DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top")))
        Case 7 ; WMSZ_BOTTOMLEFT - Bottom-left corner
            DllStructSetData($tRECT, "Left", DllStructGetData($tRECT, "Right") - (DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top")))
        Case 8 ; WMSZ_BOTTOMRIGHT - Bottom-right corner
            DllStructSetData($tRECT, "Right", DllStructGetData($tRECT, "Left") + (DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top")))
    EndSwitch

    Return True ; An application should return TRUE if it processes this message.
EndFunc   ;==>WM_SIZING

Share this post


Link to post
Share on other sites

Deathbringer,

when naming variables inside a function, you should use an underscore after the type specifier

Where did you get that from? :x

The AutoIt User Defined Functions Standards page is here and makes no such stipulation.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

@Manadar I just figured out why I thought the second parameter wasn't working. It's because the original array does not get altered in your second example. There's actually nothing wrong with the second param. :P I see that it's a good alternative function, but it does something slightly different.

@Mat I have a request. How to get the ideal size of an image, whilst leaving exactly the right amount of space for a label containing a defined amount of text at a specified font size within specified GUI dimensions. :x

Edited by czardas

Share this post


Link to post
Share on other sites

using an underscore is something I've never seen in AutoIt. The only reason it's sometimes used in other languages where you may get (I think): rglpwsz

AutoIt's longest prefix as 2 characters: a* as an array of type *. Of course theirs nothing stopping you having nested arrays... $aaiBigArray = an array of integer arrays.

On a seperate note... Modular is a lot of things is maths and computing. AutoIt is a modular language (we use includes).

Share this post


Link to post
Share on other sites

czardas,

exactly the right amount of space for a label containing a defined amount of text at a specified font size

The StringSize UDF in my sig will give you the size you need for the text. :x

Deathbringer,

Personal experience

If that is what you want to do in your code then please do so, but "you should use" implies an imperative which is not the case here - unless you are Valik in disguise. :P

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

The StringSize UDF in my sig will give you the size you need for the text. :x

Added to favourites. I'll look at it later. Thx!

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I thought modular was a mathematical term refering to a modal system. Perhaps it has another meaning to a programmer.

It does mean what you think, but it is not something to name every single one of your functions by. Every function ever should be modular, so it's redundant to name your functions by this. Similar to why you don't name all functions Like XXHasParametersAndReturns(). If you wrote a system that loads bits of code dynamically into your system, that's when it's appropriate to use the term modular. (Similar to what Mat said, with includes)

I also don't get what is wrong with using ByRef. Your code produces several arrays. That's not my intention.

This is questionable, indeed. Maybe it's not the point of your code to produce several arrays, but several arrays are produced internally. That's why I am hesitant to use ByRef. Using ByRef will give off the idea that only one array is used internally. This is a weak argument, but in this case it is better than no argument at all. Maybe speed is a much stronger argument.

Finally if I can figure out how to do this using ByRef, but without ReDim or copying part of the original array then that would be ideal.

Well, that's extremely simple - but it requires copying an array at least once. This is another reason why I didn't opt for ByRef solution; The programmer can copy the result array into the original array himself and it gives him more freedom (and potentially more speed). Alternatively, you can use two methods which do different things: One ByRef and one that returns the new array.

#include-once
#include <Array.au3>

Local $in[5] = ["a", "b", "c", "d", "e"]

_ArraySpin($in, 1)
_ArrayDisplay($in)

_ArraySpin($in, -1)
_ArrayDisplay($in)

Func _ArraySpin(ByRef $aInput, $iSpinCount)
    ; store Ubound of $aInput in $aInputLen for faster access (hopefully)
    Local $aInputLen = UBound($aInput)

    ; do parameter boundary checks
    If $iSpinCount >= $aInputLen Then $iSpinCount = Mod($iSpinCount, $aInputLen)
    If $iSpinCount = 0 Then Return

    ; create array for output values
    Local $aTemp = $aInput

    For $i = 0 To $aInputLen-1
         ; calculate new position for $i
        $n = $i - $iSpinCount

        ; check if $n is in bounds, this causes the wheel effect
        If $n < 0 Then $n = $aInputLen + $n
        If $n >= $aInputLen Then $n = $n - $aInputLen

        ; put value in its new position
        $aInput[$n] = $aTemp[$i]
    Next
EndFunc
Edited by Manadar

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Thanks again Manadar for the explanaition. I will avoid using the term modular in future, however it would be nice if there was a built in 'modal array variable type' in the language. Perhaps one exists elsewhere. I still feel the need to indicate this somehow: as I consider the word 'Spin' to be unclear by itself. Perhaps ModalSpin or something like that would be better.

I noticed that you used a full copy of the array, which I was trying to avoid, in case the array happens to be very large or the spin value is very small. I thought this was unecessary (hence the use of ByRef). In any case, your code is very clear, and I very much appreciate you spending time on this. As always, there are a few points for me to to consider. :x

Edited by czardas

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

I just looked at the source for _arrayConcatenate, and Manadar is right to call the method into question. A For loop is used there, so there will be no overall difference in the number of element declarations. I like the idea of a function with two alternative methods as suggested. One returning a new array, and the other modifying the original. I will combine Manadar's last method with my own (using two For loops and less conditional statements) and get rid of the ReDim.


Here's the new version. I think it's better. Hopefully you think so too.

#include <Array.au3>
 
Func _ArrayModalSpin(ByRef $av_Array, $iClicks)
    Local $iDirection = 0, $iElements = UBound($av_Array)
    If $iClicks < 0 Then
        $iDirection = 1
        $iClicks *= -1
    EndIf
 
    If $iClicks >= $iElements Then $iClicks = Mod($iClicks, $iElements)
    If $iClicks = 0 Then Return
 
    If $iDirection = 0 Then ; Elements move down.
        Local $iStart = $iElements -$iClicks, $iResume = $iClicks
    Else ; Elements move up.
        Local $iStart = $iClicks, $iResume = $iElements -$iClicks
    EndIf
 
    Local $av_Temp[$iElements]
    For $i = 0 To $iResume -1
        $av_Temp[$i] = $av_Array[$iStart +$i]
    Next
 
    For $i = $iResume To $iElements -1
        $av_Temp[$i] = $av_Array[$i -$iResume]
    Next
    $av_Array = $av_Temp
EndFunc
 
; Example
Local $asMonths[12] = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
 
_ArrayModalSpin($asMonths, 17)
_ArrayDisplay($asMonths)
 
_ArrayModalSpin($asMonths, -5)
_ArrayDisplay($asMonths)

I also looked into the word modular, and I see how it stems from the word module, although it also is used to define modal systems. These are two completely different interpretations of the word modular. This is a semantic discrepancy - nothing more and nothing less. It is a term I use quite a lot when refering to closed loops.

Edited by czardas

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Now might be a good time to do some speed testing of each separate function, starting with the original version you wrote going through those two of mine and ending with your final version. I think it'll need between 1000 to 10000 iterations of each function with the same input to be able to get somewhat accurate measurements. What I'm hoping to see is that the first version is slow in comparison to all the versions that followed up. In all the follow up versions I don't expect a significant difference.

About the word module and modularity. The only reference I know of that doesn't mean "existing of independent parts" is the following in math: http://en.wikipedia.org/wiki/Module_(mathematics) which has a definition something like this (and it does not simply substitute the word "ring" or "circular"):

A left R- module M over the ring R consists of an abelian group (M, +) and an operation R × M → M (called scalar multiplication, usually just written as rx for r in R and x in M) such that:

For all r,s in R, x,y in M, we have:
r(x + y) = rx + ry
(r + s)x = rx + sx
(rs)x = r(sx)

And it can be argued that even this formal definition simply means "existing of interchangeable parts".

By this I mean that in programming, and many other engineering fields, words are often given an unambiguous meaning. This meaning of words changes per group or subgroup of people. Which in practice means that a meaning of a word could be different for every company, department or forum - although it can be the same. The important part is that everyone that hears or reads the word knows what it means, all the time with no exceptions. The word "module" in programming (and also on this forum) is always (with reasonable certainty) used to describe something existing of parts. This is mostly thanks to a short but meaningful history in programming where writing code in individual parts is one of the main principles that drive software. TLDR; If you mean list, say list. If you mean module, say module.

Then there is the question of whether you should follow "the trend" and whether or not to follow it even it could be incorrect. That's not something I'm going to discuss here because it's mostly a yes/no thing and both sides have strong arguments depending on your point of view and what you're trying to achieve. TLDR; Everything in this post is moot anyway.

Also, I wanted to make a post why using only one array is not possible. But have no time for that now. It's cool stuff though.

Edited by Manadar

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

I thought there have been some interesting and worth while observations made in this thread so far. Regarding the word 'modular': I had heard of it being used in contexts other than modular arithmetic. I always thought the word had been stolen. :P I'll have to look into its etymology and find out who though of it first.

Advance Warning ==> My next post will include the word 'inversion'. LOL

I will run some speed tests later today and post the results. :x

Edited by czardas

Share this post


Link to post
Share on other sites

I thought there have been some interesting and worth while observations made in this thread so far. Regarding the word 'modular': I had heard of it being used in contexts other than modular arithmetic. I always thought the word had been stolen. :x I'll have to look into it's etymology and find out who though of it first.

Consider my argument it doesn't matter who used it first. It matters what everyone thinks it means. If your definition is off from everyone else's, then you fail. 8)

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Consider my argument it doesn't matter who used it first. It matters what everyone thinks it means. If your definition is off from everyone else's, then you fail. 8)

Appreciated. However I can't avoid using the term 'modulation', whatever that might mean to anyone else. It can't be helped. :x Edited by czardas

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

At least you are not using the shortened version 'mod':

  • Modular arithmetic
  • Module
  • Modal
  • MOD
  • Not a rocker
  • Modulo
  • Moderator
  • Modify

That's just the list off the top of my head...

Edited by Mat

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

Okay I tried the following test and the results surprised me. I tried to make the test as unbiased as possible. Please check the code because I may have overlooked something. If not, then I guess that the additional conditional statements are slowing down the second and third methods.

#include-once
#include <Array.au3>

Local $aLargeArray[1000]
For $i = 0 To 999 Step 2
    $aLargeArray[$i] = 998
    $aLargeArray[$i +1] = 999
Next

$a = 0
$b = 0
$c = 0
$d = 0

For $i = -999 to 999
    ; Prepare parameters for the first function.
    If $i < 0 Then
        $a1 = $i*(-1)
        $a2 = 1
    Else
        $a1 = $i
        $a2 = 0
    EndIf

    $iTimer = TimerInit()
    _ArrayModularSpin($aLargeArray, $a1, $a2)
    $a += TimerDiff($iTimer)

    $iTimer = TimerInit()
    _ArraySpin1($aLargeArray, $i)
    $b += TimerDiff($iTimer)

    $iTimer = TimerInit()
    _ArraySpin2($aLargeArray, $i)
    $c += TimerDiff($iTimer)

    $iTimer = TimerInit()
    _ArrayModalSpin($aLargeArray, $i)
    $d += TimerDiff($iTimer)
Next

ConsoleWrite("Method 1 " & $a & @LF & "Method 2 " & $b & @LF & "Method 3 " & $c & @LF & "Method 4 " & $d & @LF)


Func _ArrayModularSpin(ByRef $av_4rray, $iClix, $iMde)
    If $iClix >= UBound($av_4rray) Then $iClix = Mod($iClix, UBound($av_4rray))
    If $iClix = 0 Then Return $av_4rray
    If $iMde = 0 Then
        Local $i5plit = $iClix, $iLments = UBound($av_4rray) -$iClix
    Else
        Local $i5plit = UBound($av_4rray) -$iClix, $iLments = $iClix
    EndIf
    Local $av_Arrai[$i5plit]
    For $i1nt = 0 To UBound($av_Arrai) -1
        $av_Arrai[$i1nt] = $av_4rray[$iLments +$i1nt]
    Next
    ReDim $av_4rray[$iLments]
    _ArrayConcatenate($av_Arrai, $av_4rray)
    $av_4rray = $av_Arrai
EndFunc

Func _ArraySpin1($aInput, $iSpinCount)
    Local $aInputLen = UBound($aInput)
    If $iSpinCount >= $aInputLen Then $iSpinCount = Mod($iSpinCount, $aInputLen)
    If $iSpinCount = 0 Then Return $aInput
    Local $aOutput[$aInputLen]
    For $i = 0 To $aInputLen-1
        $n = $i - $iSpinCount
        If $n < 0 Then $n = $aInputLen + $n
        If $n >= $aInputLen Then $n = $n - $aInputLen
        $aOutput[$n] = $aInput[$i]
    Next
    Return $aOutput
EndFunc

Func _ArraySpin2(ByRef $aInput, $iSpinCount)
    Local $aInputLen = UBound($aInput)
    If $iSpinCount >= $aInputLen Then $iSpinCount = Mod($iSpinCount, $aInputLen)
    If $iSpinCount = 0 Then Return
    Local $aTemp = $aInput
    For $i = 0 To $aInputLen-1
        $n = $i - $iSpinCount
        If $n < 0 Then $n = $aInputLen + $n
        If $n >= $aInputLen Then $n = $n - $aInputLen
        $aInput[$n] = $aTemp[$i]
    Next
EndFunc

Func _ArrayModalSpin(ByRef $av_Array, $iClicks)
    Local $iDirection = 0, $iElements = UBound($av_Array)
    If $iClicks < 0 Then
        $iDirection = 1
        $iClicks *= -1
    EndIf
    If $iClicks >= $iElements Then $iClicks = Mod($iClicks, $iElements)
    If $iClicks = 0 Then Return
    If $iDirection = 0 Then
        Local $iStart = $iElements -$iClicks, $iResume = $iClicks
    Else
        Local $iStart = $iClicks, $iResume = $iElements -$iClicks
    EndIf
    Local $av_Temp[$iElements]
    For $i = 0 To $iResume -1
        $av_Temp[$i] = $av_Array[$iStart +$i]
    Next
    For $i = $iResume To $iElements -1
        $av_Temp[$i] = $av_Array[$i -$iResume]
    Next
    $av_Array = $av_Temp
EndFunc

Results

Test 1
Method 1 => 5577.01747009745 czardas
Method 2 => 9799.94384761192 Manadar
Method 3 => 8270.53801530642 Manadar
Method 4 => 4054.27477514601 czardas

Test2
Method 1 => 5537.39958570154 czardas
Method 2 => 9790.02750349554 Manadar
Method 3 => 8269.94101205601 Manadar
Method 4 => 4066.88056722293 czardas

It should be made clear that: it is thanks to Manadar's insightful comments that I was able to improve on my first method.

Edited by czardas

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0