I’m trying to get some results from a few functions of Accelerate framework but I don’t know how to. So far, I’ve worked with the topics ‘vDSP’ and ‘vectLib’ trying with "current application’s " and simple call, like this script below:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use framework "Accelerate"
set someInitialVector to {1 / 4, 1 / 2, 3 / 4, 1, 5 / 4, 1 / 3}
set n to the count of someInitialVector
set aScalar to 4
set arrayInput to current application's NSArray's arrayWithArray:someInitialVector
set arrayOutput to current application's NSMutableArray's arrayWithCapacity:n
set arrayCount to current application's NSNumber's numberWithInt:n
-- vDSP
set scalar_vDSP to current application's NSNumber's numberWithFloat:aScalar
set arrayStrides_vDSP to current application's NSNumber's numberWithInt:n
try
get current application's vDSP_vsmul(arrayInput, arrayStrides_vDSP, scalar_vDSP, arrayOutput, arrayStrides_vDSP, arrayCount)
-- error "Il est impossible de poursuivre vDSP_vsmul." number -1708
on error
get vDSP_vsmul(arrayInput, arrayStrides_vDSP, scalar_vDSP, arrayOutput, arrayStrides_vDSP, arrayCount)
--*** -[BAGenericObjectNoDeleteOSAID vDSP:vsmul]: unrecognized selector sent to object <BAGenericObjectNoDeleteOSAID @0x6000004348c0: OSAID(2) ComponentInstance(0x83000a)>
end try
--vectLib
try
get current application's vvcospif(arrayOutput, arrayInput, arrayCount)
-- error "Il est impossible de poursuivre vvcospif." number -1708
on error
get vvcospif(arrayOutput, arrayInput, arrayCount)
--error "*** -[BAGenericObjectNoDeleteOSAID vvcospif]: unrecognized selector sent to object <BAGenericObjectNoDeleteOSAID @0x618000621060: OSAID(2) ComponentInstance(0x81000d)>" number -10 000
end try
Obviously, getting current application is not the way to go but I don’t know what to say about this unrecognized selector.
Any idea on how to get the correct result?
With vDSP, expected result is {1,2,3,4,5,4/3}
With vectLib --> {~0.71, 0, ~(-0.71), -1, (~-0.71), ~0.86}
You’re unlikely to be able to use much, if anything, in the Accelerate framework because the AppleScript scripting bridge doesn’t support most of the types its functions use.
Any workaround? Like using some kind of intermediate between the Bridge and the Accelerate framework that I could invoke to do and (then) undo these types? Or another method that can do trig, linear algebra, reversing matrices, matrice determinants calculations and long sums like computing a Taylor series ?
You might consider using JavaScript for Automation (JXA). It provides the same access to apps as AppleScript, and JavaScript has many libraries written for it.
Then, within an Applescript, I would run a javaScript containing a known function from either built-in or from math.js and retrieve the result for trig/exp/ln and matrice/array calculus (I would still need summation). However, I’d rather stay within Applescript and not having to add any module (math.js) with the script library that I wrote a few years back and I’d like to improve its speed (determinants and summations, mostly) as well as calculating reverse matrix.
So for now, I’ll keep this idea in mind if I don’t find what I’m looking for, that is, staying within AS & ASObjC. Thanks for the help.
The only thing I can think of is a new framework wrapping the calls you want in Objective-C that can be called from AppleScript. If it’s only a handful of things, that’s not too big an effort, but if you want access to a lot of stuff, it’s going to be a big project.
Have you looked at the scripting additions from Satimage?
I don’t think that will work. You can use an AppleScript Script Library from JXA, but NOT vise-versa. The only way I know of using JavaScript in an AppleScript is by using a Browser app.
You could write a JXA script library to just do the core math, and call that from an AppleScript.
EDIT: 2017-10-14 9:07 PM CT
Sorry, I had a brain fart when I posted that, which obviously conflicts with my above statement.
If the Satimage.osax (or other scripting additions that they offer) that @ShaneStanley suggested will provide what you need, then that is a good option. I’ve used it a lot with great success.
Well, it could be; I’m just starting to look into it. But considering where I’m at with Objective-C now, whether it’s a handful or not, it would still be a big project for me.
I did and I enjoy quite a bit the ‘evalFormula’ call. However, since I have shared this library already with people who are cold at the idea of adding stuff they don’t know much about, I removed it from this project early on stuck on the standard installation. I may come back to it or take the JavaScript route as proposed in another reply.
In the mean time, I’ll upgrade this library a bit here, a bit there with what is available with ASObjC.
That’s right! It does and even more. I don’t close the door on it (neither with your other suggestion); I will just look into a way to use ASObjc a bit more to improve this library before.
There are a couple of other ways. For fairly simple stuff, you can do this sort of thing:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "JavaScriptCore"
set theContext to current application's JSContext's new()
set theJSVaue to theContext's evaluateScript:"Math.tan(Math.PI/3)"
set theResult to theJSVaue's toObject() as real
To load a JXA script library and call a function, you can do this:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "OSAKit"
use scripting additions
try -- will fail because it's js
script "JSTest.scpt"
on error from jsLib -- jsLib will refer to lib
set jsLibPath to POSIX path of (jsLib as alias)
-- load the lib
set {myJSLib, theError} to current application's OSAScript's alloc()'s initWithContentsOfURL:(current application's |NSURL|'s fileURLWithPath:jsLibPath) |error|:(reference)
if myJSLib is missing value then error (theError's localizedDescription()) as text
end try
my callFunction:"doIt" withArgs:{2, 2} inJSLib:myJSLib
--> 4
on callFunction:funcName withArgs:argsList inJSLib:myJSLib
set {theResult, theError} to myJSLib's executeHandlerWithName:funcName arguments:argsList |error|:(reference)
if theResult is missing value then error (theError's localizedDescription()) as text
-- hack to convert from descriptor to correct AS class
return item 1 of ((current application's NSArray's arrayWithObject:theResult) as list)
end callFunction:withArgs:inJSLib:
But there’s obviously a bit of overhead in both of them.