Math Functions

Discuss the future of the AutoHotkey language
User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Math Functions

20 Aug 2018, 15:49

Hello!
I would like the following functions to be added: Map, ATan2, Radians (degrees to radians), Degrees (radians to degrees), Factorial, Log(x,base=10), Hypot, ACosh, ASinh, ATanh, Cosh, Sinh, Tanh.
Constants: PI (also PI2?), E (_E?).

Here is an example using the Map function (AHKv1).
Original here: https://autohotkey.com/boards/viewtopic ... 20#p102945.

Code: Select all

#NoEnv
#Warn All, Off
#SingleInstance Force
SetBatchLines -1

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

global w   := 800
global h   := 600
global a   := 0
global b   := 0
global hue := 0

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

hSHLWAPI := DllCall("LoadLibrary", "Str", "shlwapi.dll", "Ptr")
hGDIPLUS := DllCall("LoadLibrary", "Str", "GdiPlus.dll", "Ptr")
VarSetCapacity(SI, 24, 0), Numput(1, SI, 0, "Int")
DllCall("GdiPlus.dll\GdiplusStartup", "UPtr*", pToken, "Ptr", &SI, "Ptr", 0)

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

Gui, +LastFound +hwndhGDIPFun
Gui, Show, w%w% h%h%

DllCall("GdiPlus.dll\GdipCreateFromHWND", "Ptr", hGDIPFun, "Ptr*", pGraphics)
DllCall("GdiPlus.dll\GdipCreateBitmapFromGraphics", "Int", w, "Int", h, "Ptr", pGraphics, "Ptr*", pBitmap)
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphicsCtxt)
DllCall("Gdiplus.dll\GdipSetSmoothingMode", "Ptr", pGraphicsCtxt, "Int", 2)
DllCall("Gdiplus.dll\GdipCreatePen1", "UInt", 0xFFFFFFFF, "Float", 1, "Int", 2, "Ptr*", pPen)
DllCall("GdiPlus.dll\GdipGraphicsClear", "Ptr", pGraphicsCtxt, "UInt", 0x7F000000)

loop
{
    DllCall("GdiPlus.dll\GdipSetPenColor", "Ptr", pPen, "UInt", "0xCC" ColorHLSToRGB(hue, 120, 240))
    , X0 := map( sin(a)    , -1, 1, W/5, W - W/5 )
    , Y0 := map( cos(a)*1.5, -1, 1, H/5, H - H/5 )
    , X1 := map( sin(b)    , -1, 1, W/5, W - W/5 )
    , Y1 := map( cos(b)    , -1, 1, H/5, H - H/5 )
    , DllCall("GdiPlus.dll\GdipDrawLine", "ptr", pGraphicsCtxt, "ptr", pPen, "float", x0, "float", y0, "float", x1, "float", y1)
    , a += 0.04, b += 0.05, hue += 1, hue := (hue > 239) ? mod(hue, 239) : hue
    , DllCall("Gdiplus.dll\GdipDrawImage", "Ptr", pGraphics, "Ptr", pBitmap, "Float", 0, "Float", 0)
} until (a > 24)
return

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

ColorHLSToRGB(hue, lum, sat)
{
    clr := DllCall("shlwapi.dll\ColorHLSToRGB", "UShort", hue, "UShort", lum, "UShort", sat)
    return Format("{:06X}", ((clr & 0xff00) | ((clr & 0xff) << 16) | ((clr & 0xff0000) >> 16)))
}

Map(Value, Start1, Stop1, Start2, Stop2, ConstrainMin := FALSE, ConstrainMax := FALSE)
{
    return ( ConstrainMin && Value < Start1 ) ? Start2 : ( ConstrainMax && Value > Stop1 ) ? Stop2
           : ( ( ( Value - Start1 ) / (Stop1 - Start1) ) * ( Stop2 - Start2 ) ) + Start2
}

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

GuiClose:
GuiEscape:
    DllCall("GdiPlus.dll\GdipDeletePen", "Ptr", pPen)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphicsCtxt)
    DllCall("Gdiplus.dll\GdipDisposeImage", "Ptr", pBitmap)
    DllCall("GdiPlus.dll\GdipDeleteGraphics", "Ptr", pGraphics)
    DllCall("GdiPlus.dll\GdiplusShutdown", "Ptr", pToken)
    DllCall("FreeLibrary", "Ptr", hGDIPLUS)
    DllCall("FreeLibrary", "Ptr", hSHLWAPI)
    ExitApp
return
I consider that these are the basic functions (and constants) that we should have built-in.
These functions are very useful when working with graphics (eg. gdip) and performance is important.
:wave:
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
guest3456
Posts: 2464
Joined: 09 Oct 2013, 10:31

Re: Math Functions

21 Aug 2018, 15:25

map() is a common name for a functional programming feature of applying a function to a range of values.

Code: Select all

arr := [1,2,3]
arr2 := map(arr, "square")
msgbox, % arr2.1 "`n" arr2.2 "`n" arr2.3
return

square(x)
{
   return (x*x)
}

map(array, function)
{
   if (function.name == "")
      function := Func(function)
   returnarray := []
   for i,v in array
      returnarray[i] := function.call(v)
   return returnarray
}
not sure what your map() func does but i'd recommend Naming it something different

User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: Math Functions

21 Aug 2018, 18:05

@guest3456 You're right, it should have a different name.
not sure what your map() func does: 1 ⠀⠀⠀2.
Another example:

Code: Select all

#NoEnv
#Warn All, Off
#SingleInstance Force
SetBatchLines -1
CoordMode Mouse, Client

hGDIPLUS := DllCall("LoadLibrary", "Str", "Gdiplus.dll", "Ptr")
VarSetCapacity(SI, 24, 0), Numput(1, SI, 0, "Int")
DllCall("Gdiplus.dll\GdiplusStartup", "UPtr*", pToken, "Ptr", &SI, "Ptr", 0)
w := 640, h := 360
Gui +LastFound +hwndhGui
Gui Show, w%w% h%h%

DllCall("GdiPlus.dll\GdipCreateFromHWND", "Ptr", hGui, "Ptr*", pGraphics)
DllCall("GdiPlus.dll\GdipCreateBitmapFromGraphics", "Int", w, "Int", h, "Ptr", pGraphics, "Ptr*", pBitmap)
DllCall("Gdiplus.dll\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphicsCtxt)
DllCall("Gdiplus.dll\GdipSetSmoothingMode", "Ptr", pGraphicsCtxt, "Int", 2)
DllCall("Gdiplus.dll\GdipCreateSolidFill", "UInt", 0, "UPtrP", pBrush, "UInt")
DllCall("GdiPlus.dll\GdipGraphicsClear", "Ptr", pGraphicsCtxt, "UInt", 0x7F000000)

loop
{
    MouseGetPos X, Y
    d := map(X, 0, W, 0, 250), c := (0xFF << 24) | (0xFF << 16) | (map(X, 0, W, 0, 175) << 8) | 0
    DllCall("Gdiplus.dll\GdipGraphicsClear", "Ptr", pGraphicsCtxt, "UInt", 0xFF000000)
    DllCall("Gdiplus.dll\GdipSetSolidFillColor", "UPtr", pBrush, "UInt", c, "UInt")
    FillStar(pGraphicsCtxt, pBrush, W/2, H/2, d/2, d)
    DllCall("Gdiplus.dll\GdipDrawImage", "Ptr", pGraphics, "Ptr", pBitmap, "Float", 0, "Float", 0)
}
return

Map(Value, Start1, Stop1, Start2, Stop2, ConstrainMin := FALSE, ConstrainMax := FALSE)
{
    return ( ConstrainMin && Value < Start1 ) ? Start2 : ( ConstrainMax && Value > Stop1 ) ? Stop2
           : ( ( ( Value - Start1 ) / (Stop1 - Start1) ) * ( Stop2 - Start2 ) ) + Start2
}

FillStar(G, Brush, X, Y, Radius1, Radius2, Points := 5)
{
    local PI2 := 2 * ACos(-1), Angle := PI2 / Points, HalfAngle := Angle/2.0, a := 0, a2 := 0, n := 0, buf := "", s := 0
    while ( a2 < PI2 )
        a2 += Angle, ++n
    VarSetCapacity(buf, s := 4 * (4 * n + 2))
    while ( a < PI2 )
        NumPut(X + cos(a) * Radius2, &buf + 16 * (A_Index - 1), "Float")
      , NumPut(Y + sin(a) * Radius2, &buf + 16 * (A_Index - 1) + 4, "Float")
      , NumPut(X + cos(a+HalfAngle) * Radius1, &buf + 16 * (A_Index - 1) + 8, "Float")
      , NumPut(Y + sin(a+HalfAngle) * Radius1, &buf + 16 * (A_Index - 1) + 12, "Float"), a += Angle
    NumPut(NumGet(&buf+0,"Float"), &buf+s-8, "Float"), NumPut(NumGet(&buf+4,"Float"), &buf+s-4, "Float")
    DllCall("Gdiplus.dll\GdipFillPolygon", "UPtr", G, "UPtr", Brush, "UPtr", &buf, "Int", 2*n+1, "Int", 0, "UInt")
}

GuiClose:
GuiEscape:
ExitApp
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
guest3456
Posts: 2464
Joined: 09 Oct 2013, 10:31

Re: Math Functions

21 Aug 2018, 23:06

Flipeador wrote:
not sure what your map() func does
: 1 ⠀⠀⠀2.
i get it now. seems like it scales a value from one range into the corresponding value in another range, right? if so i think scale() is the appropriate name

User avatar
nnnik
Posts: 3526
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Math Functions

21 Aug 2018, 23:59

Rad2Deg, Deg2Rad are better names for the conversions I think.
Recommends AHK Studio
User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: Math Functions

22 Aug 2018, 07:38

@nnnik I think that in this case it is not necessary, I would say that it is the obvious conversion. Also, IMO radians()/degrees() look better. :)
@guest3456 I was thinking something like maprange(), but scale() looks good. :thumbup:
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
User avatar
nnnik
Posts: 3526
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Math Functions

22 Aug 2018, 08:19

radians()/degrees() doesn't sound like its converting anything.
It seems like its creating a value of the type degree or radians - the source of their data is not mentioned.
Thats especially bad because there are multiple possible source types.

See: https://en.wikipedia.org/wiki/Angle#Units
Recommends AHK Studio
User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: Math Functions

22 Aug 2018, 08:35

AHK is not a specialized/optimized language to perform mathematical operations, we do not need all kinds of conversions. Here I am only proposing the most used/common. Creating a value of type degrees/radians does not make any sense to me.
https://docs.python.org/3/library/math.html | https://processing.org/tutorials/trig/
If lexikos plans to add several types of conversions, then we can take into account the name you propose.
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
User avatar
jeeswg
Posts: 5403
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Math Functions

22 Aug 2018, 10:11

- For situations like this, a list of function names for different programming languages would be useful. If anyone has any links. Unfortunately Rosetta Code does not appear to do this.
- Re. function names: I would use Fact instead of Factorial. Radians/Degrees are common names, or DegToRad/RadToDeg if people wanted. 'To' rather than '2' would probably be better for consistency, because you could end up with 'Utf82' instead of 'Utf8To' etc.
- Here are some degrees/radians solution ideas. Even Excel falls shorts re. degrees/radians in terms of being newbie-friendly, as AutoHotkey should always be. It's hard to remember when using Sin/ASin, whether to use Radians or Degrees, and which function is inside which. A potential source of needless bugs.

Code: Select all

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

;DEGREES/RADIANS

;PSEUDOCODE
;sin(30 degrees) = 0.5
;asin(0.5) = 30 degrees

;GOOD SOLUTIONS
;the real functions would lack the underscore: Sin(30, "d") or ASin(0.5, "d")
MsgBox, % _Sin(30, "d")
MsgBox, % _ASin(0.5, "d")

MsgBox, % SinDeg(30)
MsgBox, % ASinDeg(0.5)

;OTHER SOLUTIONS
MsgBox, % Sin(Radians(30)) ;same as Excel
MsgBox, % Degrees(ASin(0.5)) ;same as Excel

MsgBox, % Sin(DegToRad(30))
MsgBox, % RadToDeg(ASin(0.5))

MsgBox, % Sin(Deg2Rad(30))
MsgBox, % Rad2Deg(ASin(0.5))

PI := 4 * ATan(1)
MsgBox, % Sin(30 * (PI/180))
MsgBox, % ASin(0.5) * (180/PI)

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

RadToDeg(vRad)
{
	;d = r * (180/pi)
	return vRad * 57.29578
}
DegToRad(vDeg)
{
	;r = d * (pi/180)
	return vDeg * 0.01745329252
}

Rad2Deg(vRad)
{
	;d = r * (180/pi)
	return vRad * 57.29578
}
Deg2Rad(vDeg)
{
	;r = d * (pi/180)
	return vDeg * 0.01745329252
}

Degrees(vRad)
{
	;d = r * (180/pi)
	return vRad * 57.29578
}
Radians(vDeg)
{
	;r = d * (pi/180)
	return vDeg * 0.01745329252
}

_Sin(vAngle, vUnit:="")
{
	if (vUnit = "d")
		return Sin(vAngle * 0.01745329252)
	else
		return Sin(vAngle)
}
_ASin(vNum, vUnit:="")
{
	if (vUnit = "d")
		return ASin(vNum) * 57.29578
	else
		return ASin(vNum)
}

SinDeg(vAngle)
{
	return Sin(vAngle * 0.01745329252)
}
ASinDeg(vNum, vUnit:="")
{
	return ASin(vNum) * 57.29578
}

;==================================================
- I've written some potential code for ATan2 and Log, here:
C++: AHK source code: potential functions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 23&t=54392
Last edited by jeeswg on 22 Aug 2018, 13:09, edited 1 time in total.
User avatar
nnnik
Posts: 3526
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Math Functions

22 Aug 2018, 12:19

Limiting ourselves this early on in the development could really hinder us later on.
There are no good arguments for degrees and radians naming conventions.
Python actually forces its users to rewrite parts of their scripts with every minor update - in AHK we don't do that.
The development culture is different - therefore I wouldnt use Python as reference here.
Recommends AHK Studio
User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: Math Functions

22 Aug 2018, 13:48

As I mentioned, I doubt that so many conversion functions will be added, radians/degrees are common names, I do not believe that other conversion functions are necessary with respect to this, and I do not think that these names will limit us in the future. We do not have any function that uses that form (2, To) to name them. Anyway, it is better to use To instead of 2, as jeeswg says.
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
User avatar
jeeswg
Posts: 5403
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Math Functions

14 Sep 2018, 16:36

- Re. 'to', the String function checks for a ToString method, and so there might be an ObjToString function in future.

- A FloorMod function could be extremely useful as a built-in function.
- FloorMod(Dividend, Divisor): if the divisor is positive, the result is positive.
FloorDiv / FloorMod (and an 'always positive' Mod function) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=55751

- I had also thought that Combin/Permut functions (that can handle with/without repetitions) would be very useful. Familiar with Excel, I was surprised that they weren't in AutoHotkey when I first started using it.
- They are awkward because they commonly need numbers bigger than Int64 when doing the calculations, thus they would be a good candidates as built-in functions. Otherwise big number/infinite precision (numbers as strings) functions might be good as built-in functions.
- (Combin/Permut are not a personal priority of mine for the AHK v2 first release.)

- Links.
- For reference here are some mathematical functions from various languages/programs. I often feel that Excel is a great model for mathematical and date functions. (Although the date functions wouldn't have to be built-in IMO.)
- (I have tried to implement Combin/Permut/big int and all (I believe) of the Excel date functions in AutoHotkey, and have released or intend to release them at some point.)
<cmath> (math.h) - C++ Reference
http://www.cplusplus.com/reference/cmath/
Math (Java Platform SE 8 )
https://docs.oracle.com/javase/8/docs/a ... /Math.html
All Mathematical Functions Defined under Math Module in Python 3
https://www.programiz.com/python-progra ... dules/math
Excel Functions List
https://www.excelfunctions.net/excel-fu ... gFunctions
- Also:
[Feature Request] Add "Sign" function - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37&t=54044
iseahound
Posts: 354
Joined: 13 Aug 2016, 21:04
GitHub: iseahound

Re: Math Functions

18 Sep 2018, 19:48

No constants please. 2.7182... and 3.141592... lets the user choose the precision of the float, so some calculations can be performed faster if the user wants.

All trig functions should return radians. Conversion should be left to the user, (where the precision of PI is left to them)

gamma() which is like the factorial extended would be nice as well. Also +1 for inverse/hyperbolic trig functions.
User avatar
Flipeador
Posts: 1019
Joined: 15 Nov 2014, 21:31
GitHub: Flipeador
Location: Argentina
Contact:

Re: Math Functions

18 Sep 2018, 21:03

No constants please. 2.7182... and 3.141592... lets the user choose the precision of the float, so some calculations can be performed faster if the user wants.
Is this true in AHKv2?, Do you have any script that you want to show us that supports this?.
Anyway, I do not agree, I think lexikos must decide the precision, it does not need to be too much, or at least not for the use that will be given in AHK. 3.141592 seems ok.
I'm not sure where much precision is needed, but if that's the case, I do not think AHK is the right language for it anyway.
Windws 1♂ Pro 64-Bits I make scripts for AHKv2 (my v2 compiler) & WIN_7+ Spanish Argentina SublimeText 3 & AHKv2 My GDI+ Library
User avatar
nnnik
Posts: 3526
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Math Functions

19 Sep 2018, 00:37

I don't think that limiting AHKs capabilities like that from the start will end well.
Recommends AHK Studio
Helgef
Posts: 3295
Joined: 17 Jul 2016, 01:02
Contact:

Re: Math Functions

19 Sep 2018, 02:25

The number is a double anyways. Specifying a less accurate number will only make make the result less accurate, not one bit faster. Unless you take, eg, pi as 3, and only make calculations with integer and integer results.
User avatar
nnnik
Posts: 3526
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Math Functions

19 Sep 2018, 02:33

Calculating and storing the constant once at startup seems like a good idea though.
Recommends AHK Studio

Return to “AutoHotkey v2 Development”

Who is online

Users browsing this forum: No registered users and 4 guests