开发者

The best way to implement piece-wise periodic function in Objective-C?

开发者 https://www.devze.com 2023-02-18 22:50 出处:网络
I need to implement kind of illustrated function ( ratio = somefunction(time)) in Objective-c. Language doesn\'t actually matters, because task seems purely algorithmic. Is there any common way to d

The best way to implement piece-wise periodic function in Objective-C?

I need to implement kind of illustrated function ( ratio = somefunction(time)) in Objective-c. Language doesn't actually matters, because task seems purely algorithmic. Is there any common way to do things l开发者_StackOverflow社区ike this? Next things should be easily adjustable in process of design:

1) Number of small intervals per period (now it 4, but it can be 3 or 20 for example). 2) f1 can be changed. It's simple function like f(x) = sin(x). 3) if we say

    f_resulting = 
    f1 for a time t1 
    f2 for a time t2
   then again
    f1 for a time t1 
    etc..

ratio when f1 "works" vs f2 "works" (t1 to t2) should be adjustable.


Standard C itself has no closures so if you use C function pointers you need to build your own closure - you just use a class instance to store the two function pointers and duration and an invoke method to call the composed periodic function.

However Apple has introduced blocks, which are just inline functions implemented with closures, so in Apple C you can easily compose functions. This is more interesting, but "best" you will have to decide...

An example which composes double -> double functions. First the header, Periodic.h:

typedef double (^Monadic)(double);

Monadic makePeriodic(Monadic firstFunction, double firstPeriod,
                     Monadic secondFunction, double secondPeriod);

And the implementation, Periodic.c:

#include "Periodic.h"

Monadic makePeriodic(Monadic firstFunction, double firstPeriod,
                     Monadic secondFunction, double secondPeriod)
{
    return Block_copy(^(double time)
                      {
                          return fmod(time, firstPeriod+secondPeriod) < firstPeriod
                                 ? firstFunction(time)
                                 : secondFunction(time);
                      }
                     );
}

Blocks are constructed on the stack and can reference local variables and parameters in the enclosing scope. As such you cannot simply return a block from a function as the scope it refers to disappears on return. The function Block_copy() moves a block, and any blocks it refers to, onto the heap allowing them to outlive their creating scope. A heap block must be released with Block_release() when no longer needed.

And a simple demo:

Monadic queer = makePeriodic(^(double t) { return t * t; }, 5,
                             ^(double t) { return sqrt(t); }, 3);

for(double ix = 0; ix <= 16; ix++)
    printf("%f -> %f\n", ix, queer(ix));

Block_release(queer); // clean up

Now you can wrap all this up in a class if you wish so it fits Obj-C style. When you do this you can also send copy and release messages to the block, just as if it was an Obj-C object. In a garbage collected environment you still need the copy to get thge block onto the heap, but the release is not needed.

Periodic.h:

typedef double (^Monadic)(double);

@interface ComposeOne : NSObject
{
}

+ (Monadic) makePeriodicWithFunction:(Monadic)firstFunction
                           forPeriod:(double)firstPeriod
                         andFunction:(Monadic)secondFunction
                            forPeriod:(double)secondPeriod;

@end

Periodic.M:

@implementation ComposeOne

+ (Monadic) makePeriodicWithFunction:(Monadic)firstFunction
                           forPeriod:(double)firstPeriod
                         andFunction:(Monadic)secondFunction
                            forPeriod:(double)secondPeriod
{
    Monadic result = (^(double time)
                      {
                          return fmod(time, firstPeriod+secondPeriod) < firstPeriod
                                 ? firstFunction(time)
                                 : secondFunction(time);
                      }
                     );
return [result copy];
}

@end

And the simple demo (still using printf though for convenience):

Monadic queer = [ComposeOne makePeriodicWithFunction:^(double t) { return t * t; }
                                           forPeriod:5
                                         andFunction:^(double t) { return sqrt(t); }
                                           forPeriod:3];
for(double ix = 0; ix <= 16; ix++)
    printf("%f -> %f\n", ix, queer(ix));

[queer release];
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号